Skip to content

fix(export): draw exports with the static kit and write Word math - #5157

Merged
zbeyens merged 20 commits into
nextfrom
export-static-presentation
Oct 11, 2026
Merged

zbeyens merged 20 commits into
nextfrom
export-static-presentation

Conversation

@natamox

@natamox natamox commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator
  • Auto release

Plan: docs/plans/2026-10-09-html-static-repair-redo.md, built through its iterations presentation context, export finishing, Word owns Word and static kit drift.

Why

Exporting a document with a table, image, task list or other interactive block crashed, because export drew each block with its editing component. Word output also carried its own hidden theme, wrote equations as LaTeX text and drew task checkboxes as buttons.

What changed

  • renderStaticHtml and exportDocx take presentation, a static plugin array that draws each node by plugin name. The registry export toolbar passes BaseEditorKit. Meaning and settings still come from the live editor.
  • Word export writes equations as Word math and tasks as ☑ or ☐ list items, and leaves colors and fonts to the app's stylesheet. Word import reads Word math back as equations.
  • The export menu shows an error when an export throws, Copilot's ghost text no longer makes strict Word export refuse the file, and the static indent and list kits accept images.

Scope

  • Covers phases 1 to 3 of the plan. Freezing settings for the length of an export, the authored redesign's Word revisions and comment mapping, and the registry's unused *ElementDocx drawings stay open in the plans' Open work.
  • No Word install was available, so how Word draws the equations and the ☑ and ☐ markers is not checked.
  • Of the added lines, about 1,750 are package and registry code, 2,100 are tests and 2,100 are plans and decision logs under docs/plans. The JSON under apps/www/public/r and apps/www/src/__registry__ is generated.

Tradeoffs

  • presentation reuses the app's static kit. An architect bakeoff rejected a second export editor and a component map.

Blast Radius

Every exportDocx caller gets the new Word output: equations become Word math, and callouts and code blocks draw without built-in colors or fonts unless the stylesheet sets them, as the registry's DOCX_EXPORT_STYLES does. Apps that copied the registry's export toolbar, block-list-static, docx-export, indent-static or list-static get the fixes on their next registry update.

Verification

  • Chromium on /blocks/docx-demo through the real toolbar exports HTML, Word and Word with tracked changes for tables, tasks, callouts, columns, code blocks, images and equations, and the Word file imports back with its equations; the docx browser spec passes 4 of 4.
  • CI fails the same 7 of 25 pnpm check steps as next's own CI at 666f02406e, and the same 6 Plite Chromium specs as next's last Plite CI run, whose Plite inputs match 666f02406e. The Registry job's template lint fails with the same 45 errors at 666f02406e and on this branch. None of these failures is in a file this branch changes, and the moving 5,000 ms test timeouts pass locally. CI's www step stops at a missing plate bin. Locally at the branch head, pnpm check www passes with its fresh-registry and docs parity checks and the production build, as do the static, Word export, Word import and AI React partitions and the slow Word suites. The CI triage is in the babysit plan.
  • A three-model panel reviewed each iteration and then this branch in two rounds. The branch round found a display equation in a Word list item losing its list on import and props: { editor: undefined } throwing; both are fixed with tests that fail before the fix.

🤖 Generated with Claude Code

natamox and others added 9 commits October 10, 2026 10:06
The export toolbar passed the live editor to renderStaticHtml and exportDocx,
so static dispatch drew each block with its editing component, and tables,
images, task lists and other interactive blocks crashed HTML and Word export.
Both functions take a `presentation` static plugin array. Each installed
plugin's element, mark and function slot drawing comes from the presentation
plugin of the same name. The live editor still supplies the document, the
projection and the settings. A plugin with no static drawing draws plain and
reports missing-static-presentation, which Word counts as lost content. The
registry export toolbar passes BaseEditorKit.

