Round trips and preservation
When a DOCX is read and written back, what is rebuilt from meaning, what is kept verbatim, and what is lost.
A round trip means reading a file with parseDocx, optionally changing the LitAST, and writing it back with generateDocx. generateDocx always rebuilds the whole package from LitAST rather than patching the original ZIP, so what can be written back depends on what the LitAST holds.
Three kinds of preservation
Rebuilt from meaning
Recognized content (paragraphs, text formatting, tables, images, headers and footers, fields, content controls, comments, tracked changes and more) becomes the matching nodes, and OOXML is generated again from those nodes on write. Change the nodes and the change appears in the output file.
Elements kept verbatim
Unrecognized elements become unknownBlock (block-level) or unknownInline (inline) nodes with their original structure stored in rawXml, and are written back unchanged. rawXml is an internal serialization, not an XML string; do not edit it by hand.
Passing preserveRawXml: false when parsing drops these elements. Equations (OMML) are always kept in their original structure inside math nodes, regardless of this option.
Parts kept verbatim
These parts are stored in ast.meta.rawXmlFiles and written back unchanged:
- Styles, numbering definitions, document settings, the font table and the theme
- Core and custom properties
- Comments, their extension parts and the comment people list
- Footnotes and endnotes
Chart source data (chart parts and embedded workbooks) is also kept and written back, but charts cannot be created or edited through LitAST.
Phonetic guides
ruby writes native w:ruby, with base text in children and annotation in attrs.rubyText.
Edited text or modeled properties use their current values. Unchanged ordinary run formatting,
unmodeled rubyPr properties and explicit zero/false values are kept in _rubyPreservation;
do not edit this internal source record. preserveRawXml: false does not disable it.
Content with relationships or range identities does not replay stale XML. A link around the whole ruby uses the shared relationship allocator; links inside either text layer violate the OOXML ruby content model and are rejected on export. Complete lifecycles for nested fields, comments and revisions remain unverified. Reopening, editing and saving were checked in Word 16.109.2; ordinary horizontal display was checked in WPS 12.1.28496. Other producers and complex combinations remain unverified; cross-producer fidelity is not guaranteed.
What is lost
The following are currently not kept through a round trip:
| Content | Notes |
|---|---|
| Building blocks (glossary) | Recorded in rawXmlFiles.glossaryXml when read, but not written back |
| Custom XML parts | Recorded in ast.meta.customXmlParts when read, but not written back |
| Any other part not listed above | Not copied into the output |
If your use case depends on any of these, check the output file after writing.
Saving LitAST
LitAST can be saved with JSON.stringify. After JSON.parse it can still be passed to generateDocx, and verbatim content is written back with it.