Saving edits
- The host listens to Univer’s
CommandExecutedevent and reacts only to mutations of this workbook:typeisMUTATION, the mutation is notonlyLocal(formula calculation), andparams.unitIdis the workbook’s id. The cell editor is a separate internal Univer document that mutates on every keystroke; without the unit check the post was marked dirty as soon as it opened. - Changes are debounced (400 ms), then the edit component compares the snapshot’s JSON with the last one it saw and only then calls
setAttributes( { workbook } ). WordPress’s own Save, autosave and revisions take it from there. - When the attribute changes from outside the grid (editor undo, a restored revision, a collaborator’s save) the grid reloads from it.
Collaboration
The block editor’s real-time collaboration syncs the whole workbook as one attribute, so two people editing different cells at the same moment overwrite each other: the last change wins for the whole workbook. Presence, title, status and terms sync normally. Cell-level co-editing needs Univer’s mutations mapped onto the editor’s Yjs document (planned).
REST API
Namespace lh/v1, base spreadsheets (filters lh_spreadsheets_rest_return_namespace, lh_spreadsheets_rest_return_rest_base). GET lists up to 50 (own only without edit_others_posts), POST creates, and GET, PUT and DELETE on /{id} read, patch and delete. Writes take title, description, status and workbook (an object); the API wraps the workbook in the block itself. Publishing without publish_posts is demoted to pending. Core’s wp/v2/spreadsheets route also exists, returning the raw block markup.
Building
Source is in src/; build/ is generated with npm install then npm run build and deployed as is (nothing is built on the server). webpack.config.js runs two builds: the block with WordPress packages as externals, and the Univer host with everything bundled. Univer is pinned to an exact version in package.json; upgrade it deliberately and retest, since its API has moved between releases.
Roadmap
- Cell-level collaboration over the block editor’s Yjs transport.
- A Grist-compatible API adapter.