Skip to content

Commit c64ae5c

Browse files
🐛 fix: Fix latex
1 parent 1e20b00 commit c64ae5c

File tree

2 files changed

+147
-5
lines changed

2 files changed

+147
-5
lines changed

src/hooks/useMarkdown/latex.test.ts

Lines changed: 142 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,9 @@ describe('escapeCurrencyDollars', () => {
328328
// Our implementation conservatively treats closed $ pairs without
329329
// LaTeX commands as potential formulas
330330

331-
// LaTeX with closing $
332-
expect(escapeCurrencyDollars('$10$')).toBe('\\$10$'); // Current behavior
331+
// LaTeX with closing $ - treated as LaTeX, not currency
332+
expect(escapeCurrencyDollars('$10$')).toBe('$10$');
333+
expect(escapeCurrencyDollars('$100$')).toBe('$100$');
333334

334335
// Clear currency (no closing $)
335336
expect(escapeCurrencyDollars('$10 ')).toBe('\\$10 ');
@@ -427,6 +428,145 @@ describe('escapeCurrencyDollars', () => {
427428
const expected = 'Angle is $90^\\circ$ and price is \\$100';
428429
expect(escapeCurrencyDollars(content)).toBe(expected);
429430
});
431+
432+
test('preserves LaTeX expressions with number lists', () => {
433+
// Edge case: $1,-1,0$ should be treated as LaTeX, not currency
434+
const content = '$1,-1,0$';
435+
expect(escapeCurrencyDollars(content)).toBe(content);
436+
});
437+
438+
test('preserves LaTeX expressions with comma-separated values', () => {
439+
const content = 'The values $1,2,3$ and $x,y,z$ are valid';
440+
expect(escapeCurrencyDollars(content)).toBe(content);
441+
});
442+
443+
describe('edge cases', () => {
444+
test('handles negative numbers in LaTeX', () => {
445+
expect(escapeCurrencyDollars('$-1$')).toBe('$-1$');
446+
expect(escapeCurrencyDollars('$-10$')).toBe('$-10$');
447+
expect(escapeCurrencyDollars('$-100$')).toBe('$-100$');
448+
});
449+
450+
test('handles negative number lists', () => {
451+
expect(escapeCurrencyDollars('$-1,-2,-3$')).toBe('$-1,-2,-3$');
452+
expect(escapeCurrencyDollars('$1,-1,0$')).toBe('$1,-1,0$'); // Original bug
453+
expect(escapeCurrencyDollars('$-5,0,5$')).toBe('$-5,0,5$');
454+
});
455+
456+
test('handles mixed positive and negative numbers', () => {
457+
expect(escapeCurrencyDollars('$1,-2,3,-4$')).toBe('$1,-2,3,-4$');
458+
expect(escapeCurrencyDollars('$100,-50,0,25$')).toBe('$100,-50,0,25$');
459+
});
460+
461+
test('handles numbers with many commas', () => {
462+
expect(escapeCurrencyDollars('$1,2,3,4,5$')).toBe('$1,2,3,4,5$');
463+
expect(escapeCurrencyDollars('$10,20,30,40,50$')).toBe('$10,20,30,40,50$');
464+
});
465+
466+
test('distinguishes between LaTeX lists and currency thousands', () => {
467+
// LaTeX list: comma separates multiple numbers
468+
expect(escapeCurrencyDollars('$1,000$')).toBe('$1,000$');
469+
470+
// Currency with comma (no closing $)
471+
expect(escapeCurrencyDollars('$1,000 price')).toBe('\\$1,000 price');
472+
expect(escapeCurrencyDollars('$2,500 each')).toBe('\\$2,500 each');
473+
});
474+
475+
test('handles zero in various contexts', () => {
476+
expect(escapeCurrencyDollars('$0$')).toBe('$0$');
477+
expect(escapeCurrencyDollars('$0,1,2$')).toBe('$0,1,2$');
478+
expect(escapeCurrencyDollars('$-1,0,1$')).toBe('$-1,0,1$');
479+
});
480+
481+
test('handles single-digit formulas in complex text', () => {
482+
const content = 'If $n=1$ then $f(1)=0$ and $g(1)=2$';
483+
expect(escapeCurrencyDollars(content)).toBe(content);
484+
});
485+
486+
test('handles adjacent dollar signs correctly', () => {
487+
// Display math followed by inline math
488+
expect(escapeCurrencyDollars('$$x^2$$ and $y^2$')).toBe('$$x^2$$ and $y^2$');
489+
490+
// Should not confuse with currency
491+
expect(escapeCurrencyDollars('$$1,2,3$$ then $4,5,6$')).toBe('$$1,2,3$$ then $4,5,6$');
492+
});
493+
494+
test('handles large numbers in LaTeX', () => {
495+
expect(escapeCurrencyDollars('$1000$')).toBe('$1000$');
496+
expect(escapeCurrencyDollars('$10000$')).toBe('$10000$');
497+
expect(escapeCurrencyDollars('$999999$')).toBe('$999999$');
498+
});
499+
});
500+
501+
describe('comprehensive scenarios', () => {
502+
test('handles mathematical sequences', () => {
503+
const content = 'The sequence $1,-1,1,-1,1$ alternates between values';
504+
expect(escapeCurrencyDollars(content)).toBe(content);
505+
});
506+
507+
test('handles coordinate-like expressions', () => {
508+
expect(escapeCurrencyDollars('Point $1,0$ and $-1,0$')).toBe('Point $1,0$ and $-1,0$');
509+
expect(escapeCurrencyDollars('Origin $0,0,0$')).toBe('Origin $0,0,0$');
510+
});
511+
512+
test('handles mixed LaTeX numbers and text currency', () => {
513+
const content = 'The formula $1,2,3$ costs about $50 to compute';
514+
const expected = 'The formula $1,2,3$ costs about \\$50 to compute';
515+
expect(escapeCurrencyDollars(content)).toBe(expected);
516+
});
517+
518+
test('handles complex mathematical expressions with numbers', () => {
519+
const content = 'When $x \\in \\{1,2,3\\}$ the cost is $100';
520+
const expected = 'When $x \\in \\{1,2,3\\}$ the cost is \\$100';
521+
expect(escapeCurrencyDollars(content)).toBe(expected);
522+
});
523+
524+
test('handles multiple types of formulas in one text', () => {
525+
const content = 'Values $1,-1,0$ with $x^2$ and $90^\\circ$ cost $100';
526+
const expected = 'Values $1,-1,0$ with $x^2$ and $90^\\circ$ cost \\$100';
527+
expect(escapeCurrencyDollars(content)).toBe(expected);
528+
});
529+
530+
test('handles LaTeX in tables with currency', () => {
531+
const content = `| Formula | Values | Price |
532+
|---------|--------|-------|
533+
| $x^2$ | $1,2,3$ | $100 |
534+
| $y^2$ | $-1,0,1$ | $200 |`;
535+
536+
const result = escapeCurrencyDollars(content);
537+
538+
// LaTeX formulas should be preserved
539+
expect(result).toContain('$x^2$');
540+
expect(result).toContain('$1,2,3$');
541+
expect(result).toContain('$-1,0,1$');
542+
543+
// Currency should be escaped
544+
expect(result).toContain('\\$100');
545+
expect(result).toContain('\\$200');
546+
});
547+
548+
test('handles scientific notation-like patterns', () => {
549+
expect(escapeCurrencyDollars('$1,000,000$')).toBe('$1,000,000$');
550+
expect(escapeCurrencyDollars('$-1,000,000$')).toBe('$-1,000,000$');
551+
});
552+
553+
test('preserves complex number sequences', () => {
554+
const content = '$1,-2,3,-4,5,-6,7,-8,9$';
555+
expect(escapeCurrencyDollars(content)).toBe(content);
556+
});
557+
558+
test('handles formulas at start and end of text', () => {
559+
expect(escapeCurrencyDollars('$1,-1,0$ is a sequence')).toBe('$1,-1,0$ is a sequence');
560+
expect(escapeCurrencyDollars('The sequence is $1,-1,0$')).toBe('The sequence is $1,-1,0$');
561+
expect(escapeCurrencyDollars('$1,-1,0$')).toBe('$1,-1,0$');
562+
});
563+
564+
test('handles multiple currencies and formulas mixed', () => {
565+
const content = 'Buy $1,2,3$ items for $19.99, or $4,5,6$ items for $29.99';
566+
const expected = 'Buy $1,2,3$ items for \\$19.99, or $4,5,6$ items for \\$29.99';
567+
expect(escapeCurrencyDollars(content)).toBe(expected);
568+
});
569+
});
430570
});
431571

