fix(metadata): detect sectPr nested in tables; ignore text-box sections (#51)#271
Merged
Conversation
…ns (#51) GetDocumentMetadata's CollectSectionData scanned only the body's direct children, so a w:sectPr carried by a paragraph inside a table cell was never seen. Such a document reported one section instead of two, and the per-section page dimensions and paragraph/table index ranges used for lazy-loading pagination were wrong. CollectSectionData now walks the body as a single main story in document order, descending into tables (w:tbl -> w:tr -> w:tc) so an in-cell section break is counted and attributed to the section it starts in. Each w:p is treated as a leaf (only its direct w:pPr/w:sectPr is inspected, never its runs), so a w:sectPr inside a text box -- a separate story that does not paginate the main document -- is excluded automatically, along with text-box paragraphs; counting it would invent a phantom section. Only body-level tables count toward the table total, preserving the previous counts for the common case. Tests: DM022 (in-cell break detected, table attributed correctly) and DM023 (text-box section properties ignored). The separate-story rule is documented in docs/ooxml_corner_cases.md.
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.
Summary
Closes #51.
WmlToHtmlConverter.GetDocumentMetadata()reported the wrong number of sections for documents whose section break lives inside a table cell.CollectSectionDatascanned only the body's direct children:so a
w:sectPrcarried by a paragraph nested inw:tbl/w:tr/w:tc/w:p/w:pPrwas invisible. Such a document reported one section instead of two, and the per-section page dimensions and paragraph/table index ranges used for lazy-loading pagination were wrong. The method even carried a comment flagging this as a known limitation tracked by this issue.This is the Document Metadata API in
WmlToHtmlConverter.cs— it is not part of redlining,WmlComparer, or the DocxDiff engine, so no comparison code is touched.The fix
CollectSectionDatanow walks the body as a single main story in document order:w:tbl → w:tr → w:tc) because a cell's content is part of the main story, so an in-cell section break is detected and attributed to the section it starts in.w:pis treated as a leaf — only its directw:pPr/w:sectPris inspected, never its runs. Because a text box (w:txbxContent) is always nested inside a run, aw:sectPrinside a text box is excluded automatically, along with text-box paragraphs. A text box is a separate story that does not paginate the main document; counting its section properties would invent a phantom section and corrupt the metadata. Headers/footers/footnotes/endnotes/comments live in their own parts and are out of the body tree by construction.w:sectPrplacementw:body/w:p/w:pPr/w:sectPr(body paragraph)w:body/w:sectPr(trailing/final)w:tbl/w:tr/w:tc/w:p/w:pPr/w:sectPr(table cell)…/w:txbxContent/…/w:sectPr(text box)The change is self-contained:
CollectSectionDatahas exactly one caller (GetDocumentMetadata), and the publicDocumentMetadata/SectionMetadatashape is unchanged, so the WASM/npm surfaces pick this up with no wire change.Testing
DocumentMetadataTests.cs:DM022_GetDocumentMetadata_DetectsSectionBreakInsideTableCell— an in-cell break now yields 2 sections, the table is attributed to the section it starts in, and paragraph/section indices stay contiguous.DM023_GetDocumentMetadata_IgnoresSectionPropertiesInsideTextBox— a text-boxw:sectPrdoes not create a section (single section, governed by the bodyw:sectPr), and text-box paragraphs are not counted.dotnet test).-c Release,TreatWarningsAsErrors=true) is clean — no new warnings from the changed file.Docs
CHANGELOG.md— entry under[Unreleased] → Fixed.docs/ooxml_corner_cases.md— new section documenting why a table-cellw:sectPris a section break while a text-boxw:sectPris not (separate-story rule).🤖 Generated with Claude Code
Generated by Claude Code