markdown: Add LaTeX math rendering support - #53150
Conversation
|
We require contributors to sign our Contributor License Agreement, and we don't have @n-WN on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
Implement LaTeX math rendering in the markdown preview using the ReX typesetting engine with a custom GPUI backend that converts glyph outlines to Path primitives and rules to Quad primitives. - Parse InlineMath/DisplayMath events from pulldown-cmark (previously discarded) - Create GpuiMathBackend implementing ReX's Backend trait for native rendering - Bundle XITS Math font for OpenType MATH table support - Add async rendering with OnceLock caching (following the mermaid pattern) - Display math renders as centered block elements - Inline math renders as inline elements with text color adaptation Closes zed-industries#10899 Release Notes: - Added LaTeX math rendering in markdown preview ($inline$ and $$display$$ math)
8b7da29 to
714ac56
Compare
|
We require contributors to sign our Contributor License Agreement, and we don't have @n-WN on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
|
I have read and signed the CLA at https://zed.dev/cla @cla-bot check |
|
We require contributors to sign our Contributor License Agreement, and we don't have @n-WN on file. You can sign our CLA at https://zed.dev/cla. Once you've signed, post a comment here that says '@cla-bot check'. |
|
The cla-bot has been summoned, and re-checked this pull request! |
|
@cla-bot check |
|
The cla-bot has been summoned, and re-checked this pull request! |
- Add Options::ENABLE_MATH to PARSE_OPTIONS so pulldown-cmark actually emits InlineMath/DisplayMath events - Scale math rendering based on the actual base_text_style font size instead of hardcoded values - Render at native ReX scale (1.0) and apply font-size scaling at display time for correct proportions Release Notes: - N/A
Instead of rendering inline math as a separate canvas element (which breaks text flow), convert LaTeX to Unicode characters and render as italic text via push_text. This preserves natural text reflow. Covers superscripts, subscripts, Greek letters, common math operators, and set theory symbols. Display math still uses canvas rendering. Release Notes: - N/A
Compute actual bounding box from rendered paths/rects instead of relying on ReX layout dimensions, which underestimate size for matrices and large delimiters. Normalize coordinates to start at origin (0,0) so the canvas element properly allocates space. Release Notes: - N/A
ReX uses Y-down convention (matching screen coordinates), so the layout-to-canvas transform should not flip Y. The previous sy: -scale caused bracket and delimiter positions to be vertically mirrored relative to matrix content. Font glyph outlines (Y-up) still flip correctly via the separate glyph transform. Release Notes: - N/A
- Fix extract_group to handle \command after ^ and _ (e.g. G^\perp → G⊥) - Recursively convert LaTeX to Unicode inside super/subscript groups - Preprocess \[ → [ and \] → ] for escaped bracket delimiters - Style failed math rendering as monospace code blocks with background instead of raw plaintext Release Notes: - N/A
|
Thanks for working on this! I'm really looking forward to real math equations in the AI chat window. Did you have some list of latex functions that you were working from? Or how did you decide which latex functions to support for the inline unicode translation? The unicode fraction slash character might be an interesting next step, as "frac" takes two parameters not one. |
|
Thank you very much for this and the time and effort that went into this! Furthermore, sorry for no reply yet - we are always cautious with such big changes and thus takes us some more time to get back here sometimes, more than we'd like. Unfortunately, I am gonna close this out in favor of #54668 - that PR brings some Windows fixes already as well as an overall less invasive approach for the issue at hand. Thus, I decided we'll push that PR to completion. However, I already informed the contributor there that we should also take learnings from this Pr so that your effort here does not go to waste. Hope you can understand that, in any case, thank you very much for this PR! |
I'm happy to see his effect, but do I have a chance to be a co-author, as some experimental attempts. |

Summary
InlineMath/DisplayMathevents from pulldown-cmark instead of silently discarding them (addENABLE_MATHto parser options)Pathprimitives and fraction bars/rules toQuadprimitivesOnceLockcaching following the existing mermaid diagram pattern$$...$$) renders as centered block elements via ReX vector paths$...$) converts LaTeX to Unicode text and renders as italic styled text, preserving natural text flowScreenshot
<img width="1648" height="977" alt="LaTeX math rendering in Zed markdown preview"" src="https://github.com/user-attachments/assets/dfe3f7e9-e04f-4cbc-8650-500cc7094a88" />
Architecture
Display math rendering is cached per unique expression and runs on a background thread to avoid blocking the UI. Text color automatically adapts to the current theme (light/dark).
Known Limitations
ttfparser-fontparserfeature — ideally this would be upstreamed or vendored\begin{matrix}with escaped brackets) fall back to showing raw sourceCloses #10899
Test plan
$$E = mc^2$$) renders as centered formula$x^2 + y^2$) renders within paragraph text flowRelease Notes:
$inline$and$$display$$math)