Skip to content

Render LaTeX math in chat via vendored KaTeX 0.18.1 - #222

Open
leonidasbarkas98-cpu wants to merge 8 commits into
andrepimenta:mainfrom
leonidasbarkas98-cpu:feat/latex-katex-rendering
Open

leonidasbarkas98-cpu wants to merge 8 commits into
andrepimenta:mainfrom
leonidasbarkas98-cpu:feat/latex-katex-rendering

Conversation

@leonidasbarkas98-cpu

Copy link
Copy Markdown

Renders LaTeX math in chat messages using vendored KaTeX 0.18.1, toggleable via a new claudeCodeChat.ui.renderMath setting.

  • A self-contained delimiter scanner (findMathSegments) locates $...$, $$...$$, \(...\) and \[...\] math spans in message text before markdown processing runs, guarding against common false positives (price mentions like "$5 and $10", shell variables like $PATH/$$, and math spans that overlap a fenced code block, which are left untouched).
  • Each located span is rendered via katex.renderToString with trust: false and throwOnError: false (no HTML injection through LaTeX macros; a render failure falls back to the escaped raw source instead of breaking the message).
  • KaTeX 0.18.1 (JS, CSS, 20 web fonts, MIT license) is vendored under assets/katex/ and copied into out/katex/ at build time; served through the webview's own resource URI scheme, which the existing localResourceRoots already covers.
  • A build/check-webview-syntax.js gate (new, npm run check-webview-syntax) parses the generated webview <script> block with a real AST parser and asserts a few load-bearing invariants (e.g. that the code-block-restore call site is present and safe) that no other check would otherwise catch on a .toString()-spliced script.
  • Along the way, found and fixed a real latent bug the math-delimiter work surfaced: the existing code-block-restore step (parseSimpleMarkdown) used String.prototype.replace(placeholder, htmlString), which interprets $-sequences in the replacement text ($&, $`, $', $$) as replacement patterns — a code block containing one of these sequences could splice already-rendered HTML from elsewhere in the message across block boundaries. Fixed by switching to a function replacer, which performs a literal substitution.

This is one of several PRs from our fork submitted together as part of a broader, thematically grouped series (permission/session handling, settings/UI, security hardening, rendering, etc. split across separate branches/PRs). This branch is based directly on current main (ab6e307) and does not stack on any other PR in the series, though src/markdown-restore.ts (introduced here) also appears independently, with slightly different content, in the security-hardening PR of this series — a merge conflict is expected if both are merged.

tsc --noEmit clean, no new runtime dependencies (KaTeX is vendored, not an npm dependency).

🤖 Generated with Claude Code

Jonas Kunert and others added 8 commits July 28, 2026 13:03
…1 and build/test infrastructure

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… toggle

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replacement strings containing $&, $`, $' or $$ were interpreted as
special replacement patterns by String.replace, corrupting restored code
blocks. Extract the restore loop into markdown-restore.ts using a
function replacement (same pattern as restoreMathSegments, introduced for
the LaTeX-rendering feature), add test:markdown-restore (9 tests,
red-green verified) and a check-webview-syntax assertion guarding the
call site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nal tracker references

Cleans up leftover German-language documentation and comments plus bare
internal issue-tracker references (andrepimenta#47/andrepimenta#55) that do not belong in a PR
against an English upstream repo. Pure text change, no behavior affected.
…plan references

math-segments.test.ts had German-language test titles and fixtures that
escaped an earlier umlaut-based grep because they used ASCII transliteration
("fuer", "beruehmt"). Translated all of them to English, recomputing the one
offset-based assertion whose expected start/end positions changed because the
replacement prose has a different length than the German original.

Also removes internal review-round shorthand labels from math-segments.ts,
math-segments.test.ts and ui-styles.ts comments and suite/test names,
replacing them with neutral descriptions of what each guard actually
verifies. Pure text change, no behavior affected (71/71 tests still
passing, same count as before).
script.ts had four comments still carrying an internal planning label
with no meaning for readers outside this fork. Removed it; text-only
change, no behavior affected.
Several comments cited neighbouring-file analogies (diff-utils.ts,
shell-utils.ts, auto-model-switch.ts, collapse-rules.ts, html-escape.ts)
that don't exist on this branch -- leftovers from a shared comment
template reused across branches. Corrected each to name only modules
that actually exist here (model-updater.ts, math-segments.ts,
math-script.ts) or dropped the file list where a neutral description
was clearer. Text-only change, no behavior affected.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant