feat: render LaTeX math in markdown with KaTeX#214
Conversation
Conversation markdown often contains LaTeX equations (e.g. Claude Code explaining loss functions), but they were shown as raw `$...$` / `$$...$$` source instead of rendered math. - Add remark-math + rehype-katex to the markdown pipeline and import the KaTeX stylesheet. - Normalize single-line `$$...$$` blocks (the form Claude Code emits) into the block form remark-math needs so they render as centered display equations, while leaving fenced code blocks and inline code untouched. - Cover inline math, single-line display math, and the code-span guard with unit tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
📝 WalkthroughWalkthroughThis PR adds KaTeX math rendering support to the MarkdownContent component. It introduces three new npm dependencies ( ChangesMath Rendering Feature
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/web/app/components/MarkdownContent.test.tsx (1)
57-79: ⚡ Quick winAdopt the shared Effect test layer stack for these new cases.
These new tests are added using the file’s direct DOM/root harness instead of the reusable Effect testing layers; please migrate them to
src/testing/layers/withtestPlatformLayeras the base setup for consistency.As per coding guidelines "Use reusable Effect test layers from
src/testing/layers/for testing, withtestPlatformLayeras the foundation".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/web/app/components/MarkdownContent.test.tsx` around lines 57 - 79, These tests currently use the file’s direct DOM/root harness via renderComponent and container; migrate them to the shared Effect test layer stack by importing testPlatformLayer from src/testing/layers and using the project’s shared layer test helper instead of renderComponent (e.g., the helper that runs components under testPlatformLayer — replace usages of renderComponent and direct container setup with the shared renderWithLayers/renderWithTestLayers helper that composes testPlatformLayer), update the test imports/fixture setup accordingly, and keep the same assertions (querying for ".katex" and ".katex-display" and the text checks) but executed under the testPlatformLayer harness.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/web/app/components/MarkdownContent.test.tsx`:
- Around line 57-79: These tests currently use the file’s direct DOM/root
harness via renderComponent and container; migrate them to the shared Effect
test layer stack by importing testPlatformLayer from src/testing/layers and
using the project’s shared layer test helper instead of renderComponent (e.g.,
the helper that runs components under testPlatformLayer — replace usages of
renderComponent and direct container setup with the shared
renderWithLayers/renderWithTestLayers helper that composes testPlatformLayer),
update the test imports/fixture setup accordingly, and keep the same assertions
(querying for ".katex" and ".katex-display" and the text checks) but executed
under the testPlatformLayer harness.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e60f03bd-f05c-4a54-8e81-34fdbcb27336
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (3)
package.jsonsrc/web/app/components/MarkdownContent.test.tsxsrc/web/app/components/MarkdownContent.tsx
Summary
Conversation markdown frequently contains LaTeX equations — e.g. when Claude Code explains loss functions or other math — but the viewer rendered them as raw
$...$/$$...$$source instead of formatted math. This PR renders them with KaTeX.Before / After
Equations like
$$\mathcal{L}_{\text{pre}} = \text{MSE}(\text{decode}(\text{encode}(X)),\ X)$$previously showed as literal text; they now render as proper display equations.Changes
remark-math+rehype-katexto theMarkdownContentpipeline and import the KaTeX stylesheet.$$...$$blocks into the block formremark-mathv6 requires for display mode. Claude Code emits display equations on one line; without this they would render as small inline math. Fenced code blocks and inline code spans are protected from rewriting.Why the normalization step
remark-math@6only treats$$...$$as display math when the$$delimiters sit on their own lines. Claude Code outputs them on a single line, so a plainremark-math+rehype-katexsetup would render those as inline math.normalizeDisplayMath()rewrites single-line$$...$$to the multi-line block form while leaving code untouched.Testing
pnpm test— newMarkdownContenttests pass (inline, display, code-span guard).pnpm typecheck,pnpm lint— clean.pnpm build:frontend— builds successfully (KaTeX CSS + fonts bundle correctly).🤖 Generated with Claude Code
Summary by CodeRabbit