Skip to content

fix(docx): keep a stack of one layer on the page the layout puts it on - #931

Merged
DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-one-layer-stack-whole
Oct 20, 2026
Merged

DemchaAV merged 1 commit into
2.5-devfrom
fix/docx-one-layer-stack-whole

Conversation

@DemchaAV

Copy link
Copy Markdown
Owner

Why

A layer stack is atomic in the layout, so a page break moves it whole. A stack of one layer is
written in the flow as plain paragraphs, and nothing told Word to keep them together. Word broke
between them, which left part of a stack the page sets on the next page at the foot of the page
above.

Measured in Word 16 and LibreOffice on Windows: a stack whose layer is a section of three lines,
"Opening", "Body" and "Tail", that the page moves to page 2 (baselines; p = page).

Stack of one layer Page Before, Word / LibreOffice After, Word / LibreOffice
three plain lines all on p2 (86.2, 99.2, 112.1) Opening and Body on p1, Tail on p2 / same all on p2 (85.3, 98.2, 111.2) / same
an 8pt spacer, then the lines all on p2 (94.2, 107.2, 120.1) Opening and Body on p1, Tail on p2 / same all on p2 (93.0, 105.9, 118.9) / same
a 10pt margin on the first line all on p2 (96.2, 109.2, 122.1) Opening and Body on p1, Tail on p2 / same all on p2 (95.2, 108.2, 121.2) / same

Nothing was named. A stack that stays on its page stood where the page sets it before, and still
does.

What changed

  • writePlacedNode keeps a stack of one layer in the flow on its page as it keeps a block
    that asks for keepTogether(): through keepOnOnePage, when the layout put it on one page.
    • Each paragraph keeps its lines, and every one but the last keeps with the next. A table in
      it is chained row by row.
    • In a cell a stack's paragraphs are its table's, and are left to the row.
    • A stack of more than one layer is not kept here.
  • The spacer's own keep is removed. fix(docx): keep the space above a spacer opening a stack of one layer #930 added followedInItsStack for a spacer opening such
    a stack on a new page. The stack's keep now holds every paragraph but its last to the next, so
    the separate keep is gone. The spacer's line still holds the space above it.
  • Docs:
    • the capability matrix's keep row;
    • the recipe's sections row;
    • CHANGELOG v2.5.0.

Verification

  • Corpus, 62 DOCX before and after: all 62 are byte-identical, and the report's 1246 notes
    are identical. A corpus document with a stack of one layer in the flow would have gained its
    keeps, so none of the 62 has one.

  • Example: word-export-companion.docx was regenerated. It differs from the committed one only
    in docProps/core.xml, the export's time.

  • fix(docx): keep the space above a spacer opening a stack of one layer #930's spacer cases, measured again on this code in both editors: the text stands at 107.0
    where the page sets it at 108.2, as before.

  • DocxKeepTogetherTest, 5 new tests:

    • a stack is chained into one unit, and its last line is tied to nothing after it;
    • a row in a stack gets the keeps and the one-row table of a section kept together;
    • a stack in a row's cell is left to its row;
    • a band is not chained here;
    • without a layout nothing is kept.

    The fix(docx): keep the space above a spacer opening a stack of one layer #930 spacer tests in DocxStackOfOneLayerOnANewPageTest pass through the stack's keep.

  • 4 sabotages, all caught:

    • no keep for a stack;
    • kept in a cell;
    • a band kept too;
    • kept with no layout.
  • ./mvnw -B -ntp clean verify: BUILD SUCCESS.

    • Since then only comments, one test and the docs changed.
    • After them: render-docx's 1881 tests and qa's 27 documentation and guard tests pass, and so
      do the knowledge checks.

What this leaves, each recorded as a separate step:

  • A stack of one layer inside a painted panel's cell: a panel is a table whose row may break,
    and the stack there is not kept. Whether Word holds a cell's paragraph keeps in a row that may
    break is not measured.
  • A band (a stack of more than one layer) opening a page still breaks in Word. That is its
    own step.

Lane: render-docx (semantic backend). DOCX output changes only for a stack of one layer in
the flow, outside any cell.

The layout moves a layer stack to a new page whole, but its one layer
is written in the flow as plain paragraphs, and Word was told nothing.
Measured in Word and LibreOffice, a stack of three lines that the page
moved to the next page stood with two of them at the foot of the page
above; so did one opening with a spacer or with a margin.

A stack of one layer in the flow is now kept on its page as a block
kept together is, through keepOnOnePage. The spacer's own keep added
for a stack opening a page is gone with it, as the stack's keep holds
every paragraph but its last to the next.
@DemchaAV
DemchaAV merged commit 875c027 into 2.5-dev Oct 20, 2026
13 checks passed
@DemchaAV
DemchaAV deleted the fix/docx-one-layer-stack-whole branch October 20, 2026 16:36
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