Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
bf4329c
First but not final pass at refactoring UI to use React.
methnen Mar 6, 2026
1dd3b34
Localization support.
methnen Mar 6, 2026
c5085c3
Some bug fixes and other tweaks.
methnen Mar 7, 2026
078f1a9
Tweaks to support third party libraries.
methnen Mar 7, 2026
e0165d9
Added Copy to clipboard button to shortcode input.
methnen Mar 7, 2026
0e72f31
Auto sizing number fields.
methnen Mar 9, 2026
98adcb4
Further parse class refactoring
methnen Mar 12, 2026
2b41c75
More changes to parsing and a complete rewrite of the Chart.js helper…
methnen Mar 13, 2026
f298590
Some code style tweaks.
methnen Mar 13, 2026
294fd24
comments
methnen Mar 13, 2026
8e74861
Small tweak to the block editor.
methnen Mar 13, 2026
84f8f1e
More style tweaks, some missing function comments
methnen Mar 14, 2026
8c92eb4
Fixes for the table stuff after moving things around.
methnen Mar 14, 2026
b395015
This isn't ready completely yet but need to commit it so I can more e…
methnen Mar 15, 2026
735ebbb
Added function to fix old block arguments.
methnen Mar 15, 2026
f3b494d
More block UI tweaks and some translation updates.
methnen Mar 17, 2026
f871b73
More block ui and translated stuff that I forgot to add.
methnen Mar 17, 2026
2815145
Getting a little closer on the translations
methnen Mar 17, 2026
cd1d566
Actually working translations, why is the WP translation stuff so fre…
methnen Mar 17, 2026
c7250cb
Working Netherlands translation
methnen Mar 17, 2026
e4b5fe0
English translation
methnen Mar 17, 2026
6bcc868
I had renamed the new admin code to admin-ui and some remnants of tha…
methnen Mar 18, 2026
50173bc
More tweaks/changes to the block ui as well some better comments
methnen Mar 19, 2026
21e8246
Misc
methnen Mar 20, 2026
8bae34e
First code review run finished up.
methnen Mar 21, 2026
57455ca
Translation updates.
methnen Mar 22, 2026
8240892
Fixed typo.
methnen Mar 22, 2026
8363558
Removal of some more old code now that all UIs will be React based an…
methnen Mar 25, 2026
03457c1
A couple of bug fixes
methnen Mar 27, 2026
c54baac
Forgot to include a .map file in the last commit.
methnen Mar 27, 2026
d92e700
Misc
methnen Mar 30, 2026
a08fa93
Readme updates.
methnen Mar 30, 2026
832b6b1
Screenshot updates.
methnen Mar 30, 2026
428db85
License updates.
methnen Mar 30, 2026
1d519f1
Readme updates.
methnen Mar 30, 2026
ccfee72
Typo fix.
methnen Mar 31, 2026
f65738e
Added some VuePress based documentation to replace the Wiki based docs.
methnen Apr 1, 2026
c27780a
Misc
methnen Apr 2, 2026
e2f831d
Chart.js helper comment tweaks.
methnen Apr 2, 2026
5e61fc9
More doc changes and tweaks.
methnen Apr 2, 2026
7553216
Including docs workflow.
methnen Apr 2, 2026
5592386
Few more style tweaks to docs.
methnen Apr 2, 2026
c4c7778
Yet more style tweaks.
methnen Apr 2, 2026
48fd830
A whole bunch of readme and doc improvement changes.
methnen Apr 3, 2026
7a0a339
Some performance tweaks.
methnen Apr 3, 2026
74c9526
React UI fix for adding new charts
methnen Apr 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .distignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
/components/sass
/config.rb
/deploy
/docs
/DEVELOPERS.md
/Gruntfile.js
/node_modules
Expand Down
55 changes: 55 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
name: Deploy Documentation

on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
pages: write
id-token: write

concurrency:
group: pages
cancel-in-progress: false

jobs:
build:
name: Build docs
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: npm

- name: Install dependencies
run: npm ci

- name: Build docs
run: npm run build:docs

- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/.vuepress/dist

deploy:
name: Deploy to GitHub Pages
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
6 changes: 5 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,8 @@ node_modules/
deploy/
build/
package-lock.json
.vscode/
.vscode/
.php-cs-fixer.cache
docs/.vuepress/dist
docs/.vuepress/.temp
docs/.vuepress/.cache
149 changes: 146 additions & 3 deletions DEVELOPERS.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
# Developer Instructions #