432572
describe('fixCommonLaTeXErrors', () => {

src/hooks/useMarkdown/latex.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,11 @@ export function escapeCurrencyDollars(text: string): string {
162162
// 2. Inline code: `...`
163163
// 3. Display math: $$...$$
164164
// 4. Inline math with LaTeX commands: $...\...$ (must contain backslash to distinguish from currency)
165-
// 5. LaTeX bracket notation: \[...\]
166-
// 6. LaTeX parenthesis notation: \(...\)
167-
/(```[\S\s]*?```|`[^\n`]*`|\$\$[\S\s]*?\$\$|(?<!\\)\$(?!\$)(?=[\S\s]*?\\)[\S\s]*?(?<!\\)\$(?!\$)|\\\[[\S\s]*?\\]|\\\(.*?\\\))/g,
165+
// 5. Simple number formulas: $1$, $10$, $100$ (pure digits in math mode)
166+
// 6. Number lists in math mode: $1,-1,0$ or $1,2,3$ (comma-separated numbers, possibly negative)
167+
// 7. LaTeX bracket notation: \[...\]
168+
// 8. LaTeX parenthesis notation: \(...\)
169+
/(```[\S\s]*?```|`[^\n`]*`|\$\$[\S\s]*?\$\$|(?<!\\)\$(?!\$)(?=[\S\s]*?\\)[\S\s]*?(?<!\\)\$(?!\$)|\$\d+\$|\$-?\d+(?:,-?\d+)+\$|\\\[[\S\s]*?\\]|\\\(.*?\\\))/g,
168170
(match) => manager.add(match),
169171
);
170172

0 commit comments

Comments
 (0)