Skip to content

fix(docx): even a table row's vertical cell margins, and hold a composed chip to its outline - #795

Merged
DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-rota-cobalt
Sep 30, 2026
Merged

DemchaAV merged 2 commits into
2.5-devfrom
fix/docx-rota-cobalt

Conversation

@DemchaAV

@DemchaAV DemchaAV commented Sep 30, 2026 •

Copy link
Copy Markdown
Owner

Why

In Word, CobaltRota stood 23pt off its page on median and ran onto a second page.

  • The cause, measured in both Word and LibreOffice: a table row gives every cell the largest top margin of any cell in it, and the largest bottom margin.
    • A row whose day cells were padded 5.5pt above and 10.25pt below, beside a label padded 0.75pt, stood 60.3pt tall in both editors. Its tallest cell, content and padding, came to 46.
    • CobaltRota's masthead row stood 20.8pt taller than the page's.
    • Each staff row, its name padded 2.55pt against its days' 1.35, stood 2.4pt taller.
  • A second defect in the same rota: a shift chip is a shape composed in a table cell and written as a panel. It has no layout placement, so its row was not held to its height. The chips closed round their line of text: most of the 17.5pt chips to 12.7pt.

What changed

  • evenTheRowsMargins, called in writeTableRows once a row's cells are written and before holdRowHeight:
    • Each cell's top and bottom w:tcMar is lowered to the row's smallest.
    • The rest of the padding is written as w:before on the cell's first paragraph and w:after on its last.
    • Some cells keep their margin on a side: a cell opening with a table has no paragraph above it, and a cell in a vertical merge has its bottom edge in another row. The row's margin then comes down no lower than the largest margin such a cell keeps, so the cells beside it are not padded twice.
    • holdRowAtLeast still subtracts the row's margins, now the smaller ones. The moved spacing is part of the content, so the held height comes out the same.
  • dropTheSpaceBelow is unchanged. It leaves a table with a drawn bottom alone, and every table writeTableRows writes has one (POI's single table border), so the padding moved below a last row's text is never stripped at the end of a page.
  • writePanelPiece. A ShapeContainerNode written as a panel with no layout placement, which means composed in a table cell, is held at least its outline's height. This matches how panelWidth already takes the outline's width.
  • Docs. CHANGELOG.md and docs/recipes/docx-export.md (the Tables row and the composed-shape paragraph) are updated.

Verification

  • 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 gives BUILD SUCCESS (1791 + 127 tests).
    • After install, examples run 93 green.
    • The knowledge checks and extract-api --check pass.
    • render-docx runs 706 tests.
  • DocxCellPaddingTest:
    • New: a row's cells share its smallest top and bottom margins, and each cell's own padding sums back from margin plus paragraph spacing.
    • New: a cell opening with a table keeps its margin, and the 3pt cell beside it gets no padding written twice.
    • New: a cell in a vertical merge keeps its margins, with nothing written below it.
    • New: a cell in a vertical merge holds the row's bottom up to its own, so a 6pt cell beside it is left as it was.
    • New: the nested table's cell keeps its 5pt.
    • Changed: the padding cascade is asserted as margin plus the first paragraph's spacing.
  • DocxComposedCellTest: the pill test now pins its row held at least the outline's 14pt, where fix(docx): write a filled pill composed in a table cell as a panel, so a rota's shift chips keep their colour #772 had pinned it not held.
  • Each rule fails its own test when reverted: the evening, the top and bottom floors at the kept margins, the vertical-merge exclusion, and the outline hold.
  • Template corpus (62 documents), against 2.5-dev:
    • Two documents change: CobaltRota and OrangeOps (unchanged in both editors).
    • CobaltRota's median drift falls from 23.1pt to 8.9 in Word and in LibreOffice.
    • CobaltRota fits one page again in LibreOffice; in Word its last staff row still goes onto a second page.
    • On that second page in Word, the repeated header stands where it does on the first, to within 0.1pt, so the padding moved into its cells' paragraphs is kept.
    • In Word, 62 of its 67 chips are 17.5pt, as on the page; before, they were 12.7 to 16.1pt.

Known limits

  • Still left in CobaltRota in Word (about 9pt, one row onto page 2):
    • The masthead subtitle's -6.5pt top margin inside a composed cell has no space above it to come out of.
    • A stacked chip's 10pt line stands in a 9.2pt chip.
    • The group icons are anchored a row low.
  • Each of these is its own mechanism.

Lane: shared-engine (render-docx). No public API change.

… of their padding in their paragraphs, and hold a composed chip to its outline
@DemchaAV DemchaAV changed the title fix(docx): give a row's cells its smallest vertical margins, the rest of their padding in their paragraphs, and hold a composed chip to its outline fix(docx): even a table row's vertical cell margins, and hold a composed chip to its outline Sep 30, 2026
@DemchaAV
DemchaAV merged commit 501df89 into 2.5-dev Sep 30, 2026
12 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-rota-cobalt branch September 30, 2026 21:08
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