Skip to content

feat: render LaTeX math in markdown with KaTeX#214

Open
YonghaoZhao722 wants to merge 1 commit into
d-kimuson:mainfrom
YonghaoZhao722:feat/latex-math-rendering
Open

feat: render LaTeX math in markdown with KaTeX#214
YonghaoZhao722 wants to merge 1 commit into
d-kimuson:mainfrom
YonghaoZhao722:feat/latex-math-rendering

Conversation

@YonghaoZhao722

@YonghaoZhao722 YonghaoZhao722 commented Jun 4, 2026

Copy link
Copy Markdown

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

  • Add remark-math + rehype-katex to the MarkdownContent pipeline and import the KaTeX stylesheet.
  • Normalize single-line $$...$$ blocks into the block form remark-math v6 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.
  • Unit tests for inline math, single-line display math, and the code-span guard.

Why the normalization step

remark-math@6 only treats $$...$$ as display math when the $$ delimiters sit on their own lines. Claude Code outputs them on a single line, so a plain remark-math + rehype-katex setup would render those as inline math. normalizeDisplayMath() rewrites single-line $$...$$ to the multi-line block form while leaving code untouched.

Testing

  • pnpm test — new MarkdownContent tests 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

  • New Features
    • Added mathematical expression rendering support to markdown content.
    • Inline and block-level equations are now rendered properly.
    • Math expressions within code blocks are preserved as literal text.

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>
@coderabbitai

coderabbitai Bot commented Jun 4, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds KaTeX math rendering support to the MarkdownContent component. It introduces three new npm dependencies (katex, remark-math, rehype-katex), imports KaTeX styling, implements display-math normalization logic, wires plugins into the Markdown pipeline, and adds three test cases validating inline and display math rendering behavior.

Changes

Math Rendering Feature

Layer / File(s) Summary
Dependencies and styling setup
package.json, src/web/app/components/MarkdownContent.tsx
KaTeX (0.16.22), remark-math (6.0.0), and rehype-katex (7.0.1) are added to devDependencies; KaTeX stylesheet is imported into MarkdownContent.
Math processing pipeline
src/web/app/components/MarkdownContent.tsx
remark-math and rehype-katex plugins are imported; normalizeDisplayMath helper uses regex to convert single-line $$...$$ into display-math block delimiters while protecting fenced and inline code; Markdown renderer is configured with plugins and renders normalized content via useMemo.
Test coverage for math rendering
src/web/app/components/MarkdownContent.test.tsx
Three test cases verify inline math ($...$) produces .katex, single-line display math ($$...$$) produces .katex-display, and escaped display math inside backticks is not transformed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Math finds its home in markdown's embrace,
KaTeX renders equations with grace,
Display and inline, both shining bright—
Where dollars dance and symbols take flight! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: render LaTeX math in markdown with KaTeX' accurately and concisely describes the main change: adding KaTeX-based LaTeX math rendering to the Markdown component.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (1)
src/web/app/components/MarkdownContent.test.tsx (1)

57-79: ⚡ Quick win

Adopt 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/ with testPlatformLayer as the base setup for consistency.

As per coding guidelines "Use reusable Effect test layers from src/testing/layers/ for testing, with testPlatformLayer as 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

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8eb62 and 733e602.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • package.json
  • src/web/app/components/MarkdownContent.test.tsx
  • src/web/app/components/MarkdownContent.tsx

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