fix(docx): keep a block on one page in Word when the layout does - #725
Merged
Merged
Conversation
keepTogether() and keepWithNext() are resolved by the layout, and Word re-paginates on its own, so the export has to say them. A block the layout placed on one page gives each of its paragraphs w:keepLines and every one but the last w:keepNext, the last as well for keepWithNext; a table inside it is chained row by row. A block that ran over a page break in the layout is left to flow.
DemchaAV
force-pushed
the
fix/docx-keep-sections
branch
from
September 23, 2026 12:58
5a528c8 to
e8609fd
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
keepTogether()andkeepWithNext()are resolved byLayoutCompiler:keepWithNextblock moves down together with the first line of the block after it.Word re-paginates a DOCX itself and the export told it neither. So a card the page holds together split across Word's page break, and a heading the page moves down with its body could be left at the foot of the page above.
What changed
DocxSemanticBackend.writeNodenotes where the document body ends, writes the node, then hands everything the node wrote tokeepOnOnePage:w:keepLineson every paragraph.w:keepNexton every paragraph but the last, which chains the block into one unit.keepWithNext,w:keepNexton the last paragraph too.DocxLayoutMetrics.onOnePage: start page equals end page). The layout keeps a block together only when a page can hold it and lets a taller one flow. A block that ran over a page break is that taller block, so it is left to flow in Word too. With no layout there is nothing to go on, and nothing is written.DocumentNode.keepTogether()/keepWithNext(), so it covers sections, modules and timelines. ALineNodewithkeepWithNextis dropped by this backend already, so it writes nothing.Verification
In an editor. A 300×300 page with filler paragraphs above a six-line section, converted with LibreOffice (
soffice --headless --convert-to pdf), card lines by page:keepTogetherkeepTogetherThe layout places the section the same way: pages 0–1 without the flag, page 1 with it.
Gate. Full reactor gate (
clean verifyover core, render-pdf/docx/pptx, templates, testing, qa, coverage) → BUILD SUCCESS. Examples after install: 93 green. No committed preview moved.New
DocxKeepTogetherTest(6 tests):keepWithNextheading keeps with its body.Sabotaging the one-page check and the last-paragraph exception fails 4 of the 6.
Lane: shared-engine (render-docx) — paragraph properties only; no public API change. Touches
DocxLayoutMetricsand the CHANGELOG head next to #724, so whichever merges second needs a rebase.