diff --git a/docs/showcase/book.docx b/docs/showcase/book.docx index 2fa1eba..9e72df3 100644 Binary files a/docs/showcase/book.docx and b/docs/showcase/book.docx differ diff --git a/docs/showcase/book.odt b/docs/showcase/book.odt index c8b5110..db2c393 100644 Binary files a/docs/showcase/book.odt and b/docs/showcase/book.odt differ diff --git a/docs/showcase/newsletter.docx b/docs/showcase/newsletter.docx index df77edd..9a1b286 100644 Binary files a/docs/showcase/newsletter.docx and b/docs/showcase/newsletter.docx differ diff --git a/docs/showcase/newsletter.odt b/docs/showcase/newsletter.odt index f46e3d0..718a153 100644 Binary files a/docs/showcase/newsletter.odt and b/docs/showcase/newsletter.odt differ diff --git a/docs/showcase/thesis-review.docx b/docs/showcase/thesis-review.docx index eddb636..c4047cb 100644 Binary files a/docs/showcase/thesis-review.docx and b/docs/showcase/thesis-review.docx differ diff --git a/docs/showcase/thesis-review.odt b/docs/showcase/thesis-review.odt index fb85c56..f648ec2 100644 Binary files a/docs/showcase/thesis-review.odt and b/docs/showcase/thesis-review.odt differ diff --git a/docs/showcase/thesis.docx b/docs/showcase/thesis.docx index e091a95..1bf99f8 100644 Binary files a/docs/showcase/thesis.docx and b/docs/showcase/thesis.docx differ diff --git a/docs/showcase/thesis.odt b/docs/showcase/thesis.odt index 207ec08..36f6978 100644 Binary files a/docs/showcase/thesis.odt and b/docs/showcase/thesis.odt differ diff --git a/src/lib/math/mathml.ts b/src/lib/math/mathml.ts index 440dc6d..bef75ae 100644 --- a/src/lib/math/mathml.ts +++ b/src/lib/math/mathml.ts @@ -13,6 +13,8 @@ const esc = (s: string) => const TAG_BY_KIND: Record = { i: 'mi', n: 'mn', o: 'mo', f: 'mi' }; +const BRACKETS = /^[([{|‖⟨⌊⌈)\]}⟩⌋⌉]$/; + // A row that MathML needs as a single element (mfrac, msup, … each take exactly one // child per slot), so a multi-node row is wrapped in . function slot(n: MathNode): string { @@ -27,7 +29,9 @@ export function astToMathml(n: MathNode): string { if (n.kind === 'f') return `${esc(n.s)}`; // Multi-letter identifiers stay upright in MathML unless split, and a number // like 3.14 is one token — so emit the run whole and let the class pick the tag. - return `<${TAG_BY_KIND[n.kind]}>${esc(n.s)}`; + // A bracket typed without \left stays glyph-height; only a fence stretches. + const attr = n.kind === 'o' && BRACKETS.test(n.s) ? ' stretchy="false"' : ''; + return `<${TAG_BY_KIND[n.kind]}${attr}>${esc(n.s)}`; } case 'frac': return `${slot(n.num)}${slot(n.den)}`; case 'script': { diff --git a/tests/unit/math.test.ts b/tests/unit/math.test.ts index 4b70122..4491cf3 100644 --- a/tests/unit/math.test.ts +++ b/tests/unit/math.test.ts @@ -54,6 +54,8 @@ describe('MathML', () => { expect(astToMathml(parseLatex('\\int_{0}^{1} x'))).toContain(''); // Brackets must be stretchy or they stay glyph-height next to a fraction. expect(astToMathml(parseLatex('\\left(x\\right)'))).toContain('('); + // A plain bracket must not: the dictionary would stretch it to the row's tallest. + expect(astToMathml(parseLatex('C(b) = \\frac{1}{2}'))).toContain('('); }); it('round-trips through the document element', () => {