Skip to content

feat: honor PAGE/NUMPAGES field format switches (SD-2990)#3262

Open
luccas-harbour wants to merge 14 commits into
luccas/sd-2991-feature-oddeven-headers-and-footersfrom
luccas/sd-2990-feature-headerfooter-page-numbers
Open

feat: honor PAGE/NUMPAGES field format switches (SD-2990)#3262
luccas-harbour wants to merge 14 commits into
luccas/sd-2991-feature-oddeven-headers-and-footersfrom
luccas/sd-2990-feature-headerfooter-page-numbers

Conversation

@luccas-harbour
Copy link
Copy Markdown
Contributor

Summary

Parses \* general-format and \# numeric-picture switches when importing
PAGE/NUMPAGES fields and threads the requested format (Roman, alphabetic,
zero-padded decimal, dashed) plus the section-aware numeric page value
through the converter → pm-adapter → layout engine → DOM painter so page
number fields render in the format Word stored — not always decimal.

The original instruction text is preserved on the node so export round-trips
back to the same field code Word wrote.

Changes

Converter (super-editor)

  • New shared helper field-references/shared/page-number-field-switches.js parses
    \* Arabic|roman|ROMAN|alphabetic|ALPHABETIC|ArabicDash and \# 0000-style
    picture switches into { pageNumberFormat, pageNumberZeroPadding, instruction }.
  • page-preprocessor.js and num-pages-preprocessor.js now accept an options
    object ({ docx, instructionTokens, fieldRunRPr }) and emit those attrs on
    sd:autoPageNumber / sd:totalPageNumber. All sibling preprocessors updated
    to the new options-object signature for consistency.
  • autoPageNumber-translator / totalPageNumber-translator round-trip the
    attrs back to the original PAGE/NUMPAGES instruction on export and apply
    the format to the cached NUMPAGES export value.
  • PageNumber / TotalPageCount extensions gain instruction,
    pageNumberFormat, pageNumberZeroPadding attributes (all rendered: false).
  • HeaderFooterPerRidLayout resolver now also returns displayNumber (the
    section-aware numeric value) so non-decimal formats can be applied per page.

Contracts

  • New page-number-formatting.ts centralizes formatPageNumber /
    formatPageNumberFieldValue and the PageNumberFieldFormat /
    PageNumberFormat types. pageNumbering.ts in layout-engine now re-exports
    from contracts to keep the public surface stable.
  • TextRun gains pageNumberFieldFormat?: PageNumberFieldFormat.

pm-adapter

  • New getPageNumberFieldFormat() helper reads the node attrs and attaches
    pageNumberFieldFormat to token runs in both generic-token.ts and
    text-run.ts.

Layout bridge / engine

  • resolveHeaderFooterTokens and resolvePageNumberTokens apply the field
    format when present, falling back to the previous display text.
  • layoutHeaderFooter opts out of digit-bucketing for variants whose PAGE
    tokens use formats that don't share a digit-width budget (Roman, letters,
    zero-padded decimal). decimal and numberInDash still bucket.
  • Per-page displayNumber is plumbed through HeaderFooterLayout
    FragmentRenderContext → DOM painter so the painter formats per-page.

DOM painter

  • resolveRunText uses pageNumberFieldFormat + displayPageNumber to
    format PAGE / NUMPAGES tokens at render time when a format is set.

@luccas-harbour luccas-harbour requested a review from a team as a code owner May 13, 2026 12:30
@linear
Copy link
Copy Markdown

linear Bot commented May 13, 2026

SD-2990

@github-actions
Copy link
Copy Markdown
Contributor

The output structure (begin/instrText/separate/result/end runs with xml:space="preserve" on instrText) matches the OOXML complex field grammar. The PR is preserving the original field instruction text and re-emitting it verbatim, so spec validity depends on whether the instruction text being preserved is valid PAGE/NUMPAGES syntax. Looking at the changed files only:

Status: PASS

The two translators (autoPageNumber-translator.js for PAGE and totalPageNumber-translator.js for NUMPAGES) are SuperDoc-internal sd:* elements that round-trip OOXML field switch metadata. Their OOXML output looks correct:

  • The decode path emits a standard complex-field run sequence (w:fldChar begin → w:r/w:instrTextw:fldChar separate → optional w:t result → w:fldChar end), which matches ECMA-376 §17.16.18 w:instrText and §17.16.2 w:fldChar.
  • w:instrText carries xml:space="preserve" and the instruction has a leading space ( PAGE \* roman, NUMPAGES \# "00"), which is the canonical Word-produced form.
  • The preserved switches (\* general formatting, \# numeric picture) are documented for PAGE and NUMPAGES fields per §17.16.5 and the field switch tables (§17.16.4).
  • The encode path only reads custom attributes off the sd: internal element — no OOXML elements/attributes are introduced there.

No non-existent attributes, no missing required attributes, no incorrect defaults observed in the four changed files.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6157e5d222

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

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-commenter
Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@luccas-harbour luccas-harbour changed the base branch from main to luccas/sd-2991-feature-oddeven-headers-and-footers May 13, 2026 13:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants