textBox becomes an inline node carrying block content, like the frame both
formats write, so "in line with text" really is in the line and a box reaches
a table cell or a list item through their paragraphs. Both exports write it
where it sits (an as-char draw:frame / a wp:inline drawing) and both imports
leave it there, which drops the hoisting machinery on either side.
Two guards the schema cannot express: no box inside a box, and a selection
reaching into a box grows to the box's bounds rather than dissolving it.
The generator assigns a builtin (node species following the style's
level kinds, override-, start- and marker-format-free — each of those
drops the name by design) and no longer pairs textAlign right with an
rtl paragraph, where it is the suppressed default. Found the w:jc
suppression fix the commit before this one.
An inline atom drawn gray as ‹label›: a click selects the whole field,
typing replaces it, Tab/Shift-Tab jump between fields. Exports to ODF
<text:placeholder> (PLH sentinel U+E022) and a DOCX w:sdt content
control tagged edentext-placeholder; both importers read it back, the
export-minted gray stripped. Covered in roundtrip Leg 31 + fuzzDoc.
styledTable now materializes the region attr (paintTable's shape), keeps
runs heading-safe only in bold regions, and layers direct overrides over
the paint: replaced or cleared cell shading and an own bottom border.
The generator now emits tableOfContents nodes of all five families, styled
tables painted through the real resolveTableCell (name + look + materialized
fill/borders), side-by-side topBottom image pairs (wrapAlign), vertical-text
boxes and the Caption paragraph style. normalize learns the index attr
defaults the DOCX TOC field has no switch for.
The generator now emits columns sections, Title/Subtitle/Quotations
paragraphs (heading-safe runs), floating text boxes with offsets, and
table margins, cell borders, cell padding and formula cells.
Generator gains insertion/deletion marks, sequence/index/date-time fields,
citations (one record per identifier), builtin character styles (redundant
direct marks dropped — import suppresses them like heading defaults) and
floating images (wrapDist only beside a side wrap). normalize canonicalizes
revision ids/dates like comments, recounts sequence numbers per category,
and drops an auto date field's value and a citation's derived label.
Generator: text boxes (shape, fill, stroke), inline and display
formulas, comments, bookmarks with cross-references, ruby, rowspan
merges. Display rides a formula owning its line; a stroke width needs
a stroke color; a vertical merge keeps a second column so no row is
all covered cells. Normalize canonicalizes comment ids and dates
(naive local vs UTC are one instant) and trims a formula's latex
(the OMML side keeps the serializer's trailing space on purpose).
New in the pool: paragraph shading/rule lines (also in cells and lists), rtl
paragraphs, keepNext/keepLines/widowControl, tab stops, custom bullet chars,
heading levels to 8, image alt/rotation, row heights and custom note labels.
noHyphenation stays out: without the document-wide hyphenate flag the
importers suppress it as meaningless. 1000 sweep seeds clean on both legs.
colspan merges (grid-consistent), orderedList listStyleType (upper-* only on
nested lists: lower/decimal forms are depth defaults the importers suppress),
and inline PNG images. 300 sweep seeds clean on both legs.
New in the pool: underline/strike line styles, super/subscript, caps,
textPosition, links, page breaks, footnotes/endnotes, cell shading and
vertical alignment. normalize() canonicalizes importer-generated note ids and
drops the link mark's default plain:false; FUZZ_SEEDS widens the sweep beyond
the default 50. This is the suite that surfaced the last four export/import
fixes; all 300 sweep seeds now round-trip clean on both legs.
tests/fuzzDoc.ts generates documents from a seeded PRNG (marks, lists,
tables, indents, XML-hostile text); fuzz-roundtrip.test.ts runs 50 seeds
through buildOdt -> importOdt and diffs the normalized JSON, naming the
failing seed. normalize/firstDiff moved out of roundtrip.test.ts into
tests/normalize.ts for reuse. The generator documents what is lossy by
design: default-equal marks in headings, indents and start in nested lists.