renderStaticHtml's props option rejects editor and document, because either
could replace the exported document. Word export takes a nested list's level
from its host block's indent. The static list wrapper drops its own margin,
which indented HTML lists twice. Word export also decodes quoted inline styles
before inlining the stylesheet, so a callout under a matching rule exports.

Two review findings stay open in the plan. The fallback element path still
runs live afterNodeChildren slots under a presentation, and a drawing created
in a configure((ctx) => ...) callback reads the presentation's own state.

Plan: docs/plans/2026-10-09-html-static-repair-redo.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The full check flagged files from the presentation commit. The image fixture
now uses its schema type, and the configure-context test draws a slot, because
the schema adoption audit allows only slots, render and the other explicit keys
in a contextual configure. The lint baseline drops the old StaticHtmlDiagnostic
alias, platejs turbo.json picks up the partitions the new docx specs import, and
the superseded draft plan names tracked source files as its review inputs.

Plan: docs/plans/2026-10-09-html-static-repair-redo.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…from it

compilePeers compiled a renderStaticHtml or exportDocx presentation with
buildEditor, which activated its plugins and left them running. It now uses
withPlateFormatCompilation, so nothing activates and the temporary runtime
rolls back. A drawing created in a configure callback that calls its context
while drawing throws, which rejects the export.

With a presentation, an element no plugin renders, such as a type a complete
editor schema declares, now draws its afterNodeChildren slots from the
presentation instead of running the live editor's. An installed
afterNodeChildren component, React.memo included, that the presentation has no
function for is reported as missing-static-presentation instead of vanishing.
Without a presentation, output is unchanged.

One case stays open. A callback-built drawing that copies plain context values
before its callback returns draws the presentation's own configuration without
an error. The JSDoc and the static guide call such drawings unsupported.

Plan: docs/plans/2026-10-10-html-presentation-context.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The registry export menu awaited renderStaticHtml and exportDocx without
catching, so an export that threw downloaded nothing and showed nothing. Each
of the HTML and Word items now catches the error, logs it and shows an error
toast.

CopilotPlugin's ghost-text slot had no static drawing and was not edit-only,
so an export with a presentation reported it as missing-static-presentation,
and exportDocx's default loss policy refused the file. CopilotPlugin now sets
editOnly: { on: false }. Exports skip its slots, and its DOM handlers still run
in read-only mode, so live editing is unchanged.

A component that throws during Word export still rejects the export, as the
static guide says. The export menu now reports it.

Plan: docs/plans/2026-10-10-html-export-finishing.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Word export wrote each equation as its TeX source, drew task items as a
button beside their text, and baked its own colors and fonts into
callouts and code blocks, so the app's stylesheet never reached the file.
exportDocx now builds Word math from KaTeX's MathML and keeps the TeX
inside a Word equation where Word math cannot express it. importDocx
reads Word math back as equation and inlineEquation nodes. Task items
export as one paragraph with a checked or unchecked box marker. The Word
components draw structure only, and the copied docx-export stylesheet
holds the look. List numbering lives on each document, so concurrent
exports keep their own, and passing stylesheet or fontFamily rebuilds an
unchanged imported file.

Plan: docs/plans/2026-10-10-html-word-owns-word.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The live IndentKit and ListKit let a user indent an image or put it in a
list, but the static kits did not target images, and the static editor's
closed schema refused any document that held one. The server HTML block,
the AI command route and the AI preview then threw on that document.
Both static kits now target images, so the static editor loads the
document and draws the image as a list item at its indent.

Plan: docs/plans/2026-10-10-html-static-kit-drift.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
materializeEquations replaced any paragraph whose only content was a
display equation with a block equation node. A Word list item or an
indented paragraph built that way lost its listType and indent, the
items after it renumbered, and strict import reported no loss. Such a
paragraph now stays, and its equation imports inline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…props

The props type forbids editor and document with optional never fields,
which still admit an explicit undefined, but the guard threw on any own
key. renderStaticHtml now throws only when either holds a value.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The redo plan's Close records the two-round panel on the branch diff,
the check steps that also fail on next, and the owner's call to open
the pull request. The static kit plan names its review inputs, as the
review ledger requires.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@natamox
natamox requested a review from a team October 10, 2026 13:38
@codesandbox

