| Headings, lists, bold and italic, and tables convert from a python-docx file | Covered by a test | superdocuments/tests/office_real.rs (docx_structure_comes_from_styles_numbering_and_tables); fixture tests/fixtures/office/basic.docx | Ran 2026-11-08, passing. Title and Heading 1 and 2 give '#', '#' and '##'; 'List Bullet' and 'List Number' give '- ' and '1. ' through numbering.xml; a cell with a pipe and a soft break gives 'Value \| pipe' and 'Line one<br>Line two'. |
| Links with targets, a footnote, a nested list and a merged cell convert from a LibreOffice file | Covered by a test | superdocuments/tests/office_real.rs (libreoffice_docx_keeps_links_footnotes_nested_lists_and_merged_cells); fixture tests/fixtures/office/rich.docx | Ran 2026-11-08, passing. The fixture was written by LibreOffice 'soffice --convert-to docx' from a flat ODT, so its footnote ids and style ids are LibreOffice's, not hand-picked. |
| Entity references (& < >) in text survive in DOCX | Covered by a test | superdocuments/tests/office_real.rs (entity_references_are_kept_in_every_xml_format) | Ran 2026-11-08, passing. Before commit 44241df every XML reader here dropped the character an entity reference stands for. |
| Any namespace prefix reads; outline level; tracked deletions; alternate content; nested tables; gridSpan and vMerge; HYPERLINK fields; w:b val=0; Title without a styles part | Covered by a test | superdocuments/src/ooxml/docx.rs (module tests) | Ran 2026-11-08, 9 tests passing. They use XML built by hand in the test, not a file from Word. |
| A heading is decided by outline level or style name along the basedOn chain, capped at six | Read from the code | superdocuments/src/ooxml/docx.rs (Styles::heading_level, name_level) | A direct outlineLvl wins; level 9 gives body text; Title is depth one. |
| A bullet level gives '- ', other formats give a counted '1.', format none gives plain text | Read from the code | superdocuments/src/ooxml/docx.rs (Numbering::is_bullet, Parser::finish_paragraph) | The count restarts when a shallower level of the same list appears. |
| Only the Choice half of mc:AlternateContent is read | Read from the code | superdocuments/src/ooxml/docx.rs (Parser::start, skip counter) | Fallback and the property-change records are skipped with the same counter. |
| convert_streaming and the cache use the same DOCX reader as convert_bytes | Read from the code | superdocuments/src/document.rs (convert_streaming fallback arm; DocFormat::is_streaming) | The earlier write_docx_streaming, lift_docx and render_docx were deleted. The equality test convert_streaming_matches_convert_bytes_for_csv_docx_xlsx still passes. |
| ZIP bounds: 4,096 entries, 32 MiB per declared entry, 128 MiB declared total | Read from the code | superdocuments/src/document.rs (archive, entry) | Unchanged by the rewrite. |
| A relationship target is resolved inside the package; one that leaves it is refused | Covered by a test | superdocuments/src/ooxml/mod.rs (resolve_joins_against_the_holding_part_and_stays_inside) | Ran 2026-11-08, passing. |
| Routing: the Webfold command line sends docx and docm to the superdocuments conversion | Read from the code | webfold/src/cli/document.rs:130-140 | markdown_source lists docx and docm in the document branch and calls webfold::document::convert_path, which uses the superdocuments revision Webfold pins (68c216f). |
| Webfold converts mixed office and ebook fixtures in about 27.7 microseconds median on one document when warm and in process | Measured | /benchmarks/documents/ ; webfold-bench/bench/results/document-rust-cold-hot-2026-09-24.json | 45 public fixtures across formats, uncached, measured with the older readers. The new readers have not been benchmarked, and the figure is not a DOCX number. From a fresh process the median is 2.77 ms. Measured with the older readers; the new ones have not been benchmarked. |