Skip to content

Commit a8859df

Browse files
authored
fix(math): propagate paragraph spacing to display math blocks (SD-2409) (#2645)
1 parent 245c756 commit a8859df

6 files changed

Lines changed: 81 additions & 2 deletions

File tree

packages/layout-engine/pm-adapter/src/converters/math-block.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,34 @@ describe('handleMathBlockNode', () => {
8080
handleMathBlockNode(makeNode({ textContent: 'b' }) as any, context);
8181
expect(blocks[0].id).not.toBe(blocks[1].id);
8282
});
83+
84+
it('resolves paragraph spacing from paragraphProperties', () => {
85+
const { context, blocks } = makeContext();
86+
const node = makeNode({
87+
textContent: 'x',
88+
paragraphProperties: { spacing: { before: 240, after: 160, line: 276, lineRule: 'auto' } },
89+
});
90+
91+
handleMathBlockNode(node as any, context);
92+
93+
const block = blocks[0] as ParagraphBlock;
94+
expect(block.attrs?.spacing).toBeDefined();
95+
expect(block.attrs?.spacing?.before).toBeGreaterThan(0);
96+
expect(block.attrs?.spacing?.after).toBeGreaterThan(0);
97+
});
98+
99+
it('falls back to paragraph alignment when justification is unknown', () => {
100+
const { context, blocks } = makeContext();
101+
const node = makeNode({
102+
textContent: 'x',
103+
justification: 'unknown',
104+
paragraphProperties: { justification: 'right' },
105+
});
106+
107+
handleMathBlockNode(node as any, context);
108+
109+
const block = blocks[0] as ParagraphBlock;
110+
// When math justification is unknown, falls back to paragraphAttrs alignment
111+
expect(block.attrs?.alignment).toBeDefined();
112+
});
83113
});

packages/layout-engine/pm-adapter/src/converters/math-block.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { ParagraphBlock, MathRun } from '@superdoc/contracts';
22
import type { PMNode, NodeHandlerContext } from '../types.js';
33
import { estimateMathDimensions } from './math-constants.js';
4+
import { computeParagraphAttrs } from '../attributes/index.js';
45

56
const JUSTIFICATION_TO_ALIGN: Record<string, 'left' | 'center' | 'right'> = {
67
center: 'center',
@@ -32,12 +33,17 @@ export function handleMathBlockNode(node: PMNode, context: NodeHandlerContext):
3233
pmEnd: pos?.end,
3334
};
3435

36+
// Resolve paragraph spacing from the parent w:p's properties (carried via paragraphProperties attr).
37+
// This ensures display math paragraphs get the same spacing as their containing paragraph.
38+
const { paragraphAttrs } = computeParagraphAttrs(node, context.converterContext);
39+
3540
const block: ParagraphBlock = {
3641
kind: 'paragraph',
3742
id: nextBlockId('paragraph'),
3843
runs: [mathRun],
3944
attrs: {
40-
alignment: JUSTIFICATION_TO_ALIGN[justification] ?? 'center',
45+
...paragraphAttrs,
46+
alignment: JUSTIFICATION_TO_ALIGN[justification] ?? paragraphAttrs.alignment ?? 'center',
4147
},
4248
};
4349

packages/super-editor/src/editors/v1/core/super-converter/v2/importer/math/math-importer.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,15 @@ const handleMathPara = (params) => {
2929
const originalXml = carbonCopy(xmlNode);
3030
const textContent = extractMathText(xmlNode);
3131
const justification = extractJustification(xmlNode);
32+
// Use raw inline properties (not resolved) to match how regular paragraphs work.
33+
// The style-engine resolves them at render time via computeParagraphAttrs.
34+
const paragraphProperties = params.extraParams?.inlineParagraphProperties ?? null;
3235

3336
return {
3437
nodes: [
3538
{
3639
type: 'mathBlock',
37-
attrs: { originalXml, textContent, justification },
40+
attrs: { originalXml, textContent, justification, paragraphProperties },
3841
marks: [],
3942
},
4043
],

packages/super-editor/src/editors/v1/core/super-converter/v2/importer/math/math-importer.test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,41 @@ describe('mathNodeHandler', () => {
9999
const result = handler({ nodes: [oMathParaNode] });
100100
expect(result.nodes[0].attrs.justification).toBe('centerGroup');
101101
});
102+
103+
it('captures paragraphProperties from extraParams', () => {
104+
const oMathParaNode = {
105+
name: 'm:oMathPara',
106+
elements: [
107+
{
108+
name: 'm:oMath',
109+
elements: [{ name: 'm:r', elements: [{ name: 'm:t', elements: [{ type: 'text', text: 'z' }] }] }],
110+
},
111+
],
112+
};
113+
114+
const spacing = { before: 240, after: 160 };
115+
const result = handler({
116+
nodes: [oMathParaNode],
117+
extraParams: { inlineParagraphProperties: { spacing } },
118+
});
119+
120+
expect(result.nodes[0].attrs.paragraphProperties).toEqual({ spacing });
121+
});
122+
123+
it('sets paragraphProperties to null when extraParams is absent', () => {
124+
const oMathParaNode = {
125+
name: 'm:oMathPara',
126+
elements: [
127+
{
128+
name: 'm:oMath',
129+
elements: [{ name: 'm:r', elements: [{ name: 'm:t', elements: [{ type: 'text', text: 'w' }] }] }],
130+
},
131+
],
132+
};
133+
134+
const result = handler({ nodes: [oMathParaNode] });
135+
expect(result.nodes[0].attrs.paragraphProperties).toBeNull();
136+
});
102137
});
103138

104139
describe('non-math elements', () => {

packages/super-editor/src/editors/v1/core/super-converter/v3/handlers/w/p/helpers/legacy-handle-paragraph-node.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export const handleParagraphNode = (params) => {
147147
extraParams: {
148148
...params.extraParams,
149149
paragraphProperties: resolvedParagraphProperties,
150+
inlineParagraphProperties,
150151
numberingDefinedInline: Boolean(inlineParagraphProperties.numberingProperties),
151152
},
152153
path: [...(params.path || []), node],

packages/super-editor/src/editors/v1/extensions/math/math-block.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ export const MathBlock = Node.create({
3030
default: 'centerGroup',
3131
rendered: false,
3232
},
33+
paragraphProperties: {
34+
default: null,
35+
rendered: false,
36+
},
3337
};
3438
},
3539
});

0 commit comments

Comments
 (0)