codesandbox Bot commented Oct 10, 2026

Copy link
Copy Markdown

Review or Edit in CodeSandbox

Open the branch in Web Editor • VS Code • Insiders

Open Preview

@changeset-bot

changeset-bot Bot commented Oct 10, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f8a6d34

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
platejs Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

natamox and others added 11 commits October 10, 2026 23:38
The docx guide and the changeset said an equation exports its TeX when
Word math cannot express the notation. The fallback covers notation this
converter does not handle, such as a matrix, which Word math can express.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…flect

The html subject file now describes the branch's export: the static kit
as presentation, the detached compile, the export error toast and the
static kits' image targets, with the plans' remaining open work. The
Word plan's Close gains the decision-trail review its first close
skipped, with its narrowed claims, and the redo plan records the session
reflect and its backlog.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The review ledger needs every review_inputs path in a tree or commit. The
Word plan listed nine probe logs from its author's ignored run directory,
so review-ledger passed on that machine and failed in CI. The plan now names
the six tracked specs that hold its tests, and its Close names them too.
The Close also lists the revision-diagnostic deviation its first close
missed.
exportDocx drew the body and each comment body through two near-copies
that built the same static HTML options and returned diagnostics in two
shapes. One renderDocxHtml now renders either document, exportDocx applies
the review projection to the body, and missingDrawings reads the render
results. Output is unchanged.
The marker codec's parse regex matches only comment and revision markers,
but Marker['kind'] also listed three equation kinds, so its cast admitted
kinds parse never returns. The codec now builds the three equation tokens
once as codec.equation, which instrumentWordMath and materializeEquations
read.
U+2061 and the combining accents in the Word math converters and their
shared vocabulary read as empty strings in review. Each is now written as
a Unicode escape with the same value.
The PR's code-quality review found that lists inside callouts and columns
likely restart their numbering, that Word math import hardcodes plugin
types and list keys, and that text-only Word math reports Mammoth's
diagnostic code. Each is listed in the documents subject's Open work with
its owner and stop.
The babysit plan records the CI triage against next's own runs, the
repair of the branch's one own CI failure, the code-quality review's
findings and how each was settled, and the merge frontier. Its decision
log holds each call with its proof.
A Codex reviewer checked the babysit's decision log against its
transcript. The Close now says the red checks are next's by CI evidence
only, that the full www check passes locally with its production build,
and how each review warning was settled. A numbered list after a plain
paragraph joins the Word list numbering item in the documents subject's
Open work.
The owner moved the review-ledger checker fix into the session that started the babysit, so the plan's default names that session instead of a proposed task.
# Conflicts:
#	apps/www/public/r/block-list-static.json
#	apps/www/public/r/docx-docs.json
#	apps/www/public/r/registry-docs.json
#	apps/www/public/r/registry.json
#	apps/www/src/__registry__/generation.json
#	apps/www/src/__registry__/index.tsx
#	apps/www/src/__registry__/overlays/manifest.json
#	apps/www/src/__registry__/registry-metadata.json
#	apps/www/src/registry/changelog/components.json
#	apps/www/src/registry/changelog/index.json
#	apps/www/src/registry/components/editor/block-list-static.tsx
#	docs/plans/topics/documents.md
#	packages/platejs/src/docx/export/lib/exportDocx.tsx
#	packages/platejs/src/docx/export/lib/internal/docx-document.ts
#	packages/platejs/src/docx/export/lib/internal/render-document-file.ts
#	packages/platejs/src/docx/export/lib/internal/xml-builder.ts
#	packages/platejs/src/docx/import/lib/importDocx.ts
@zbeyens
zbeyens merged commit 5fc246c into next Oct 11, 2026
5 of 7 checks passed
@zbeyens
zbeyens deleted the export-static-presentation branch October 11, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants