100–1400× faster Mermaid rendering. Pure Rust. Zero browser dependencies.
Parse Mermaid natively and render straight to SVG (or PNG) — no Chromium, no Node, no Puppeteer.
cargo install mermaid-rs-renderer
# or
echo 'flowchart LR; A-->B-->C' | mmdr -e svg# Pipe to stdout (fastest)
echo 'flowchart LR; A-->B-->C' | mmdr -e svg
# File to SVG (440× faster than mermaid-cli)
mmdr -i diagram.mmd -o output.svg -e svg
# With timing JSON
mmdr -i diagram.mmd -o out.svg -e svg --timing
# Library embed (Criterion: ~1.5 ms)
use mermaid_rs_renderer::render;
let svg = render("flowchart LR; A-->B-->C")?;Official mermaid-cli spawns headless Chromium per diagram — ~2s startup tax every time.
| Workload | mermaid-cli | Reality |
|---|---|---|
| 50 diagrams in CI | ~2 minutes | Browser tax dominates |
| Live editor preview | Multi-second lag | Unusable feedback loop |
| Batch docs | Coffee break | Throughput capped by Puppeteer |
mmdr parses Mermaid in Rust and emits SVG/PNG directly.
| Metric (typical) | mmdr | mermaid-cli | Speedup |
|---|---|---|---|
| Flowchart | ~4.5 ms | ~2.0 s | ~440× |
| Class | ~4.7 ms | ~1.9 s | ~410× |
| State | ~4.0 ms | ~2.0 s | ~500× |
| Sequence | ~2.7 ms | ~1.9 s | ~700× |
Warm font cache: 500–900×. Optional --fastText: 1600×+ on tiny diagrams.
| Feature | What it does |
|---|---|
| Native parse + layout | No browser process spawn |
| SVG + PNG | PNG via resvg (feature-gated) |
| Library API | Embed in Rust apps without CLI spawn |
| Themes | default · dark · forest · neutral · modern |
| 23 diagram types | Flowchart, sequence, class, state, ER, gantt, … |
| CI-friendly | Single static binary, ~15 MB RAM vs ~300 MB Chromium |
# Pipe to stdout
echo 'flowchart LR; A-->B-->C' | mmdr -e svg
# File → file
mmdr -i diagram.mmd -o output.svg -e svg
# Dark theme + timing JSON on stderr
mmdr -i diagram.mmd -o out.svg -e svg --theme dark --timing
# Fast text metrics (ASCII labels)
mmdr -i diagram.mmd -o out.svg -e svg --fastText
# PNG
mmdr -i diagram.mmd -o out.png -e png-
Browser-free by default.
If a doc tool needs Chromium just to draw boxes and arrows, something is wrong. -
Milliseconds matter in agent loops.
Agents and live previews render diagrams constantly; 2s cold starts kill the loop. -
Library first, CLI second.
Criterion-level in-process times (flowchart ~1.5 ms) beat even a fast CLI spawn. -
Visual parity is a ratchet, not a promise of pixel identity.
Hard gates and conformance fixtures continuously reduce divergence from mermaid-js. -
Feature-gated weight.
Droppng/clifeatures when embedding in servers or static-site generators.
| Use case | mermaid-cli | Kroki / remote | mmdr |
|---|---|---|---|
| CI with 50 diagrams | ~2 min | Network + queue | < 1 s |
| Real-time preview | Lag | Latency | Instant |
| Embed in Rust apps | N/A | HTTP client | Library API |
| Runtime deps | Node + Chromium | Service | Binary only |
| Offline / air-gap | Heavy | ❌ | ✅ |
| Visual parity | Reference | Varies | Improving fast |
When to use mmdr:
- CI pipelines rendering many diagrams
- Local previews and agent toolchains
- Embedding Mermaid in Rust services / static generators
When mmdr might not be ideal:
- You need every experimental mermaid-js plugin / click handler
- Pixel-perfect identity with mermaid-cli is a hard release gate (diff goldens)
# crates.io
cargo install mermaid-rs-renderer
# Homebrew
brew tap 1jehuang/mmdr && brew install mmdr
# Scoop (Windows)
scoop bucket add mmdr https://github.com/1jehuang/scoop-mmdr && scoop install mmdr
# AUR
yay -S mmdr-bin
# Nix flake
nix run github:1jehuang/mermaid-rs-renderer -- --help
# From this fork (source)
git clone https://github.com/quangdang46/mermaid-rs-renderer.git
cd mermaid-rs-renderer
cargo install --path .Note: Upstream package/Homebrew paths may track
1jehuang/mermaid-rs-renderer. This fork atquangdang46/mermaid-rs-rendererfollows the same CLI (mmdr).
[dependencies]
mermaid-rs-renderer = { version = "0.3", default-features = false }| Feature | Default | Purpose |
|---|---|---|
cli |
✅ | mmdr binary |
png |
✅ | PNG via resvg |
# stdin → stdout
echo 'flowchart LR; A-->B-->C' | mmdr -e svg
# explicit stdin → file
echo 'flowchart LR; A-->B-->C' | mmdr -i - -o out.svg -e svg
# file → file
mmdr -i diagram.mmd -o output.svg -e svg
# size metadata only (JSON)
mmdr -i diagram.mmd --size
# layout dump for debugging
mmdr -i diagram.mmd -o out.svg --dumpLayout layout.jsonuse mermaid_rs_renderer::{render, render_with_options, RenderOptions};
let svg = render("flowchart LR; A-->B-->C")?;
let opts = RenderOptions::default();
let svg = render_with_options("sequenceDiagram\nAlice->>Bob: Hi", opts)?;// Criterion-level raw render times (no process spawn):
// flowchart ~1.5 ms · sequence ~0.07 ms
mmdr [OPTIONS]
| Flag | Description |
|---|---|
-i, --input <PATH> |
Input .mmd file or - for stdin |
-o, --output <PATH> |
Output file (default: stdout for SVG) |
-e, --outputFormat <svg|png> |
Output format (default: svg) |
-c, --configFile <PATH> |
Config JSON (Mermaid-like themeVariables) |
-t, --theme <NAME> |
default · dark · forest · neutral · modern |
-w, --width <N> |
Width (PNG fallback / sizing) |
-H, --height <N> |
Height (PNG fallback / sizing) |
--preferredAspectRatio <R> |
width:height, width/height, or decimal |
--nodeSpacing <N> |
Node spacing override |
--rankSpacing <N> |
Rank spacing override |
--dumpLayout <PATH> |
Dump computed layout JSON |
--timing |
Timing JSON on stderr |
--size |
Print size metadata JSON and exit |
--fastText |
Approximate text metrics (ASCII-heavy speed path) |
mmdr -i arch.mmd -o arch.svg -e svg --theme dark --timing
mmdr -i arch.mmd -o arch.png -e png -w 1200
mmdr -i arch.mmd --size| Type | Keyword |
|---|---|
| Flowcharts | flowchart / graph (TD, TB, LR, RL, BT) |
| Sequence | sequenceDiagram |
| Class | classDiagram |
| State | stateDiagram-v2 |
| ER | erDiagram |
| Pie | pie |
| XY chart | xychart |
| Quadrant | quadrantChart |
| Gantt | gantt |
| Timeline | timeline |
| Journey | journey |
| Mindmap | mindmap |
| Git graph | gitGraph |
Coverage continues to expand; verify your dialect against fixtures if you depend on edge syntax.
| Mode | When | Speedup vs mermaid-cli |
|---|---|---|
| Cold | First run | 100–700× |
| Warm font cache | After first render | 500–900× |
--fastText |
Tiny ASCII-heavy diagrams | 1600–2000× |
Large diagrams (200 nodes) still land ~50–100×+ — layout cost grows, browser tax still dominates mermaid-cli.
Memory: ~15 MB vs ~300 MB for mermaid-cli.
.mmd / stdin
│
▼
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Parser │ ──▶ │ Layout │ ──▶ │ Render │
│ parser.rs │ │ layout/* │ │ render.rs │
└─────────────┘ └──────────────┘ └──────┬──────┘
│
┌───────────┼───────────┐
▼ ▼ ▼
SVG PNG* layout dump
(resvg)
* feature = "png"
| Module | Role |
|---|---|
parser |
Mermaid → IR |
layout |
Placement, routing, subgraph containment |
render |
SVG emit (+ optional PNG) |
theme / config |
Themes + Mermaid-like variables |
text_metrics |
Font / --fastText widths |
cli |
mmdr binary |
cargo install mermaid-rs-renderer
# ensure ~/.cargo/bin is on PATH
export PATH="$HOME/.cargo/bin:$PATH"Build with default features (includes png), or:
cargo install mermaid-rs-renderer --features png--fastText uses approximate ASCII widths. For CJK / proportional fonts, omit the flag.
Expected for some edge cases. Diff golden SVGs/PNGs in CI if pixel identity matters:
mmdr -i fixture.mmd -o out.svg -e svg
diff -u golden.svg out.svgFile an issue with a minimal .mmd repro. Not every experimental mermaid-js extension is implemented yet.
- Not a full Mermaid JS runtime — no browser plugins / live click handlers
- Visual parity is improving fast but not every edge case matches mermaid-cli
--fastTextis calibrated for ASCII — non-Latin labels may shift
| Capability | Current state | Notes |
|---|---|---|
| Diagram coverage | ✅ Broad | Verify your dialect |
| Pixel-perfect parity | Use golden diffs | |
| Remote Kroki-style API | ❌ | Library/CLI only |
| JS plugin ecosystem | ❌ | Out of scope |
Same SVG goal, different pipeline. Diff golden images in CI if pixel-perfect parity matters.
No Chromium process spawn. Native parse + layout + SVG emit.
Yes — use as a Rust library to avoid CLI spawn entirely. Disable default features for a thinner dependency graph.
mmdr -i d.mmd -o d.svg --theme dark
mmdr -i d.mmd -o d.svg --theme forestCustom: pass --configFile with Mermaid-like themeVariables.
Packaging/Homebrew often tracks 1jehuang/mermaid-rs-renderer. This repository is quangdang46/mermaid-rs-renderer with the same mmdr CLI surface.
Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via gh and independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.
Native Mermaid. Browser-free. Agent-friendly.
