When the footnotes referenced on a page don't fit below its text, the note that doesn't fit is split at a line boundary: its first line stays on the page of its reference (if even that doesn't fit, the reference line moves to the next page, as before), and the rest continues at the top of the next page's note area, before that page's own notes, under a full-width continuation separator. Notes still continuing after the last page get pages of their own. Endnotes are unchanged. The docx reader doesn't keep a document's own continuation separator or continuation notice, so the default line is drawn and no notice. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Brandon Thomas <echelon@gmail.com>
7.0 KiB
Layout and pagination parity with Microsoft Word
Last reviewed: 2026-10-10 · Last updated: 2026-10-10 · Change: major (first version; line breaking, pagination and object placement checked against Word's behaviour from the layout source on origin/main) · Target: Microsoft Word (Microsoft 365) for Mac 16.113.4
A document only "opens correctly" if its pages break where Word breaks them: the same lines, the
same page count, footnotes and pictures on the same pages. This checklist covers line breaking,
pagination and object placement in crates/layout. Typing behaviour is in
typing-parity.md; the reading and writing of the properties is in
file-format-parity.md.
Dimension: ~55% (estimated), 90–145 h to full (the sum of the rows below). The engine implements most of Word's layout rules, but nothing has been compared page-for-page with Word on real documents, and the default font can't match Word's metrics.
Checklist
✅ matches Word as far as our tests show · 🟡 implemented, differs or untested against Word · ❌ missing
| Feature | State | Evidence / gap | Hours |
|---|---|---|---|
Line breaking (UAX #14 with Word's exceptions: no break after /) |
✅ | layout::tests::no_line_break_right_after_a_slash |
— |
| Justification, Word 2013+ space shrinking (compat mode 15) | ✅ | #109 | — |
| Kashida justification (Arabic) | ❌ | no kashida in crates/layout |
3–5 |
| Distributed / Thai distributed alignment | 🟡 | read; layout untested | 1–2 |
| Default font metrics (Aptos, Calibri, Cambria…) | 🟡 | Carlito/Caladea/Liberation are metric-compatible for Calibri/Cambria/Arial/Times/Courier; Aptos (Word's default since 2024) has no metric-compatible open substitute, so new Word documents wrap differently (typing-parity.md Known gaps). Needs an owner decision (commission or license a metric-matched font) | 6–10 + owner |
| Line spacing (single, 1.5, double, at least, exactly, multiple), spacing before/after, contextual spacing | 🟡 | Word puts multiple-spacing extra below the text and collapses spacing differently (#135, #108 open) | 3–5 |
| Widow/orphan control, keep with next, keep lines together, page break before | ✅ | lib.rs keep_next/keep_lines |
— |
| Tabs (left, center, right, decimal, bar), leaders | 🟡 | Bar tabs untested | 1–2 |
| Hyphenation (automatic, 0.25" zone, soft hyphens, consecutive limit) | 🟡 | English patterns only; other languages hyphenate wrongly or not at all | in localization |
| Drop caps | ✅ | 2026-10-06 | — |
| Columns, column breaks, separators | 🟡 | Columns don't balance at a continuous section break or document end | 4–6 |
| Section breaks (next page, continuous, even, odd), different first page, odd/even headers | ✅ | Section breaks don't show in Draft view (#42) | 1–2 |
| Body top below a tall header, footer pushes body up | ✅ | #138 | — |
| Footnotes at the page bottom, endnotes at the end, note numbering | 🟡 | A long note continues onto the next page at a line boundary (its first line stays with the reference), first in that page's note area under a full-width continuation separator (#352); the document's own w:continuationSeparator/w:continuationNotice aren't read (default line, no notice); per-section restart partial |
2–4 |
| Tables: row heights (at least/exact), rows split across pages, header rows repeat, Can't Split | ✅ | 2026-10-06, #138 | — |
| Tables: autofit to contents/window, fixed widths, Word 2013 edge | 🟡 | #137; #44: AutoFit Contents measures each column's narrowest and widest text and shares the width like Word, once (not live as you type); cell preferred widths and spans still differ | 3–5 |
Floating tables (w:tblpPr) |
🟡 | #137; overlap rules untested | 2–3 |
| Nested tables | 🟡 | render; polish missing | 2–4 |
| Floating pictures/shapes placement (relative to page/margin/column/paragraph/line/character) | ✅ | #136 | — |
| Text wrap: square, top-and-bottom, behind, in front | ✅ | 2026-10-06 | — |
| Text wrap: tight, through (contour, wrap polygon) | ❌ | laid out as square | 6–10 |
| Text boxes, overflow, linked text boxes | 🟡 | #46; linked text boxes missing | 3–5 |
| Rotated objects and text | 🟡 | #332: pictures, shapes, charts and groups drawn turned and flipped about their centre (screen and PDF); square wrap and inline lines keep clear of the rotated bounds; hit testing on the turned shape. Text in a rotated text box stays upright | 2–3 |
| Page borders (from page edge or text), page colour, watermark | ✅ | — | |
| Line numbers (restart per page/section, count by) | ✅ | — | |
| Vertical page alignment | ✅ | — | |
| Gutter, mirror margins, book fold, 2 pages per sheet | 🟡 | gutter and mirror margins; book fold missing | 2–3 |
Document grid (w:docGrid, lines per page, characters per line) |
❌ | East Asian documents paginate differently without it | 4–6 |
Vertical text (tbRl) in sections and text boxes; cell text direction |
🟡 | cell text direction landed (#245); page-level and text-box vertical text missing | 8–12 |
| Ruby / phonetic guide, enclose characters, combined characters | ❌ | 4–6 | |
| Bidirectional paragraphs, mixed-direction lines | 🟡 | #207; RTL sections and tables (w:bidiVisual) missing |
4–6 |
| Equations: display layout, numbering, wrapping long display equations | ✅ | #191; long display equations break at top-level operators (m:brkBin, m:brkBinSub), manual breaks and m:alnAt, continuation lines indented by m:wrapIndent or set right (m:wrapRight) (#326) |
— |
| Hidden text excluded from breaking and hyphenation | ✅ | #173 | — |
| Fields: PAGE, NUMPAGES, SECTIONPAGES, TOC page numbers | ✅ | #52 | — |
Compatibility modes (Word 2003/2007/2010 layout for old files: w:compat options) |
🟡 | mode 15 behaviour; the ~60 legacy compat options are mostly ignored | 10–20 |
| Page-by-page comparison harness against Word | ❌ | Run Word locally on our own synthetic documents, export PDF, compare line breaks; Word output stays under plan/ (never committed) |
8–12 |
Performance
| Measure | WordCraft | Word | Kind |
|---|---|---|---|
| Cold layout, 188-page document | 61 ms | not measured | measured 2026-10-06 (not re-run this pass) |
| Relayout after an edit | 1.4 ms | not measured | measured 2026-10-06 |
| Font picker with many installed fonts | fixed freezes (#233) | instant | issue #31, #59 |
| Large real-world documents (500+ pages, many pictures) | not measured | gap |
Revision history
| Date | Change | Summary |
|---|---|---|
| 2026-10-10 | trivial | Long footnotes continue onto the next page with a continuation separator (#352) |
| 2026-10-10 | trivial | Rotated and flipped objects laid out and drawn (#332) |
| 2026-10-10 | trivial | Long display equations wrap across lines (#326) |
| 2026-10-10 | trivial | AutoFit Contents measures the text (#44) |
| 2026-10-10 | major | First version: layout and pagination checklist with evidence from crates/layout, PRs and issues |