Skip to content

feat: render LaTeX math in chat markdown (THU-606)#999

Open
darkbanjo wants to merge 1 commit into
mainfrom
jkab/thu-606-generalize-latex-math-rendering
Open

feat: render LaTeX math in chat markdown (THU-606)#999
darkbanjo wants to merge 1 commit into
mainfrom
jkab/thu-606-generalize-latex-math-rendering

Conversation

@darkbanjo

@darkbanjo darkbanjo commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator

What

Generalizes the LaTeX/math rendering prototyped on the OUP demo branch into a standard chat-markdown feature — no demo-specific coupling.

  • Wires remark-math + rehype-katex into the shared MemoizedMarkdown renderer and ships the KaTeX stylesheet on the chat critical path.
  • Adds normalizeDisplayMath: promotes a whole-line $$…$$ equation to fenced display math (models routinely emit standalone equations on one line). Inline $…$, mid-sentence $$…$$, and already-fenced blocks are left untouched.
  • Adds katex, rehype-katex, remark-math deps.

Test

  • New memoized-markdown.test.tsx: inline, display, mixed-with-GFM, single-line-amid-prose, and lone-dollar cases. 5/5 pass; typecheck clean.

Closes THU-606

🤖 Generated with Claude Code


Note

Low Risk
UI-only markdown rendering change with targeted preprocessing; no auth, API, or data-path changes.

Overview
Chat markdown now renders LaTeX via remark-math and rehype-katex, with KaTeX CSS loaded alongside MemoizedMarkdown. GFM still runs first; math plugins are shared on every block.

A normalizeDisplayMath pass runs before marked splits content: whole lines that are only $$…$$ get rewritten to fenced display math so single-line model equations center correctly. Inline $…$, currency-like lone $, and mid-sentence $$ are unchanged.

Adds katex, rehype-katex, and remark-math plus memoized-markdown.test.tsx covering inline/display, GFM mix, single-line display amid prose, and plain $5 text.

Reviewed by Cursor Bugbot for commit b7eb372. Bugbot is set up for automated code reviews on this repo. Configure here.

Generalize the LaTeX/math rendering prototyped on the OUP demo branch into
a standard chat markdown feature, with no demo-specific coupling.

- Wire remark-math + rehype-katex into the shared MemoizedMarkdown renderer
  and ship the KaTeX stylesheet on the chat critical path.
- Add normalizeDisplayMath: promote a whole-line `$$…$$` equation to fenced
  display math, since models routinely emit standalone equations on one line.
  Inline `$…$`, mid-sentence `$$…$$`, and already-fenced blocks are untouched.
- Add katex, rehype-katex, remark-math deps.
- Cover inline/display/mixed/lone-dollar cases in memoized-markdown.test.tsx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Semgrep Security Scan

No security issues found.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit b7eb372. Configure here.


const parseMarkdownIntoBlocks = (markdown: string): string[] => {
const tokens = marked.lexer(markdown)
const tokens = marked.lexer(normalizeDisplayMath(markdown))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Math rewrite mutates fenced code

Medium Severity

normalizeDisplayMath runs on the full markdown string before marked.lexer splits blocks, so any fenced or indented code line that is only $$…$$ gets rewritten with extra newlines inside the code text. Chat messages that include such examples show altered source, not the literal line the model sent.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit b7eb372. Configure here.

@github-actions

Copy link
Copy Markdown

Preview environment deployed 🚀

Service URL
Marketing / blog / docs https://thunderbolt-pr-999.preview.thunderbolt.io
App https://app-pr-999.preview.thunderbolt.io
API https://api-pr-999.preview.thunderbolt.io
Keycloak https://auth-pr-999.preview.thunderbolt.io
PowerSync https://powersync-pr-999.preview.thunderbolt.io

Stack: preview-pr-999 · Commit: b7eb372038282d330114cc86ce0893a12a48c916

Auto-destroys on PR close/merge. Login via the bundled Keycloak realm — demo@thunderbolt.io / demo by default.

@github-actions

Copy link
Copy Markdown

PR Metrics

Metric Value
Lines changed (prod code) +29 / -2
JS bundle size (gzipped) 🔴 682.3 KB → 761.5 KB (+79.3 KB, +11.6%)
Test coverage 🟢 78.09% → 78.10% (+0.0%)
Performance (preview) Preview not ready — Render deploy may have timed out
Accessibility
Best Practices
SEO

Updated Thu, 18 Jun 2026 17:53:22 GMT · run #1946

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