Files
wordcraft/docs/layout-parity.md
T
6526b134be Document grid: lines per page and characters per line (#391) (#401)
- Model: `SectionProps::doc_grid` (`w:docGrid` type, line pitch, charSpace) and the
  paragraph `w:snapToGrid` flag; DOCX read and write (ECMA-376 §17.6.5).
- Layout: with a line grid, lines of snapping paragraphs take whole line pitches with
  their text centred; with a character grid, East Asian characters take whole cells of
  the character pitch (all text with snapToChars), Latin text stays proportional.
  Hostile pitches and charSpace are clamped. Headers and footers don't snap.
- Command `layout.documentGrid` (type, linesPerPage, charsPerLine, linePitch,
  charSpace), one undo step, section scope; catalog row under Layout › Page Setup.
- Page Setup dialog: Document Grid section; View › Gridlines draws the document
  grid of a section that has one. UI strings in every catalog (incl. et, sr, sr-latn).
- Tests: DOCX round trip, line pitch and lines per page, character pitch placement,
  command with clamping and undo.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-11 15:29:13 -04:00

10 KiB
Raw Blame History

Layout and pagination parity with Microsoft Word

Last reviewed: 2026-10-10 · Last updated: 2026-10-11 · 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, balancing ✅ Columns balance on a section's last page when the next section starts continuous (also at the document end, which Word only balances when the document ends with a continuous break); not after next-page/even/odd breaks or on a page with a column break; keep-together, keep-with-next, widow/orphan control and unsplittable rows can leave them slightly uneven (#350) —
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 separator, continuation separator and continuation notice are drawn (the notice under a note that continues; endnotes use the document's separator but don't continue onto a page of their own); each section's note options: footnotes below the text, endnotes at the end of each section, start at, numbering restarted each section or each page (counted from where the notes land, at most three passes) (#385) 1–2
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) 🟡 #354: lines follow the wrap polygon, or the outline worked out from the object (shape geometry; a picture's opaque pixels as a convex hull; otherwise the rectangle), turned and flipped with it, kept the left/right distance from text; Through also uses gaps inside the outline. Wrap side (wrapText: both sides, left only, right only, largest side per line) applies to square, tight and through wraps, turned objects included; picture outlines are convex; not compared page-for-page with Word 1–2
Text boxes, overflow, linked text boxes ✅ #46; linked text boxes (#369): the text runs on through each box in turn at that box's line length, overflow past the last box hidden; Align Text top / middle / bottom —
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) 🟡 #391: line grid snaps line heights to whole pitches (text centred in them; w:snapToGrid off opts a paragraph out); character grid puts East Asian characters on the character pitch (linesAndChars) or all text (snapToChars), Latin text proportional; View › Gridlines draws it. Not yet: run-level w:snapToGrid, grid in headers/footers, paragraph spacing in grid lines, Word's exact glyph placement in a cell 1–2
Vertical text (tbRl) in sections and text boxes; cell text direction 🟡 cell text direction landed (#245); text-box text direction (rotate 90°, 270°, stacked) landed (#369); page-level vertical text and East Asian upright vertical glyphs missing 8–12
Ruby / phonetic guide, enclose characters, combined characters 🟡 ruby (Phonetic Guide) landed (#288): ruby text over its base by alignment, line grows to fit, in PDF; enclose and combined characters missing; ruby not yet compared with Word page by page 2–4
Bidirectional paragraphs, mixed-direction lines; RTL tables and sections 🟡 #207; RTL tables (#362): grid columns from the right edge, start alignment and indent from the right margin, cell margins and left/right borders mirrored, merged and turned cells and nested tables included; RTL sections (#362): newspaper columns right to left with the line between mirrored. Right-hand page gutter (w:rtlGutter) missing 1
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-11 trivial Document grid: line and character pitch (#391)
2026-10-11 trivial Linked text boxes, Align Text and text-box text direction (#369)
2026-10-11 trivial Right-to-left tables and sections laid out mirrored (#362)
2026-10-10 trivial The document's own note separators and continuation notice are drawn (#352)
2026-10-11 trivial Newspaper columns balance before a continuous section break (#350)
2026-10-11 trivial Group and Ungroup keep turned members' orientation and placement (#441, #443); Size resizes a group (#442); the eraser hits turned ink where it is drawn (#445)
2026-10-10 trivial Long footnotes continue onto the next page with a continuation separator (#352)
2026-10-11 trivial EQ \o fields overstrike their arguments; enclosed characters draw their circle, square, triangle or diamond as vectors (#297)
2026-10-11 trivial Ruby (Phonetic Guide) layout landed (#288)
2026-10-10 trivial Wrap side: text on both sides, left only, right only or the largest side of an object (#354)
2026-10-10 trivial Tight and Through wrapping follow the object's outline (#354)
2026-10-10 trivial Rotated and flipped objects laid out and drawn (#332)
2026-10-11 trivial Footnotes below text, endnotes at the end of each section, note numbering restarted per section or page (#385)
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