## Documentation ##

Full user and developer documentation is available at **https://methnen.github.io/m-chart/**. The developer section covers PHP hooks, JavaScript events, and the admin UI hooks API.

## Build Environment Install ##

`npm install`
```
npm install
```

> **Note:** `package.json` includes a `postinstall` script that runs `npm run build` automatically after `npm install` completes. This means a full build will fire on first install — this is expected.

## Build Commands ##

Expand All @@ -18,7 +26,7 @@ Build CSS only:
npm run build:css
```

Build JS (minify helpers):
Build JS (minifies `components/js/m-chart-chartjs-helper.js`):

```
npm run build:js
Expand All @@ -30,6 +38,12 @@ Build block only:
npm run build:block
```

Build admin React app only:

```
npm run build:admin-ui
```

Convert readme.txt to README.md:

```
Expand All @@ -38,14 +52,143 @@ npm run build:readme

## Watch Commands ##

Watch everything (CSS, JS, and block):
Watch everything (CSS, JS, block, admin app, and readme):

```
npm run watch
```

Individual watch targets are also available:

| Command | Watches |
|---------|---------|
| `npm run watch:admin-ui` | React admin app |
| `npm run watch:block` | Gutenberg block |
| `npm run watch:css` | SCSS → CSS |
| `npm run watch:js` | `m-chart-chartjs-helper.js` |
| `npm run watch:readme` | `readme.txt` → `README.md` |

## Translations (i18n) ##

PHP translations use `.po` / `.mo` files managed in Poedit. JavaScript translations require additional steps because `wp-scripts` bundles multiple source files into a single compiled file, and WordPress needs handle-named JSON files to load them.

All locale files (`.po`, `.mo`, `.l10n.php`) live in `components/languages/`.

### Workflow

1. Open the `.po` file for the locale you are updating (e.g. `components/languages/m-chart-zh_CN.po`) in Poedit.
2. **Catalog > Update from Sources** to scan for new/changed translatable strings in both PHP and JS source files.
3. Translate any new or updated strings.
4. Save in Poedit (this generates the `.mo` and `.l10n.php` files automatically).
5. Generate per-source-file JSON translation files:

```
wp i18n make-json components/languages/m-chart-zh_CN.po --no-purge
```

6. Merge the hash-based JSON files into handle-named files that WordPress can find:

```
npm run build:i18n
```

Repeat steps 1–6 for each locale.

### Why the merge step is needed

`wp i18n make-json` generates one JSON file per source file, named with the md5 hash of the source path (e.g. `components/admin-ui-src/components/AxisRows.js`). However, WordPress looks up translations using the md5 hash of the *compiled* file path (e.g. `components/admin-ui/index.js`). Since these hashes don't match, WordPress falls back to looking for `{domain}-{locale}-{handle}.json`. The `build:i18n` script merges the per-source-file JSONs into these handle-named files:

- `m-chart-{locale}-m-chart-admin-ui.json` — admin UI translations
- `m-chart-{locale}-m-chart-editor.json` — block editor translations

### Poedit configuration

Each `.po` file includes Poedit search path headers so that source scanning works correctly. These should exclude:

- `*.min.js` — minified files (duplicates of source)
- `node_modules` — third-party dependencies
- `components/external` — vendored libraries

If creating a new locale, copy these headers from an existing `.po` file (e.g. `m-chart-en_US.po`).

## Deployment ##

Deploy to WordPress.org via GitHub Actions:

Actions tab → "Deploy to WordPress.org" → "Run workflow"

Before triggering the workflow:
- Bump the version number in `m-chart.php`, `class-m-chart.php`, and `readme.txt`
- Run `npm run build` and commit all compiled assets
- Run `npm run build:readme` and commit the updated `README.md`
- Target the `main` branch when running the workflow

---

## Admin UI Architecture ##

The chart post-edit screen uses a React app (`components/admin-ui-src/`) compiled to `components/admin-ui/` by `@wordpress/scripts`. As of v2.0 the React admin UI is used for all charting libraries — the previous jQuery + Handlebars stack has been removed.

### Source layout

