fix(header-footer): centralize OOXML ref inheritance for first-page headers (SD-2997)#3264
Conversation
…regions When inferring header/footer region variants without explicit instance metadata, the fallback path only consulted the document-level titlePg flag. Multi-section documents that override titlePg per section ended up classifying the first page as 'default' instead of 'first'. Use the multi-section identifier's sectionTitlePg map when available so each section's variant is respected.
Extract the OOXML header/footer ref inheritance logic into a shared helper (`resolveInheritedHeaderFooterRef`) in `@superdoc/contracts` and use it from layout-engine, layout-bridge, and HeaderFooterSessionManager. This replaces three near-duplicate copies of the same resolution rules. While unifying the logic, fix inheritance through intermediate sections that omit `first`/`even` refs: previously the resolver only looked at the immediately prior section, so a `first` ref defined in section 0 was lost once section 1 (with only a `default` ref) sat between section 0 and a later section that also lacked an explicit `first` ref. The shared resolver now walks back to the nearest prior section that defines the requested variant.
|
Status: PASS The two translator files change how What the PR emits on the OOXML side:
Switch handling (verified against §17.16.4.1 general-format and §17.16.4.2 numeric-formatting):
The custom attributes ( No spec violations found. |
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
Summary
Fixes SD-2997 (different first-page headers) by centralizing the OOXML
header/footer ref inheritance rules into a single helper and pointing the
three places that used to re-implement them at the shared implementation.
Along the way, this corrects several inheritance bugs that broke
firstand
evenvariants in multi-section documents.What changed
@superdoc/contractshelper —resolveInheritedHeaderFooterRef/
resolveInheritedHeaderFooterRefWithTypeencode the OOXML resolutionorder (page refs → current section → walk back to the nearest prior
section that defines the variant → legacy identifier) plus the rule
that
oddmay fall back todefaultbut never vice-versa whenw:evenAndOddHeadersis enabled.layout-engine/index.ts,layout-bridge/headerFooterUtils.ts, andHeaderFooterSessionManager.tsnow delegate to the shared helperinstead of carrying three near-duplicate copies of the rules.
only consulted the immediately prior section, so a
firstref definedin section 0 was lost once section 1 (with only
default) sat betweenit and a later section that also lacked an explicit
firstref. Theshared resolver now scans back to the nearest prior section that
defines the requested variant.
calculation in
layout-enginenow uses the resolved variant(
headerResolution.variantType) for the height lookup, so inheriteddefault refs don't end up sized against a non-existent variant slot.
titlePghonored in the fallback path —HeaderFooterSessionManagerwas classifying first pages with thedocument-level
titlePgflag only; multi-section docs that overridetitlePgper section now consult the section's own value via themulti-section identifier's
sectionTitlePgmap.getHeaderFooterTypeForSectionnow returns
nullwhen neither the section nor its ancestors define ausable ref for the chosen parity (or default), so missing even-page
headers no longer render as the odd/default ref.
@superdoc/contractsinheritance helpers no longer let a later section's empty refs shadow
an earlier section's resolved ones during fallback computation.
Tests
header-footer-inheritance.test.tsincontractscovering thewalk-back, parity, and
odd → defaultfallback rules.headerFooterUtils.test.tsandlayout-engine/index.test.tsto assert the resolved variant flows through to height and margin
calculations.
HeaderFooterSessionManager.test.tsto cover theper-section
titlePgdecoration path, including the missing-map case.