block / block/buzz

Feature request: render LaTeX math in messages via KaTeX (working implementation included)

Open
#5,403 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Rust
Stars
32.7k
Forks
4.3k
Avg merge
1d 13h
Merged PRs (30d)
253

Description

**Motivation**

Buzz currently renders LaTeX math as raw source text on all platforms (Desktop / Web / Mobile). For a human–agent collaboration tool, technical discussions (math, physics, ML) routinely include formulas like `$E=mc^2$` or `$$\int e^{-x^2}dx$$`, and reading them as source is a real usability gap.

We propose adding KaTeX rendering via `remark-math` + `rehype-katex`, and we have a **working, tested implementation** on a fork (branch linked below; PR to follow). We searched existing issues/PRs for math/latex/katex/formula and found nothing — happy to be pointed at prior discussion if we missed it.

**Proposed solution**

**Desktop (core)**: the message timeline renders through react-markdown in `desktop/src/shared/ui/markdown/nodeCache.ts`. Add `remark-math` + `rehype-katex` to the plugin list and import `katex/dist/katex.min.css`. Supports inline `$...$` and display `$$...$$`.

**Web (same phase, trivial cost)**: the three react-markdown call sites (`RepoBlobViewer`, `RepoReadmeSection`, `InvitePage`) get the same two plugins.

**Performance (the part we'd want reviewed hardest)**

A chat timeline is a long list with many sessions alive, so we designed around the existing cache architecture:

1. **KaTeX runs at most once per message.** `nodeCache.ts` already caches react-markdown's output element tree at module level (`renderCachedMarkdown`). The rehype-katex output rides that cache: scrolling, viewport re-entry, and channel hot-switching never re-run KaTeX.
2. **Zero cost for messages without `$`.** remark-math short-circuits at the tokenizer level; we additionally short-circuit before the plugin pipeline (measured: 0.06ms per plain message).
3. **Abuse guards** (small standalone module `mathBounds.ts`): a message with >100 formulas degrades to literal display (math plugins skipped); a single formula >2KB is isolated (delimiters escaped) while sibling formulas still render; and pandoc-style tightness rules keep currency text like `$5 and $10` literal — remark-math@6's tokenizer accepts inline content with spaces, so without that guard currency gets mangled into math (caught in manual testing of the PoC).
4. **Measured on the implementation**: a heavy 50-formula message costs ~70ms exactly once (first parse), then ~0.014ms per display from cache; hot-switching back to a previously viewed channel adds 0 fresh parses.

**Error handling**

KaTeX standard degradation with `throwOnError: false`: malformed input never throws, valid formulas in the same message render normally, and the broken fragment degrades to its source text rather than crashing or taking down the message.

**Bundle size**

Measured on the desktop build (`vite build` output): `katex.min.css` is 23.8 KiB raw / 4 KiB gzip and bundles into the main stylesheet (no extra request). Fonts are woff2 fetched on demand via `unicode-range` — ~250 KiB total across all 19 font files, and typical formulas only pull the Main/AMS/Math/Size subset, ~150–200 KiB. Negligible for the locally bundled desktop app; web can lazy-load / CDN the fonts.

**PoC**

Branch: https://github.com/whyihaveyou/buzz/tree/feat/katex-math-rendering

- Desktop + Web implementation as described above.
- Full desktop test suite: **4504 passing / 0 failing**, including tests for inline/display rendering, cache-hit behavior, no-formula regression, malformed-input degradation, formula-bomb degradation, oversized-formula isolation (inline and display), and currency/tightness literal-rendering regressions.

**Alternatives considered**

- MathJax: heavier and asynchronous; KaTeX's synchronous, layout-free rendering fits a cached timeline.
- Mobile (Flutter): out of scope here; would need a separate evaluation (`flutter_math_fork` or equivalent).
- Pre-escaping heuristics to show raw text on malformed input: rejected — they risk silently disabling valid formulas, which is worse than honest degradation.

**Questions for maintainers**

1. Is math rendering something you'd want upstream? If yes, we'll open the PR from the PoC branch and adjust to your conventions.
2. Preference on scope: desktop-only first, or desktop + web together?
3. Any objection to KaTeX specifically (vs. MathJax)?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.