Architecture
How the editor renders DOCX with Word fidelity: one canonical OOXML tree, a DOM-free layout pass, and painted pages that are themselves the editable surface.
There is one document model and one pipeline:
bytes → bounded OPC/XML read → canonical OOXML tree → layout → painted pages → serializeWhat you see painted and what an edit mutates are the same tree, so nothing has to be kept in sync.
The canonical tree
Reading a .docx produces one tree per package part. Nodes are typed where layout needs them (the paragraph, run, and table vocabulary) and generic everywhere else, preserving the element verbatim.
Two consequences:
- Content the engine does not model is carried, not dropped. A known element in an invalid position demotes to generic rather than erroring.
- Unknown content never blocks editing. A document full of extensions the engine has never seen still opens, still edits, and still saves.
Every write is a transaction over the tree, addressed by node id and character offset. That is the only write path. There is no second way to mutate a document, so undo, the editing API, and every command go through the same door.
Layout
The layout pass is DOM-free. It takes the tree and a text measurer and returns positioned pages, working in the document's own units (twips, half-points, EMUs) rather than approximating from browser layout.
Because it is not constrained by what contenteditable can express, it lays text out the way Word does:
- Pagination is computed, not approximated: lines are measured, blocks split where Word splits them, and tables fragment across page boundaries with the right border treatment at the cut.
- Paragraph fidelity resolves through the real style cascade:
w:spacingline rules, first-line and hanging indents,w:contextualSpacing, paragraph borders, tab stops and leaders, list markers fromnumbering.xml, and table styles through theirbasedOnchain gated byw:tblLook. - Headers and footers lay out once per variant and attach per page. Editing one behaves exactly like editing the body.
The pass is incremental: per-block cache keys and flow checkpoints mean a keystroke re-lays out what changed, and a pass with no changes returns the previous pages by identity.
Paint and interaction
The painted pages are contenteditable, but the DOM is a picture. Browser mutations are prevented and re-expressed as tree operations, so the browser never gets to invent markup inside your document.
The editor also paints its own caret, from layout geometry rather than from the DOM, which is why an empty paragraph gets a caret at all. It fails soft: range selection, IME composition, or a position it cannot place all hand the native caret back rather than leaving none.
Selection maps through paragraph identity and offsets, never through DOM traversal. Page furniture (headers, footers, page numbers) is marked non-editable and excluded from selection.
Saving
Every parsed XML part is re-emitted from the canonical tree with structural fidelity, including custom XML and unknown extensions. Package payloads such as embedded fonts, media, and VBA binaries pass through untouched.
That is what "structural fidelity" means here: unsupported XML and package payloads survive editing and save without loss. Two oracles gate it in CI: a canonical fingerprint over the tree, and a save-and-reopen semantic digest.
Adapters
@docx-editor.dev/core contains everything above and no framework code. An adapter supplies DOM and paints the engine's positioned display list; it holds no editing state of its own. @docx-editor.dev/react is one such adapter, and it is thin by design. Every control it ships is a consumer of the same public contract your own controls would use.
Next steps
- Core package overview: entry points and the
Editorcontract - Word fidelity: what the fidelity claim covers, and its limits
- Composition: building on the adapter
@docx-editor.dev/core
The framework-agnostic engine: OOXML read and write, the canonical document tree, layout, paint, and the Editor contract that adapters render.
@docx-editor.dev/i18n
Locale data for the editor chrome. Ships ten languages: English, Polish, German, French, Portuguese, Hebrew, Hindi, Indonesian, Turkish, and Chinese.