Skip to content

fix(docx): set a paragraph's mark in what its text ends in, so Enter continues it - #849

Merged
DemchaAV merged 10 commits into
2.5-devfrom
fix/docx-paragraph-mark-format
Oct 5, 2026
Merged

DemchaAV merged 10 commits into
2.5-devfrom
fix/docx-paragraph-mark-format

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner

Why

Word continues a paragraph from its mark, the character that closes it:

  • press Enter at the end of a paragraph and type, and the new letters take the mark's run properties;
  • type at the end of a document, and they take its last paragraph's mark.

styleTheMark skipped every paragraph written at an exact line height, which is almost all of them, because the mark does not grow such a line. It wrote only size and face elsewhere. So the mark stayed in the document's own formatting.

The editing protocol (#847) in Word 16.0.20430 measured the effect on the corpus's 2.5-dev export:

  • Enter and type. 25 of 62 documents set the new paragraph in another size: 9pt after 10.5pt in NavySidebar, 14pt after 11pt in ClassicInvoice.
  • Type at the end. 6 more documents set the typed letters at the document's size on exact lines built for their last paragraph's smaller text, 14pt letters on 9.25pt lines.

What changed

  • styleTheMark styles a scratch run with applyStyle and moves its properties onto the paragraph's mark through the typed CTParaRPr setters, which keep the schema's order. The mark gets face, size, colour, weight, slant, strike, underline and tracking, as applyStyle writes them for the text's last run, so text restating Normal leaves its mark silent. It does not get what is written beside applyStyle: a chip's shading, a run's direction, the spacing that fits a line to the page. Exact lines are no longer skipped.
  • A rich list item's mark takes its last run's style, not the list's, since its runs are written in their own styles.
  • A paragraph or rich item ending in a chip keeps its own style on the mark. The chip's letters are styled for a fill the mark does not carry: white on a red badge would continue as white on the page.
  • Numbering markers. Word draws a numbering marker in the mark's style, so the marker follows it too. A numbered item is always a plain list line in the list's style; rich items do not get Word numbering. So every numbered marker is now in the list's style, decoration and tracking included, instead of the document's. That is the style the engine measures and draws the marker in (ListMarkerGeometry, ParagraphWrapping). A measured top level also states the list's face, size and colour on the level.
  • edit-protocol-corpus.ps1:
    • "Type at the end" now judges the typed letters against the text they continue: the same size as its last letter, on the lines the page set that text on. The protocol's own 1.1-times-size threshold for exact lines flagged the documents' design: Helvetica's 10pt text on its layout's 9.25pt lines. The threshold now applies only after an empty paragraph, and typed text under 4pt fails anywhere (a paragraph of pictures has its runs a point tall).
    • -Scenario runs chosen scenarios. Names given comma-separated are split, and an unknown name is refused. CONTRIBUTING.md describes both.
  • Docs. The recipe's "Named styles" section describes the mark and what Enter continues. CHANGELOG is updated. assets/readme/examples/word-export-companion.docx is re-rendered, since its paragraph marks changed.

Verification

  • Editing protocol (Word 16.0.20430, 62 documents, -Scenario insert-a-paragraph,add-a-page; both columns measured with this branch's script):

    Scenario 2.5-dev this branch
    Enter and type 37 / 62 62 / 62
    type at the end 23 / 62 29 / 62
  • Word corpus. scripts/docx-visual/word-fidelity.ps1 -Update → BUILD SUCCESS, baselines unchanged: no line moved.

  • LibreOffice. 20 lines move down by up to 0.2pt and none across, on Windows and on Linux.

    • Windows: 15 nearer, mostly ConsultingInvoice's label column (−0.63 → −0.53pt), and 5 further, SerifHeadline's and two of NavySidebar's dates. Two runs gave the same figures.
    • Linux, from CI: the same 20 lines, 14 nearer and 6 further.

    Both baselines are committed. The chip change moved no corpus line, in either editor.

  • Tests: DocxParagraphMarkTest:

    • an exact-line paragraph ending in a bold, coloured 11pt run has a mark of 22 half points, bold, in 1E5AA0;
    • an exact-line paragraph in the document's own style leaves its mark silent (it replaces a test that asserted the skip this PR removes);
    • a paragraph ending in a white chip has no colour on its mark;
    • a rich list item ending in a 13pt run in a 9pt list has a 26-half-point mark;
    • a paragraph composed in a cell, which used to assert no mark on its exact line, now asserts the mark in the text's size and face.
  • Sabotage. Each change fails a test:

    • restoring the exact-line skip: 3 tests fail;
    • dropping bold and colour from the copy: 1 test fails;
    • giving a rich item the list's style: 1 test fails;
    • giving a chip's style to the mark: 1 test fails.
  • render-docx. 897 tests green.

  • Full reactor gate. ./mvnw -B -ntp clean verify -pl :graph-compose-core,:graph-compose-render-pdf,:graph-compose-render-docx,:graph-compose-render-pptx,:graph-compose-templates,:graph-compose-testing,:graph-compose-qa,:graph-compose-coverage -am → BUILD SUCCESS (qa 1820 tests).

  • Examples. CommittedAssetDriftTest → 3 / 3 green after re-rendering the DOCX preview. The example's PDF is unchanged.

Notes

Lane: shared-engine (render-docx), with the test script in scripts/docx-visual.

@DemchaAV
DemchaAV merged commit 09790f9 into 2.5-dev Oct 5, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-paragraph-mark-format branch October 5, 2026 06:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant