feat(fields): add SECTIONPAGES field support with section-aware numbering (SD-3349 and SD-3027)#3605
Conversation
|
The ecma-spec MCP permission isn't being granted in this session, so I verified against my own knowledge of ECMA-376 Part 1 §17.16 (field codes) rather than the live spec. Flagging that caveat up front. Status: PASS This PR adds a
Two minor, non-blocking robustness gaps (not spec violations):
Net: no non-existent elements/attributes, no missing required attributes, no incorrect defaults. OOXML-compliant. |
💡 Codex Reviewsuperdoc/packages/layout-engine/layout-bridge/src/layoutHeaderFooter.ts Lines 164 to 168 in 9cd0404 This new list branch makes header/footer variants with PAGE/NUMPAGES/SECTIONPAGES inside list items take the token-aware layout path, but ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
cubic analysis
2 issues found across 65 files
Linked issue analysis
Linked issue: SD-3349: Bug: Numbering issues
| Status | Acceptance criteria | Notes |
|---|---|---|
| ✅ | Import DOCX SECTIONPAGES fields into the pipeline (create sd:sectionPageCount nodes, preserve cached text/run props) | New SECTIONPAGES preprocessor and importer wiring are present and covered by unit tests that assert creation and preservation of cached text/run properties. |
| ✅ | Compute and expose per-section page counts during layout (DisplayPageInfo / numbering context) | Layout code now computes sectionPageCount and threads it through page resolvers and DisplayPageInfo; incremental layout and layoutHeaderFooter were updated and corresponding tests added. |
| ✅ | Resolve SECTIONPAGES tokens (and formatting) at render/layout time (body/header/footer/shape) | Token resolution updated to accept sectionPageCount and apply pageNumberFormat; resolvePageTokens, resolveHeaderFooterTokens, text-run resolution, and unit tests were added/updated to assert formatted SECTIONPAGES output. |
| ✅ | Header/footer and shape editing surfaces render and expose section-aware values (editor options and DOM/SVG rendering) | Editor plumbing now threads sectionPageCount/current-page display values through HeaderFooterSessionManager, HeaderFooterRegistry, PresentationEditor and story editor factory; shape and SVG rendering consume sectionPageCount and tests assert behaviour and options. |
| ✅ | Export reconstructs SECTIONPAGES complex-field w:fldChar structure (encode/decode) | A sectionPageCount translator was added and wired into exporter/translators; translator has tests for encode/decode. |
| ✅ | Field refresh (F9 and fields.rebuild) recomputes SECTIONPAGES values and updates resolved text | Field update extension now treats SECTIONPAGES as updatable; document API field-wrappers and a section-pages-specific rebuild path were added with tests verifying F9/fields.rebuild behaviour. |
| ✅ | Header/footer layout fidelity when SECTIONPAGES varies per-page (use largest per-page metrics; disable page-bucketing) | Header/footer layout logic was changed to derive heights across per-page layouts and paragraph token checks now detect sectionPageCount to avoid page-bucketing; tests were added to validate choosing largest metrics. |
| ✅ | End-to-end rendering in DOM and vector shapes (formatted PAGE/SECTIONPAGES values appear in painted DOM/SVG) | Painter/renderer changes handle SECTIONPAGES and field-local formatting in shape text; tests assert formatted PAGE/SECTIONPAGES in DOM and drawing text. |
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
97ef352 to
2416c1e
Compare
9cd0404 to
efbe1b2
Compare
c9b8acd to
01fcb64
Compare
… parity OOXML (ECMA-376 §17.10.1) selects even/odd headers based on the printed page number — which respects per-section numbering restarts and offsets — not the physical page index. Track the post-restart/offset value as `displayNumber` on each page and thread it through pagination, header/footer resolution, and the HeaderFooterSessionManager so a section that starts at page 2 picks the `even` variant on its first page.
Parse `\*` general-format and `\#` numeric-picture switches when importing PAGE/NUMPAGES fields and thread the requested format (roman/alphabetic/zero-padded decimal/etc.) plus the section-aware numeric page value through the converter, pm-adapter, layout engine, and DOM painter so page-number fields render in the format Word stored rather than always decimal. The original instruction is preserved on the node so export round-trips back to the same field code.
Replace the third positional `_docxOrFieldRunRPr` argument with a generic field-preprocessing `options` object (docx, instructionTokens, fieldRunRPr), keeping backward-compat with the legacy positional w:rPr. Update cache-invalidation test fixtures to the `pageNumberFieldFormat` run shape.
25957c8 to
e2a88d6
Compare
…3620) * feat(sections): add chapter numbering to section page numbering Extend section page numbering with `chapterStyle` (w:chapStyle) and `chapterSeparator` (w:chapSep) support across the stack: - document-api: add fields to the setPageNumbering contract (anyOf now accepts chapterStyle/chapterSeparator), schemas, types, and validation - layout contracts: extend SectionNumbering with chapter fields and reuse PageNumberFormat/PageNumberChapterSeparator types - layout-adapter: extract w:chapStyle/w:chapSep from pgNumType, validate positive integers and known separators, and compare them in section signatures - sections-xml helpers: read/write chapter attributes on w:pgNumType - regenerate Document API reference docs * feat(layout): render chapter-prefixed page numbers Resolve and paint chapter number prefixes (e.g. "1-1", "3:V") for sections that enable chapter numbering, deriving the chapter from the nearest numbered Heading N marker. - contracts: add formatSectionPageNumberText helper, chapter/format fields on Page and HeaderFooterPage, and headingLevel/listLevelOrdinal paragraph attrs - pageNumbering: add buildChapterContextByPage to track the active chapter per physical page, normalizeChapterMarkerText to accept only clean single-token markers, and thread chapter context through computeDisplayPageNumber - layout-bridge: build/cache chapter context across PAGE-token convergence, apply it to body pages, and disable header/footer digit bucketing when chapter prefixes can vary the rendered width - resolvePageTokens / text-run / renderer: preserve the chapter prefix when a run-local PAGE format switch applies - layout-adapter: resolve built-in heading level from style metadata (incl. localized names) and expose the structured list ordinal * fix(page-number): fall back chapter headings * fix(page-number): use no-break chapter hyphen * fix(page-number): clear stale chapter children * fix(layout): stamp section page format * fix(page-number): accept nested chapter markers * fix(layout): converge page tokens by output * fix(header-footer): disable buckets for restarts * fix(page-number): preserve body token metadata * fix(header-footer): pass per-rid chapter context * fix(layout): key chapter cache by fragments * fix(page-number): allow safe chapter separators * fix(header-footer): measure chapter tokens in prelayout * fix(header-footer): preserve chapter page prefix in editor * fix(header-footer): clear stale chapter editor context * fix(header-footer): prelayout resolved headings * fix(header-footer): prelayout heading ordinal fallback * fix(header-footer): prelayout two digit page tokens * fix(layout-bridge): keep numpages headers bucketed
Summary
This branch builds on the PAGE/NUMPAGES field work from
luccas/sd-3006-feature-page-number-fieldsand adds full support for Word's SECTIONPAGES field — the count of physical pages in the current section (as opposed to NUMPAGES, which counts the whole document). It threads a per-section page count through the entire import → layout → paint → export pipeline, and through the header/footer/shape editing surfaces.Along the way it extends PAGE field-local number formatting (
\* roman, etc.) into the live/editable header-footer and shape-text paths, fixes a header/footer layout-height fidelity bug, and corrects a couple of malformedparseDOMselectors.What changed
New
section-page-countnode + field plumbingsection-page-count(page-number/page-number.js) with anaddSectionPageCountcommand (header/footer only), node attributes (instruction,pageNumberFormat,importedCachedText,resolvedText), node view, and CSS styling (page-number.css).constants.tsATOMIC_INLINE_TYPES/TOKEN_INLINE_TYPES), inline-node fallback (is-inline-node.js), extension index, and node-attribute typings (node-attributes.ts,miscellaneous-commands.ts).Import (DOCX → PM)
section-pages-preprocessor.jsconvertsSECTIONPAGESfield codes intosd:sectionPageCountnodes, preserving cached display text and run properties. Registered in both the main pipeline (fld-preprocessors/index.js) and the header/footer-only path (preProcessPageFieldsOnly.js).parsePageInstructiongeneralized to accept anexpectedKeywordso it parses value-format switches for bothPAGEandSECTIONPAGES.sectionPageCount-translator.js(encode/decode) + importer wiring (autoPageNumberImporter.js,docxImporter.js,handlers/index.js).Export (PM → DOCX)
sectionPageCount-translatordecode rebuilds thew:fldCharcomplex-field structure (instruction, cached text, marks) and is registered inexporter.js.Layout / paint
TextRun.tokenandTextPart.fieldTypegainsectionPageCount/SECTIONPAGES;TextPartnow carriespageNumberFormat.pageNumbering.tscomputes a per-section page count and exposes it onDisplayPageInfo.resolvePageTokens.ts,renderer.ts, andtext-run.tsresolve the new token (with optional format override) for body, shape, and decoration rendering.layout-bridge(layoutHeaderFooter.ts,resolveHeaderFooterTokens.ts,incrementalLayout.ts,HeaderFooterPerRidLayout.ts) resolves SECTIONPAGES tokens per page and disables page-bucketing when the content contains them (since the value can differ per page).Header/footer & shape editing surfaces
sectionPageCount,currentPageNumberText, andcurrentPageDisplayNumberare threaded through the story-editor chain:HeaderFooterSessionManager,HeaderFooterRegistry(with validation + DOM refresh that re-resolvespageNumberFormatviaposAtDOM),PresentationEditor,story-editor-factory,pagination-helpers,EditorConfig, and session types.svg-utils.js,ShapeGroupView.js,VectorShapeView.js,encode-image-node-helpers.js) resolves SECTIONPAGES (and now formats PAGE) in SVGforeignObjecttext, preserving cached values when no live count is available.Field refresh
field-update.js) and the Document APIfields.rebuild(field-wrappers.ts+ newsection-page-count.tshelper,field-resolver.ts) now recompute SECTIONPAGES values, replacing the node so text content andresolvedTextstay in sync.Notable fidelity fixes
HeaderFooterLayoutnow derivesminY/maxY/renderHeight/heightfrom the widest bounds across all per-page layouts instead of only the first page — previously per-page differences (now common with SECTIONPAGES) could mis-size the region.parseDOMselectors: fixed missing]in thepage-numberandtotal-page-numberselectors (span[data-id="auto-page-number"→…"]), which previously made those selectors invalid.Testing
New/updated unit tests accompany each layer:
pageNumbering,resolvePageNumberTokens, painterindex/text-run, layout-bridgeheaderFooterLayout/resolveHeaderFooterTokens, importer preprocessors (section-pages-preprocessor,preProcessPageFieldsOnly,preProcessNodesForFldChar),sectionPageCount-translator,encode-image-node-helpers,svg-utils,field-update,page-number,field-resolver,field-wrappers.section-pages,HeaderFooterRegistry,HeaderFooterSessionManager, andstory-editor-factory.