Skip to content

Commit e0b7e23

Browse files
committed
test(super-editor): add fontSize style chain resolution tests for blocks.list
1 parent 20a1341 commit e0b7e23

1 file changed

Lines changed: 176 additions & 0 deletions

File tree

packages/super-editor/src/editors/v1/document-api-adapters/plan-engine/blocks-wrappers.test.ts

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,182 @@ describe('blocksListWrapper', () => {
635635
expect(block.styleId).toBe('Heading1');
636636
expect(block.headingLevel).toBe(1);
637637
});
638+
639+
it('resolves fontSize from Normal style when inline marks have no fontSize', () => {
640+
const textNode = createNode('text', [], {
641+
text: 'No inline fontSize',
642+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Times New Roman' } }],
643+
});
644+
const paragraph = createNode('paragraph', [textNode], {
645+
attrs: { paraId: 'p1', sdBlockId: 'p1' },
646+
isBlock: true,
647+
inlineContent: true,
648+
});
649+
const doc = createNode('doc', [paragraph], { isBlock: false });
650+
// Mock editor with converter that has translatedLinkedStyles
651+
const editor = {
652+
state: { doc },
653+
converter: {
654+
translatedLinkedStyles: {
655+
docDefaults: { runProperties: { fontSize: 24 } },
656+
latentStyles: {},
657+
styles: {
658+
Normal: { runProperties: { fontSize: 20 } },
659+
},
660+
},
661+
},
662+
} as unknown as Editor;
663+
664+
const result = blocksListWrapper(editor);
665+
const block = result.blocks[0] as any;
666+
// Normal style has fontSize 20 half-points = 10pt
667+
expect(block.fontSize).toBe(10);
668+
});
669+
670+
it('resolves fontSize from basedOn chain when block has a styleId', () => {
671+
const textNode = createNode('text', [], {
672+
text: 'Heading text',
673+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Times New Roman' } }],
674+
});
675+
const paragraph = createNode('paragraph', [textNode], {
676+
attrs: { paraId: 'p1', sdBlockId: 'p1', paragraphProperties: { styleId: 'Heading1' } },
677+
isBlock: true,
678+
inlineContent: true,
679+
});
680+
const doc = createNode('doc', [paragraph], { isBlock: false });
681+
const editor = {
682+
state: { doc },
683+
converter: {
684+
translatedLinkedStyles: {
685+
docDefaults: { runProperties: { fontSize: 20 } },
686+
latentStyles: {},
687+
styles: {
688+
Normal: { runProperties: { fontSize: 20 } },
689+
Heading1: { basedOn: 'Normal', runProperties: { fontSize: 28 } },
690+
},
691+
},
692+
},
693+
} as unknown as Editor;
694+
695+
const result = blocksListWrapper(editor);
696+
const block = result.blocks[0] as any;
697+
// Heading1 has fontSize 28 half-points = 14pt
698+
expect(block.fontSize).toBe(14);
699+
});
700+
701+
it('walks basedOn chain when style has no fontSize', () => {
702+
const textNode = createNode('text', [], {
703+
text: 'List text',
704+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Arial' } }],
705+
});
706+
const paragraph = createNode('paragraph', [textNode], {
707+
attrs: { paraId: 'p1', sdBlockId: 'p1', paragraphProperties: { styleId: 'ListParagraph' } },
708+
isBlock: true,
709+
inlineContent: true,
710+
});
711+
const doc = createNode('doc', [paragraph], { isBlock: false });
712+
const editor = {
713+
state: { doc },
714+
converter: {
715+
translatedLinkedStyles: {
716+
docDefaults: {},
717+
latentStyles: {},
718+
styles: {
719+
Normal: { runProperties: { fontSize: 22 } },
720+
ListParagraph: { basedOn: 'Normal', runProperties: {} },
721+
},
722+
},
723+
},
724+
} as unknown as Editor;
725+
726+
const result = blocksListWrapper(editor);
727+
const block = result.blocks[0] as any;
728+
// ListParagraph has no fontSize, basedOn Normal which has 22 hp = 11pt
729+
expect(block.fontSize).toBe(11);
730+
});
731+
732+
it('falls back to docDefaults when no style defines fontSize', () => {
733+
const textNode = createNode('text', [], {
734+
text: 'Default text',
735+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Calibri' } }],
736+
});
737+
const paragraph = createNode('paragraph', [textNode], {
738+
attrs: { paraId: 'p1', sdBlockId: 'p1' },
739+
isBlock: true,
740+
inlineContent: true,
741+
});
742+
const doc = createNode('doc', [paragraph], { isBlock: false });
743+
const editor = {
744+
state: { doc },
745+
converter: {
746+
translatedLinkedStyles: {
747+
docDefaults: { runProperties: { fontSize: 24 } },
748+
latentStyles: {},
749+
styles: { Normal: { runProperties: {} } },
750+
},
751+
},
752+
} as unknown as Editor;
753+
754+
const result = blocksListWrapper(editor);
755+
const block = result.blocks[0] as any;
756+
// docDefaults has fontSize 24 hp = 12pt
757+
expect(block.fontSize).toBe(12);
758+
});
759+
760+
it('falls back to 10pt OOXML default when nothing defines fontSize', () => {
761+
const textNode = createNode('text', [], {
762+
text: 'Bare text',
763+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Courier' } }],
764+
});
765+
const paragraph = createNode('paragraph', [textNode], {
766+
attrs: { paraId: 'p1', sdBlockId: 'p1' },
767+
isBlock: true,
768+
inlineContent: true,
769+
});
770+
const doc = createNode('doc', [paragraph], { isBlock: false });
771+
const editor = {
772+
state: { doc },
773+
converter: {
774+
translatedLinkedStyles: {
775+
docDefaults: {},
776+
latentStyles: {},
777+
styles: {},
778+
},
779+
},
780+
} as unknown as Editor;
781+
782+
const result = blocksListWrapper(editor);
783+
const block = result.blocks[0] as any;
784+
expect(block.fontSize).toBe(10);
785+
});
786+
787+
it('inline fontSize takes precedence over style chain', () => {
788+
const textNode = createNode('text', [], {
789+
text: 'Explicit size',
790+
marks: [{ type: { name: 'textStyle' }, attrs: { fontFamily: 'Arial', fontSize: 16 } }],
791+
});
792+
const paragraph = createNode('paragraph', [textNode], {
793+
attrs: { paraId: 'p1', sdBlockId: 'p1', paragraphProperties: { styleId: 'Heading1' } },
794+
isBlock: true,
795+
inlineContent: true,
796+
});
797+
const doc = createNode('doc', [paragraph], { isBlock: false });
798+
const editor = {
799+
state: { doc },
800+
converter: {
801+
translatedLinkedStyles: {
802+
docDefaults: { runProperties: { fontSize: 20 } },
803+
latentStyles: {},
804+
styles: { Heading1: { runProperties: { fontSize: 28 } } },
805+
},
806+
},
807+
} as unknown as Editor;
808+
809+
const result = blocksListWrapper(editor);
810+
const block = result.blocks[0] as any;
811+
// Inline fontSize 16 takes precedence over Heading1's 28hp (14pt)
812+
expect(block.fontSize).toBe(16);
813+
});
638814
});
639815

640816
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)