markdown_preview: Add Mermaid Diagram Support#49064
Conversation
Enable rendering of mermaid diagrams in markdown preview, allowing users to
create flowcharts, sequence diagrams, and other visualizations directly in
markdown files using standard mermaid syntax.
- Added `ParsedMarkdownMermaidDiagram` element type to handle mermaid code blocks
- Created `mermaid_renderer` module that uses @mermaid-js/mermaid-cli (v11.4.0)
- Integrated async rendering pipeline into markdown preview workflow
- Renders diagrams as high-resolution PNG (2x scale) with transparent background
- Automatically installs mermaid-cli via npm on first use
```mermaid
flowchart TD
A[Markdown File] --> B{Parser}
B -->|```mermaid| C[ParsedMarkdownMermaidDiagram]
B -->|Other blocks| D[Other Elements]
C --> E[Async Render Pipeline]
E --> F[Get NodeRuntime]
F --> G[Install mermaid-cli]
G --> H[Execute mmdc]
H --> I[Generate PNG]
I --> J[Display in Preview]
D --> J
Technical Details
Modified files:
- crates/markdown_preview/src/markdown_elements.rs - New diagram element type
- crates/markdown_preview/src/markdown_parser.rs - Detect mermaid blocks
- crates/markdown_preview/src/markdown_renderer.rs - Render diagram images
- crates/markdown_preview/src/mermaid_renderer.rs - New: mermaid integration
- crates/markdown_preview/src/markdown_preview_view.rs - Async rendering pipeline
- crates/markdown_preview/src/markdown_preview.rs - Module declaration
- crates/markdown_preview/Cargo.toml - Added dependencies
Rendering options:
- Theme: neutral (for clean, simple output)
- Background: transparent (adapts to light/dark themes)
- Scale: 2x (high-resolution for retina displays)
- Format: PNG (universal compatibility)
Cross-Platform Support
Works on macOS, Windows, and Linux. Linux users may need additional system
packages for Puppeteer (libx11-xcb1, libxcomposite1, etc.).
Example Usage
```mermaid
graph LR
A[Start] --> B[Process]
B --> C[End]
```
…e scaling
Add intelligent content-aware caching and parallel rendering to dramatically
improve performance when editing markdown files with mermaid diagrams. Also
introduce configurable per-diagram scaling via fence syntax.
- Compute hash of diagram content + scale to detect changes
- Only re-render diagrams whose content actually changed
- Cache rendered PNGs with LRU eviction (max 50 diagrams)
- Reuse cached diagrams instantly when content unchanged
**Performance impact:**
- Editing non-mermaid content: 0 diagrams re-rendered (instant updates)
- Editing one diagram: only that diagram re-renders (~1s vs 5-10s before)
- Switching between cached content: instant retrieval
- Render multiple diagrams concurrently using `futures::future::join_all`
- 2-3x faster for documents with multiple diagrams
- Each diagram renders in independent background task
Users can now specify scale percentage in the code fence:
````markdown
```mermaid 50
graph LR
A --> B
flowchart TD
Start --> End
**Syntax:** ` ```mermaid [scale] ` where scale is 10-500 (default: 100)
**Scale calculation:**
- `50` → scale factor 1 (50% of retina default)
- `100` → scale factor 2 (default retina)
- `150` → scale factor 3 (1.5x larger)
- `200` → scale factor 4 (2x larger)
**Smart caching:** Different scales create separate cache entries, so changing
scale triggers re-render but switching back to previous scale uses cache.
```mermaid
flowchart TD
A[Edit Markdown] --> B{Parser}
B -->|mermaid block| C[Compute Hash]
C --> D{In Cache?}
D -->|Yes + File Exists| E[Reuse Cached PNG]
D -->|No| F[Spawn Render Task]
F --> G[Multiple Tasks in Parallel]
G --> H[Execute mmdc]
H --> I[Save to Cache]
I --> J[Update LRU]
J --> K{Cache > 50?}
K -->|Yes| L[Evict Oldest]
K -->|No| M[Display]
L --> M
E --> M
```
**Modified files:**
- `markdown_elements.rs` - Added `scale: u32` and `content_hash: Option<u64>` fields
- `markdown_parser.rs` - Parse scale from fence syntax, compute content hash
- `markdown_preview_view.rs` - Smart cache with LRU, parallel rendering
- `mermaid_renderer.rs` - Accept scale parameter, use integer for mmdc
- `Cargo.toml` - Added `futures` dependency
**Hash computation:**
```rust
let content_hash = {
let mut hasher = collections::FxHasher::default();
code.hash(&mut hasher);
scale.hash(&mut hasher); // Scale affects hash
hasher.finish()
};
```
**LRU cache eviction:**
- Max cache size: 50 diagrams
- Evicts least recently used entries
- Deletes corresponding PNG files on eviction
**Parallel rendering:**
```rust
let render_tasks: Vec<_> = diagrams_needing_render
.map(|diagram| cx.background_executor().spawn(...))
.collect();
let results = futures::future::join_all(render_tasks).await;
```
**Limits:**
- Minimum: 10% (prevents too-small diagrams)
- Maximum: 500% (prevents excessive memory usage)
- Default: 100% (2x scale factor for retina displays)
**Note:** mermaid-cli requires integer scale values, so:
- Values 10-49 → scale factor 1
- Values 50-99 → scale factor 1
- Values 100-149 → scale factor 2
- Values 150-199 → scale factor 3
- etc.
None. Existing ` ```mermaid ` blocks without scale work exactly as before
(default 100% = scale factor 2).
Test cases to verify:
1. ✅ Edit non-mermaid content → no diagram re-renders
2. ✅ Edit one diagram → only that diagram re-renders
3. ✅ Multiple diagrams → render in parallel
4. ✅ Undo diagram edit → uses cached version
5. ✅ Scale 50, 100, 150, 200 → correct sizes
6. ✅ Change scale → triggers re-render with new hash
7. ✅ Cache exceeds 50 diagrams → LRU eviction works
````markdown
Small flowchart:
```mermaid 50
graph LR
A --> B
```
Normal sequence diagram:
```mermaid
sequenceDiagram
Alice->>Bob: Hello
Bob->>Alice: Hi
```
Large complex diagram:
```mermaid 200
flowchart TD
A[Start] --> B{Decision}
B -->|Yes| C[Process]
B -->|No| D[Skip]
C --> E[End]
D --> E
```
|
cc @oscarvarto since this is reusing your contribution from #42822 |
|
Hi @smitbarmase! I had a related PR (#49010) that was closed in favor of this one. Your PR adds Mermaid rendering inside Markdown code blocks, which is great.. but my PR was specifically about previewing standalone .mmd/.mermaid files (similar to how svg_preview handles .svg files). @SomeoneToIgnore suggested these might be meant to be merged together. Do you have plans to also support standalone Mermaid file previews in this PR, or would it make sense to track that as a separate follow-up? Happy to help or collaborate if useful! |
|
I'm pretty happy that Zed's markdown preview supports mermaid diagrams. This should help expressing ideas/designs or simply improve documentation quality. Markdown is everywhere! Thank you very much to the Zed team for adding this feature. |
Updates docs-suggest with release channel awareness: - Auto-detects PR target branch (main vs release branch) - PRs to main: batch mode with Preview callouts - Cherry-picks: immediate mode without callouts Adds two new scripts: - docs-suggest-publish: Creates PR from batched suggestions - docs-strip-preview-callouts: Removes Preview callouts for stable release Workflow: 1. PRs to main → suggestions batched to docs/.suggestions/pending.md 2. At preview branch cut → run docs-suggest-publish to create docs PR 3. At stable release → run docs-strip-preview-callouts Preview callout format: > **Preview:** This feature is available in Zed Preview. It will be > included in the next Stable release. Tested on PRs #49064 (Mermaid) and #49051 (Git Graph keyboard nav). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Updates docs-suggest with release channel awareness: - Auto-detects PR target branch (main vs release branch) - PRs to main: batch mode with Preview callouts - Cherry-picks: immediate mode without callouts Adds two new scripts: - docs-suggest-publish: Creates PR from batched suggestions - docs-strip-preview-callouts: Removes Preview callouts for stable release Workflow: 1. PRs to main → suggestions batched to docs/.suggestions/pending.md 2. At preview branch cut → run docs-suggest-publish to create docs PR 3. At stable release → run docs-strip-preview-callouts Preview callout format: > **Preview:** This feature is available in Zed Preview. It will be > included in the next Stable release. Tested on PRs #49064 (Mermaid) and #49051 (Git Graph keyboard nav). Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Totally agree. The standalone files should get previews as well, especially given that there's already an extension for mermaid filetypes. |

Closes #10696
Adds support for rendering Mermaid diagrams in the markdown preview using mermaid-rs-renderer (with a patch).
Release Notes: