Skip to content

Commit c4258a6

Browse files
committed
webui: LaTeX-line-break in display formula
1 parent 8678f6a commit c4258a6

File tree

4 files changed

+38
-1
lines changed

4 files changed

+38
-1
lines changed

tools/server/webui/src/lib/constants/latex-protection.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ export const CODE_BLOCK_REGEXP = /(```[\s\S]*?```|`[^`\n]+`)/g;
2525
export const LATEX_MATH_AND_CODE_PATTERN =
2626
/(```[\S\s]*?```|`.*?`)|(?<!\\)\\\[([\S\s]*?[^\\])\\]|(?<!\\)\\\((.*?)\\\)/g;
2727

28+
/** Regex to capture the content of a $$...\\\\...$$ block (display-formula with line-break) */
29+
export const LATEX_LINEBREAK_REGEXP = /\$\$([\s\S]*?\\\\[\s\S]*?)\$\$/;
30+
2831
/** map from mchem-regexp to replacement */
2932
export const MHCHEM_PATTERN_MAP: readonly [RegExp, string][] = [
3033
[/(\s)\$\\ce{/g, '$1$\\\\ce{'],

tools/server/webui/src/lib/utils/latex-protection.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,23 @@ $$`
272272
// $5 becomes \$5 only *after* real math is masked — but here it's correct because the masking logic avoids treating $5 as math.
273273
});
274274

275+
test('display with LaTeX-line-breaks', () => {
276+
const input = String.raw`- Algebraic topology, Homotopy Groups of $\mathbb{S}^3$:
277+
$$\pi_n(\mathbb{S}^3) = \begin{cases}
278+
\mathbb{Z} & n = 3 \\
279+
0 & n > 3, n \neq 4 \\
280+
\mathbb{Z}_2 & n = 4 \\
281+
\end{cases}$$`;
282+
const output = preprocessLaTeX(input);
283+
// If the formula contains '\\' the $$-delimiters should be in their own line.
284+
expect(output).toBe(`- Algebraic topology, Homotopy Groups of $\\mathbb{S}^3$:
285+
$$\n\\pi_n(\\mathbb{S}^3) = \\begin{cases}
286+
\\mathbb{Z} & n = 3 \\\\
287+
0 & n > 3, n \\neq 4 \\\\
288+
\\mathbb{Z}_2 & n = 4 \\\\
289+
\\end{cases}\n$$`);
290+
});
291+
275292
test('handles mhchem notation safely if present', () => {
276293
const input = 'Chemical reaction: \\( \\ce{H2O} \\) and $\\ce{CO2}$';
277294
const output = preprocessLaTeX(input);

tools/server/webui/src/lib/utils/latex-protection.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
CODE_BLOCK_REGEXP,
33
LATEX_MATH_AND_CODE_PATTERN,
4+
LATEX_LINEBREAK_REGEXP,
45
MHCHEM_PATTERN_MAP
56
} from '$lib/constants/latex-protection';
67

@@ -198,7 +199,17 @@ export function preprocessLaTeX(content: string): string {
198199

199200
// Step 4: Restore protected LaTeX expressions (they are valid)
200201
content = content.replace(/<<LATEX_(\d+)>>/g, (_, index) => {
201-
return latexExpressions[parseInt(index)];
202+
let expr = latexExpressions[parseInt(index)];
203+
const match = expr.match(LATEX_LINEBREAK_REGEXP);
204+
if (match) {
205+
// Katex: The $$-delimiters should be in their own line
206+
// if there are \\-line-breaks.
207+
const formula = match[1];
208+
const prefix = formula.startsWith('\n') ? '' : '\n';
209+
const suffix = formula.endsWith('\n') ? '' : '\n';
210+
expr = '$$' + prefix + formula + suffix + '$$';
211+
}
212+
return expr;
202213
});
203214

204215
// Step 5: Restore code blocks

tools/server/webui/src/stories/fixtures/math-formulas.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ x = \frac{-b \pm \sqrt{\,b^{2}-4ac\,}}{2a}
174174
- Algebra: \[
175175
x = \frac{-b \pm \sqrt{\,b^{2}-4ac\,}}{2a}
176176
\]
177+
- Algebraic topology, Homotopy Groups of $\mathbb{S}^3$:
178+
$$\pi_n(\mathbb{S}^3) = \begin{cases}
179+
\mathbb{Z} & n = 3 \\
180+
0 & n > 3, n \neq 4 \\
181+
\mathbb{Z}_2 & n = 4 \\
182+
\end{cases}$$
177183
- Spacer preceded by backslash:
178184
\[
179185
\boxed{

0 commit comments

Comments
 (0)