```
components/admin-ui-src/
index.js Entry point — mounts portals into each meta box div
context/
ChartAdminContext.js Single shared reducer (all components read/write here)
hooks/
useChartRefresh.js Debounced AJAX fetch for updated chart args
useFormSubmissionGuard.js Gates Save/Publish buttons on state.formEnabled; blocks
form submission while a chart refresh is in flight
useImageGeneration.js Captures Chart.js canvas → base64 PNG → hidden textarea
useLongPress.js 500ms pointer-event long-press (tab rename on mobile)
utils/
measureTextWidth.js Canvas-based text measurement utility
components/
ChartMetaBox.js Root for the Chart meta box (preview + settings)
ChartPreview.js Imperative Chart.js instance managed via refs
ChartSettings.js Settings form container
TypeAndThemeRow.js Type / Theme / Height inputs
ParseAndFlagsRow.js Parse direction, Labels, Legend, Shared tooltip
AxisRows.js Vertical/horizontal axis title + units, Y-min
ShortcodeAndImageRow.js Shortcode display, image URL, library hidden input
SpreadsheetMetaBox.js Root for the Data meta box
SheetTabs.js Tab bar (conditionally shown for multi-sheet types)
SheetTab.js Individual tab — click/dblclick/long-press rename, delete
JspreadsheetWrapper.js Thin imperative wrapper around a Jspreadsheet worksheet
CsvControls.js CSV import (fetch + FormData) and export (temp form POST)
SubtitleField.js Controlled subtitle input (replaces subtitle-field.php)
```

### Data flow

1. PHP localises initial state into `window.m_chart_admin` via `wp_localize_script` (see `current_screen()` in `class-m-chart-admin.php`). The object contains: plugin metadata (`slug`, `version`), settings (`performance`, `image_support`, `image_multiplier`, etc.), the active `library`, chart post meta, spreadsheet data, available chart types and themes, a nonce, the AJAX URL, and initial chart args.
2. `ChartAdminContext` seeds a `useReducer` from that object — all components share one context.
3. User changes (settings, spreadsheet, title, subtitle) update context state.
4. `useChartRefresh` debounces 300 ms then POSTs to `admin-ajax.php?action=m_chart_get_chart_args`.
5. The response updates `chartArgs` in context; `ChartPreview` patches its Chart.js instance.
6. On form submit, `SpreadsheetMetaBox` serialises all sheet data to the hidden `textarea[name="m-chart[data]"]`.

### Mount points (PHP)

| PHP method | Mount div | Component |
|---|---|---|
| `edit_form_before_permalink()` | `#m-chart-subtitle-root` | `<SubtitleField />` |
| `spreadsheet_meta_box()` | `#m-chart-spreadsheet-root` | `<SpreadsheetMetaBox />` |
| `chart_meta_box()` | `#m-chart-chart-root` | `<ChartMetaBox />` |

All three share a single `ChartAdminProvider` rendered into a hidden container appended to `<form id="post">`, with portals projecting into each mount div.

### Library plugins

Library plugins (e.g. M Chart Highcharts Library) integrate with the React admin UI via the `wp.hooks` API:

- **`m_chart_admin_scripts` action** — enqueue library-specific scripts after M Chart's scripts are loaded
- **`m_chart.render_chart` filter** — handle chart rendering in the admin preview, returning `true` to prevent the default Chart.js renderer from running
- **`m_chart.settings_component` filter** — replace the default Chart.js settings UI with a library-specific React component

See `version-2-notes.md` for the full list of available hooks.

### Extensibility (wp.hooks)

See `version-2-notes.md` for the full list of JavaScript hooks available to library plugin authors.
8 changes: 2 additions & 6 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2015-2021 Jamie Poitra
Copyright (c) 2015-2026 Jamie Poitra

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -21,11 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

License info for libraries found in `components/external`:
- [canvg](https://github.com/gabelerner/canvg/)
- License at the time of writing: MIT
- [handlebars](https://github.com/wycats/handlebars.js/)
- License at the time of writing: MIT
- [handsontable](https://github.com/handsontable/handsontable)
- [Jspreadsheet CE](https://github.com/jspreadsheet/ce)
- License at the time of writing: MIT
- [Chart.js](https://github.com/chartjs/Chart.js)
- License at the time of writing: MIT
Expand Down
Loading