fix(frontend): silence noisy KaTeX warning on Unicode symbols in math spans - #1208
fix(frontend): silence noisy KaTeX warning on Unicode symbols in math spans#1208bitsandbots wants to merge 2 commits into
Conversation
AI-generated content often contains Unicode punctuation (en/em dashes,
smart quotes) inside single-dollar math spans, e.g. a price range like
"$5 – $10". Models legitimately emit inline math as $...$ per this
project's own prompts ("MATH FORMATTING" sections), so remark-math
correctly reads it as math - but KaTeX's default strict mode then logs
a console warning for every character outside its symbol table.
The warning is harmless (KaTeX still renders a best-effort glyph) but
noisy: 66+ occurrences in a few days of normal use on one deployment.
Fix: pass KaTeX's own `strict` option as a function that ignores only
the `unknownSymbol` error code, leaving every other strict check (e.g.
deprecated commands) at its default. All three markdown-rendering call
sites (chat/insight/source rendering, the note editor live preview,
and the transformation playground) now share one KATEX_OPTIONS
constant instead of duplicating the same override three times.
Verified: 140/140 frontend tests pass (including the existing test
that asserts single-dollar inline math still renders via KaTeX),
tsc --noEmit clean, eslint clean (0 errors), production build clean.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
There was a problem hiding this comment.
1 issue found across 4 files
Confidence score: 4/5
- In
frontend/src/components/ui/markdown-editor.tsx, the Unicode-warning fix is unprotected by a regression test, so a later refactor could reintroduce KaTeX warnings without failing the existing math-rendering test, leading to noisy preview behavior slipping into production — add a focused preview regression test (e.g.,$5 – $1...) that asserts warnings stay suppressed.
You’re at about 99% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/ui/markdown-editor.tsx">
<violation number="1" location="frontend/src/components/ui/markdown-editor.tsx:51">
P2: The Unicode-warning fix has no regression test for the behavior it changes, so future edits can reintroduce KaTeX warnings while the current math-rendering test still passes. A preview test for a case such as `$5 – $10$` should assert that the expected KaTeX warning is absent while a non-`unknownSymbol` strict warning remains covered.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| export const PREVIEW_OPTIONS = { | ||
| remarkPlugins: [remarkMath] as PluggableList, | ||
| rehypePlugins: [[rehypeSanitize, SANITIZE_SCHEMA], rehypeKatex] as PluggableList, | ||
| rehypePlugins: [[rehypeSanitize, SANITIZE_SCHEMA], [rehypeKatex, KATEX_OPTIONS]] as PluggableList, |
There was a problem hiding this comment.
P2: The Unicode-warning fix has no regression test for the behavior it changes, so future edits can reintroduce KaTeX warnings while the current math-rendering test still passes. A preview test for a case such as $5 – $10$ should assert that the expected KaTeX warning is absent while a non-unknownSymbol strict warning remains covered.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/ui/markdown-editor.tsx, line 51:
<comment>The Unicode-warning fix has no regression test for the behavior it changes, so future edits can reintroduce KaTeX warnings while the current math-rendering test still passes. A preview test for a case such as `$5 – $10$` should assert that the expected KaTeX warning is absent while a non-`unknownSymbol` strict warning remains covered.</comment>
<file context>
@@ -46,7 +48,7 @@ const SANITIZE_SCHEMA = {
export const PREVIEW_OPTIONS = {
remarkPlugins: [remarkMath] as PluggableList,
- rehypePlugins: [[rehypeSanitize, SANITIZE_SCHEMA], rehypeKatex] as PluggableList,
+ rehypePlugins: [[rehypeSanitize, SANITIZE_SCHEMA], [rehypeKatex, KATEX_OPTIONS]] as PluggableList,
}
</file context>
Per cubic's review on this PR: - Add a regression test asserting the em/en-dash-in-price-range pattern that motivated this fix produces no [unknownSymbol] warning, and a second test asserting a different strict violation ([commentAtEnd]) is still warned on - proving the ignore is scoped to exactly one error code, not silently widened. - Reword the KATEX_OPTIONS comment: suppressing unknownSymbol isn't purely cosmetic. KaTeX's own parser falls back unrecognized codepoints to mode: 'text' rather than proper math-mode metrics, so an ignored symbol can render with approximated spacing rather than a real glyph. Acceptable for stray punctuation, not a blanket license to route arbitrary Unicode through math mode. Verified: 142/142 frontend tests pass (up from 140 - the two new tests), tsc --noEmit clean, eslint clean (0 errors). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Addressed both points in 6ce7c00:
142/142 frontend tests pass (up from 140), |
There was a problem hiding this comment.
1 issue found across 2 files (changes from recent commits).
Confidence score: 4/5
- In
frontend/src/components/ui/markdown-editor.test.tsx, the warning filter appears to expect bracketed codes (e.g.,[unknownSymbol]) while KaTeX warns asKaTeX <code>: ..., so the test can pass for the wrong reason and miss real parsing-warning behavior changes; align the matcher with KaTeX’s actual warning format (or assert on both formats) to de-risk false positives.
You’re at about 99% of the monthly reviewed-line limit. You may want to disable incremental reviews to conserve quota. Reviews will continue until that limit is exceeded. If you need help avoiding interruptions, please contact contact@cubic.dev.
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="frontend/src/components/ui/markdown-editor.test.tsx">
<violation number="1" location="frontend/src/components/ui/markdown-editor.test.tsx:77">
P2: The bracket-wrapped error code filter (`[unknownSymbol]`, `[commentAtEnd]`) may not match KaTeX's actual console.warn format, which uses `KaTeX <code>: <message>` without brackets. If so, the first test passes trivially (no filter match even when warnings exist) and the second fails. Suggest checking the actual format by inspecting KaTeX's Settings.reportError or running the tests once. If format lacks brackets, the test would need updated assertion strings.</violation>
</file>
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
| const warn = vi.spyOn(console, 'warn').mockImplementation(() => {}) | ||
| renderPreview('Price range: $5 – $10') | ||
| const unknownSymbolWarnings = warn.mock.calls.filter(([msg]) => | ||
| typeof msg === 'string' && msg.includes('[unknownSymbol]') |
There was a problem hiding this comment.
P2: The bracket-wrapped error code filter ([unknownSymbol], [commentAtEnd]) may not match KaTeX's actual console.warn format, which uses KaTeX <code>: <message> without brackets. If so, the first test passes trivially (no filter match even when warnings exist) and the second fails. Suggest checking the actual format by inspecting KaTeX's Settings.reportError or running the tests once. If format lacks brackets, the test would need updated assertion strings.
Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At frontend/src/components/ui/markdown-editor.test.tsx, line 77:
<comment>The bracket-wrapped error code filter (`[unknownSymbol]`, `[commentAtEnd]`) may not match KaTeX's actual console.warn format, which uses `KaTeX <code>: <message>` without brackets. If so, the first test passes trivially (no filter match even when warnings exist) and the second fails. Suggest checking the actual format by inspecting KaTeX's Settings.reportError or running the tests once. If format lacks brackets, the test would need updated assertion strings.</comment>
<file context>
@@ -58,6 +58,37 @@ describe('MarkdownEditor preview sanitization', () => {
+ const warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
+ renderPreview('Price range: $5 – $10')
+ const unknownSymbolWarnings = warn.mock.calls.filter(([msg]) =>
+ typeof msg === 'string' && msg.includes('[unknownSymbol]')
+ )
+ expect(unknownSymbolWarnings).toHaveLength(0)
</file context>
Summary
AI-generated content often contains Unicode punctuation (en/em dashes, smart quotes) inside single-dollar math spans — e.g. a price range like
$5 – $10. Models legitimately emit inline math as$...$per this project's own prompts (prompts/*/system.jinja"MATH FORMATTING" sections), soremark-mathcorrectly reads that as inline math. KaTeX's default strict mode then logs a console warning for every character outside its symbol table (the en-dash, in this example).The warning is harmless — KaTeX still renders a best-effort glyph — but noisy: I saw 66+ occurrences in a few days of normal self-hosted use.
Fix
Pass KaTeX's own
strictoption as a function that ignores only theunknownSymbolerror code, leaving every other strict check (e.g. deprecated commands) at its default. Extracted to one sharedKATEX_OPTIONSconstant (frontend/src/lib/utils/katex-options.ts) so the three markdown-rendering call sites (chat/insight/source rendering viamarkdown-renderer.tsx, the note editor live preview viamarkdown-editor.tsx, and the transformation playground) don't each duplicate the same override.An earlier version of this fix disabled
remark-math'ssingleDollarTextMathoption instead — that was wrong, since it breaks the intentional single-dollar inline math this project's prompts already rely on (caught by the existing KaTeX render test before it went further).Test plan
npm run test -- --run— 140/140 pass, including the existing test asserting single-dollar inline math ($x^2 + y^2 = z^2$) still renders via KaTeXnpx tsc --noEmit— cleannpm run lint— 0 errors (pre-existing unrelated warnings only)npm run build— clean production build$5 – $10(the exact failure pattern) renders with zero console warnings, while$x^2+y^2=z^2$and$$\int_0^1 x^2\,dx=\frac13$$still render correctly via KaTeX/MathML🤖 Generated with Claude Code