Repository navigation
fix(docx): cut a panel whose table runs over pages into a table a page - #962
Merged
Merged
Conversation
The layout breaks a table in a panel between rows, repeats its header rows at the top of the next page and goes on with the panel there, no padding above it. The export wrote the panel as one table of one cell: Word broke its row where its lines ran out and repeats no header row of a table nested in a cell, so the line items after the break stood 24 to 30pt high with no header, and over three pages a row stood a page early. Once the document is written, a panel whose own table is the only child the layout breaks over pages is cut at the row each page starts with, its pages read off its own section's layout. The part after a cut is a copy of the panel holding the table's header rows, the rows from that row on and what follows the table, with no top padding; a part before a cut has no bottom padding; a hairline paragraph between the parts breaks the page before itself. The report names the cut, its pages, its fixed page breaks, any page left whole and the top border a part after a cut stands lower by.
…ge not cut A part before a cut must hold, under the page's last row, the borders Word sets inside it: its bottom border and, where it opens its page, its top border and the paragraph before it. The page sets the rows down to its foot and draws the border taking no room. Where the page above leaves less than those and a point, Word would set the last row on a page of its own and the fixed break would open one more, so that page is not cut. The report names each page not cut and why: outside the panel's table, at a row the table cannot be split at, or too near the foot. A panel cut at no page, an anchored card whose bookmark opens in its table's header row for one, is named as written whole.
A panel in a later section names the pages it is cut at, and those it is not, with its section, as other notes naming a section's pages do. A panel cut at no page says Word repeats no header row only where its table has one.
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
A panel — a painted section or container — is written as a table of one cell. When the layout sets a panel over pages because a table inside it runs on, it breaks that table between rows, repeats the table's header rows at the top of the next page, and goes on with the panel there with no padding above it. The export wrote the panel as one table, so Word broke the panel's row wherever its lines ran out. Word also repeats no header row of a table nested in a cell.
No document of the 62-document corpus has such a panel. Two real templates do, once their line items run over a page:
ObsidianInvoice's line-items card;SubscriptionInvoice's ruled line items.Measured in Word 16 and LibreOffice 24.2 with the line items repeated three and six times:
What changed
writePanelnotes a panel written whole in the body that the layout breaks over pages inside one of its own children: a table, and the only child of any kind it breaks over pages (noteATableOverPages), with its own section's layout.writeTableRowsrecords the Word table each table node is written as (tablesWritten).cutThePanelsAtTheirPagescuts each such panel at the row of its table each page starts with (DocxTableSplit.rowStarting). It runs once the document is written, after the drawings are anchored and the page references settled, so a part's copy carries what the writing put in it. It reads each panel's pages off its own section's layout, as each section is laid out on its own. Each part after a cut has no top padding, as the page goes on with the panel at the page's top. Each part before a cut has no bottom padding, as the page sets the rows down to the page's foot and closes the panel only on its last page.DocxTableSplit.splitInItsPanel(new) does one cut:A break written in that paragraph instead put a blank page after
SubscriptionInvoice's first part, which fills its page to the foot: a break before a paragraph that already opens a page adds none.splitandsplitInItsPanelshare the copy and the row trimming.Room at a cut: a part before a cut must hold, under the page's last row, the borders Word sets inside the part: its bottom border and, where that part opens its page, its top border and the 0.1pt paragraph before it, plus a point for the editor's lines. The page sets the rows down to its foot and draws the border taking no room. Where the page above leaves less (
DocxLayoutMetrics.lowestRowOnagainst the page's bottom margin), Word would set the last row on a page of its own and the fixed break would open one more page, so that page is not cut.Report: the panel is named once (
APPROXIMATED,reportTheCut). The note gives the pages it is cut at, as the panel's section counts them, the header rows where the table has them, and each page not cut and why: outside its table, at a row the table cannot be split at, or too near the foot. A panel cut at no page, an anchored card's for one, whose bookmark opens in its table's header row, is named as written whole. It says the page breaks are fixed, so rows an edit adds above a cut no longer run onto the next page. Where the panel has a top border, it also says a part after a cut stands about that border's width lower: Word draws the border inside the row, while the page strokes it on the panel's edge.Not cut:
rowStarting, as for the page-margin split); a page above which the rows end too near the foot; the note names each;Docs: the recipe's panel
Over pagesparagraph, the capability matrix's keep row, the CHANGELOG.Verification
Measured with the probe (scratch, not committed): Obsidian ×3 and ×6 and Subscription ×6 through the engine, Word 16 and LibreOffice 24.2. Every page now holds the lines the page sets on it, the same count, in both editors.
Cards padded 6pt (1pt border, a 400×300 page, two and three pages) and 12pt (2pt border, A4) also stand on their pages in both editors: page 1 within 0.33pt; each later page lower by its top border and the 0.1pt paragraph between, +1.1pt and +2.1pt in Word and LibreOffice alike.
What remains is the top border: Subscription's ruled top is 2.82pt, and it is named in the report.
Tests:
DocxPanelOverPagesTest(new, 22):InvoicePanelOverPagesDocxTest(qa, new, 2):ObsidianInvoice(×3, ×6) andSubscriptionInvoice(×6) are each a table a page for as many pages as the layout sets the card over, every part after the first opening with the line items' header.Fail-closed: 25 sabotages, each run alone, all caught: no cut; the panel never noted; a part after a cut keeping its top padding; a part before one keeping its bottom padding; the break written in the paragraph; the first part's cell left ending with its table, or closed by a paragraph a line tall; the paragraph between a line tall; no header rows after a cut; a later cut's rows read from the table's start; what follows the table kept in the first part; what precedes it kept in the second; no room kept under the last row, or none for a middle part's top border; a page after the table read as one inside it; the cut, its top border, its header rows or a lost header where there is none, a page left whole, a page outside the table, a panel cut nowhere or a later section's pages misnamed or not named; the cut reading the last section's layout; only tables counted over pages.
Corpus: no document of the 62 has a panel the layout breaks over pages; every document is unchanged part for part, and so is the report (1445 notes).
Gate:
./mvnw -B -ntp clean verify -pl <core, render-pdf, render-docx, render-pptx, templates, testing, qa, coverage> -am→ BUILD SUCCESS: core 823, render-pdf 339, render-docx 2230, testing 5, render-pptx 142, templates 127, qa 1832../mvnw -f examples/pom.xml test→ BUILD SUCCESS, 93 tests.Lane: shared-engine (render-docx). No public API change.