Skip to content

fix(docx): elect Normal from text in runs and table cells, so restyling it reaches the body - #851

Merged
DemchaAV merged 6 commits into
2.5-devfrom
fix/docx-normal-from-table-text
Oct 5, 2026
Merged

DemchaAV merged 6 commits into
2.5-devfrom
fix/docx-normal-from-table-text

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Oct 5, 2026 •

Copy link
Copy Markdown
Owner

Why

Restyling Normal in Word is how a reader changes a document's body, and the export makes body runs that restate Normal say nothing so the restyle reaches them. Normal is elected as the style the most characters are set in (dominantTextStyle), but the count left text out:

  • a paragraph made of runs counted in its paragraph's style, which its runs set aside;
  • table cells did not count at all.

Where most of the text is in runs or cells — invoices, proposals, a rota — Normal came from the few paragraphs left. The body then carried a direct size that restyling Normal never reached: Normal 14pt over 10pt text in ProposalEditorial, 12pt over 10.5pt in CobaltRota. The Word editing protocol (#847) found the body following Normal in 54 of the 62 corpus documents.

What changed

DocxSemanticBackend.weighTextStyles counts each piece of text in the style it is written in:

  • a paragraph's runs each in their own style, falling back to the paragraph's;
  • a rich list item's runs the same way;
  • a plain list item's label in the list's style;
  • a table cell's lines in the style its cascade resolves to (resolveCellTextStyle, now static), the engine's default cell face where nothing states one;
  • a composed cell's node like any other node.

An empty cell counts for nothing, so a grid of blank cells does not outvote the body.

dominantTextStyle now picks the face and size with the most text first, then the colour with the most text among them. Body text set in two colours is one body still: ProposalNorthline's 9pt text, in its body colour and a muted one, lost to its 10pt while each colour counted alone.

A header's or footer's band paragraph (writeBand) now has its mark set in its text's style, as body paragraphs have since #849. Enter there continues the band's text, not Normal.

The recipe's "Named styles" section says what counts. CHANGELOG is updated.

Verification

  • Editing protocol (Word 16.0.20430, 62 documents): restyling Normal by +2pt reaches the body in 62 / 62, against 54. "Enter and type" stays at 62 / 62.

  • LibreOffice (Windows). VioletGrid is set on one page, as the PDF, instead of two, and its lines past 2pt go from 37 to 0. 65 lines move in all:

    • 50 nearer, 38 of them VioletGrid's;
    • 15 further, all CobaltRota's, by 0.05–0.4pt across.

    The baselines are committed. LibreOffice on the Linux CI does the same: VioletGrid goes from 2 pages to 1 and from 37 lines past 2pt to 0, with 67 lines moving; that baseline comes from this PR's CI artifact.

  • Word corpus. One line moves: the right-hand slot of CobaltRota's footer, 0.36pt further across (−3.26 → −3.62). It was already one of the three Word lines past 2pt. Styling the band's mark did not move it back, and the cause is not established. Nothing else moves.

  • Tests: DocxDocumentStyleTest:

    • runs weigh in their own style, not the paragraph's;
    • table cells weigh in their resolved style;
    • empty cells weigh nothing;
    • two colours of one face and size outweigh a third style that has more text than either of them alone.

    Three tests in DocxParagraphMarkTest and DocxRunStyleTest depended on the old count, where a paragraph's runs were invisible. Their documents now hold more body text, so they still test what they did.

  • Sabotage. Each change fails its test:

    • runs weighed in the paragraph's style;
    • table cells not weighed;
    • empty cells weighing one each;
    • colour weighed apart.
  • render-docx. 901 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.

Notes

Lane: shared-engine (render-docx).

@DemchaAV
DemchaAV merged commit 173623b into 2.5-dev Oct 5, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-normal-from-table-text branch October 5, 2026 07:52
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