import { test } from 'node:test'; import assert from 'node:assert/strict'; import { splitMathSegments } from './mathParse'; test('plain text with no dollars is a single text segment', () => { assert.deepEqual(splitMathSegments('hello world'), [{ type: 'text', value: 'hello world' }]); }); test('empty string yields no segments', () => { assert.deepEqual(splitMathSegments(''), []); }); test('inline $…$ is extracted between surrounding text', () => { assert.deepEqual(splitMathSegments('a $x^2$ b'), [ { type: 'text', value: 'a ' }, { type: 'inline', value: 'x^2' }, { type: 'text', value: ' b' }, ]); }); test('block $$…$$ is extracted', () => { assert.deepEqual(splitMathSegments('$$block$$'), [{ type: 'block', value: 'block' }]); }); test('block math may span newlines', () => { assert.deepEqual(splitMathSegments('$$\na=b\n$$'), [{ type: 'block', value: '\na=b\n' }]); }); test('currency "$5 and $10" is NOT treated as math', () => { assert.deepEqual(splitMathSegments('$5 and $10'), [{ type: 'text', value: '$5 and $10' }]); }); test('escaped \\$ never opens or closes math', () => { assert.deepEqual(splitMathSegments('cost \\$5 today'), [ { type: 'text', value: 'cost $5 today' }, ]); assert.deepEqual(splitMathSegments('\\$x\\$'), [{ type: 'text', value: '$x$' }]); }); test('unbalanced single $ stays as text', () => { assert.deepEqual(splitMathSegments('price is $ here'), [ { type: 'text', value: 'price is $ here' }, ]); }); test('unbalanced $$ stays as text', () => { assert.deepEqual(splitMathSegments('$$x'), [{ type: 'text', value: '$$x' }]); }); test('inline requires non-space adjacency on both delimiters', () => { // Space right after opening $ -> not math. assert.deepEqual(splitMathSegments('$ x$'), [{ type: 'text', value: '$ x$' }]); // Space right before closing $ -> not math. assert.deepEqual(splitMathSegments('$x $'), [{ type: 'text', value: '$x $' }]); }); test('multiple inline spans on one line', () => { assert.deepEqual(splitMathSegments('$a$ and $b$'), [ { type: 'inline', value: 'a' }, { type: 'text', value: ' and ' }, { type: 'inline', value: 'b' }, ]); }); test('escaped dollar inside inline math is preserved in LaTeX', () => { assert.deepEqual(splitMathSegments('$a\\$b$'), [{ type: 'inline', value: 'a\\$b' }]); }); test('closing $ followed by a digit is skipped (currency guard) then recovers', () => { // The first candidate closer is followed by `2` so it is skipped; the later // `$` closes the span. assert.deepEqual(splitMathSegments('$x$2 + y$'), [{ type: 'inline', value: 'x$2 + y' }]); }); test('block and inline mixed with text', () => { assert.deepEqual(splitMathSegments('see $$E=mc^2$$ and $a$ ok'), [ { type: 'text', value: 'see ' }, { type: 'block', value: 'E=mc^2' }, { type: 'text', value: ' and ' }, { type: 'inline', value: 'a' }, { type: 'text', value: ' ok' }, ]); });