Skip to content

Commit 6a945da

Browse files
fix(layout-bridge): skip missing even header refs
1 parent 07ed042 commit 6a945da

3 files changed

Lines changed: 73 additions & 9 deletions

File tree

packages/layout-engine/layout-bridge/src/headerFooterUtils.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -388,10 +388,16 @@ export function getHeaderFooterTypeForSection(
388388
}
389389

390390
if (identifier.alternateHeaders) {
391-
// Keep parity-based variant selection even when this section doesn't
392-
// explicitly define that variant. Resolution/inheritance happens later.
393391
if (!hasAny) return null;
394-
return parityPageNumber % 2 === 0 ? 'even' : 'odd';
392+
const parityVariant = parityPageNumber % 2 === 0 ? 'even' : 'odd';
393+
return resolveInheritedHeaderFooterRef({
394+
identifier,
395+
sectionIndex,
396+
kind,
397+
variantType: parityVariant,
398+
})
399+
? parityVariant
400+
: null;
395401
}
396402

397403
if (hasDefault) {

packages/layout-engine/layout-bridge/test/headerFooterUtils.test.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ describe('headerFooterUtils', () => {
855855
expect(evenPageHeader?.contentId).toBe('h0-even');
856856
});
857857

858-
it('does not use section default content id for even pages when alternate header even ref is missing', () => {
858+
it('does not resolve a header for even pages when alternate header even ref is missing', () => {
859859
const sectionMetadata: SectionMetadata[] = [
860860
{
861861
sectionIndex: 0,
@@ -881,11 +881,10 @@ describe('headerFooterUtils', () => {
881881
};
882882

883883
const evenPageHeader = resolveHeaderFooterForPageAndSection(layout, 1, identifier, { kind: 'header' });
884-
expect(evenPageHeader?.type).toBe('even');
885-
expect(evenPageHeader?.contentId).toBeNull();
884+
expect(evenPageHeader).toBeNull();
886885
});
887886

888-
it('keeps parity variant but does not infer default content id for missing alternate refs', () => {
887+
it('does not resolve a footer for even pages when alternate footer even ref is missing', () => {
889888
const sectionMetadata: SectionMetadata[] = [
890889
{
891890
sectionIndex: 0,
@@ -915,8 +914,7 @@ describe('headerFooterUtils', () => {
915914
};
916915

917916
const evenPageFooterId = resolveHeaderFooterForPageAndSection(layout, 1, identifier, { kind: 'footer' });
918-
expect(evenPageFooterId?.type).toBe('even');
919-
expect(evenPageFooterId?.contentId).toBeNull();
917+
expect(evenPageFooterId).toBeNull();
920918
});
921919

922920
it('keeps inherited parity selection when the current section has no explicit refs', () => {

packages/super-editor/src/editors/v1/core/presentation-editor/tests/HeaderFooterSessionManager.test.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -861,6 +861,66 @@ describe('HeaderFooterSessionManager', () => {
861861
expect(payload!.items![0]!.blockId).toBe('default-block');
862862
});
863863

864+
it('does not render default headers on even pages when alternate headers are enabled', () => {
865+
const deps: SessionManagerDependencies = {
866+
getLayoutOptions: vi.fn(() => ({})),
867+
getPageElement: vi.fn(() => null),
868+
scrollPageIntoView: vi.fn(),
869+
waitForPageMount: vi.fn(async () => true),
870+
convertPageLocalToOverlayCoords: vi.fn(() => ({ x: 0, y: 0 })),
871+
isViewLocked: vi.fn(() => false),
872+
getBodyPageHeight: vi.fn(() => 800),
873+
notifyInputBridgeTargetChanged: vi.fn(),
874+
scheduleRerender: vi.fn(),
875+
setPendingDocChange: vi.fn(),
876+
getBodyPageCount: vi.fn(() => 2),
877+
};
878+
879+
manager = new HeaderFooterSessionManager({
880+
painterHost,
881+
visibleHost,
882+
selectionOverlay,
883+
editor: createMainEditorStub(),
884+
defaultPageSize: { w: 612, h: 792 },
885+
defaultMargins: { top: 72, right: 72, bottom: 72, left: 72, header: 36, footer: 36 },
886+
});
887+
manager.setDependencies(deps);
888+
manager.setMultiSectionIdentifier(
889+
buildMultiSectionIdentifier([{ sectionIndex: 0, headerRefs: { default: 'rId-header-default' } }], {
890+
alternateHeaders: true,
891+
}),
892+
);
893+
manager.setLayoutResults([buildHeaderResult({ type: 'even', blockId: 'even-block', pageNumber: 2 })], null);
894+
895+
const layout: Layout = {
896+
version: 1,
897+
flowMode: 'paginated',
898+
pageGap: 0,
899+
pageSize: { w: 612, h: 792 },
900+
pages: [
901+
{
902+
number: 1,
903+
sectionIndex: 0,
904+
margins: { top: 72, right: 72, bottom: 72, left: 72, header: 36, footer: 36 },
905+
},
906+
{
907+
number: 2,
908+
sectionIndex: 0,
909+
margins: { top: 72, right: 72, bottom: 72, left: 72, header: 36, footer: 36 },
910+
sectionRefs: {
911+
headerRefs: { default: 'rId-header-default' },
912+
footerRefs: {},
913+
},
914+
},
915+
] as never,
916+
} as unknown as Layout;
917+
918+
const provider = manager.createDecorationProvider('header', layout as unknown as ResolvedLayout);
919+
const payload = provider!(2, layout.pages[1]!.margins, layout.pages[1] as unknown as ResolvedPage);
920+
921+
expect(payload).toBeNull();
922+
});
923+
864924
it('normalizes resolved items when per-rId layout minY is negative', async () => {
865925
mockLayoutPerRIdHeaderFooters.mockImplementation(
866926
async (

0 commit comments

Comments
 (0)