A Milkdown plugin for rendering interactive Mermaid diagrams directly in your markdown editor. Create flowcharts, sequence diagrams, Gantt charts, and more with full editing support.
🎮 Try the Live Demo | View Source Code
Install the plugin and its peer dependency:
npm install @milkdown/plugin-mermaid mermaid
# or
pnpm add @milkdown/plugin-mermaid mermaid
# or
yarn add @milkdown/plugin-mermaid mermaid- Import the plugin and styles:
import { Editor, rootCtx } from '@milkdown/core';
import { commonmark } from '@milkdown/preset-commonmark';
import { mermaid } from '@milkdown/plugin-mermaid';
import '@milkdown/plugin-mermaid/style.css';- Add the plugin to your editor:
const editor = await Editor.make()
.config((ctx) => {
ctx.set(rootCtx, document.getElementById('editor'));
})
.use(commonmark)
.use(mermaid)
.create();- Write Mermaid diagrams in your markdown:
```mermaid
graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Action 1]
B -->|No| D[Action 2]
C --> E[End]
D --> E
```That's it! Your Mermaid diagrams will be automatically rendered as interactive SVGs.
- Automatic Rendering: Mermaid code fences are automatically detected and rendered as SVG diagrams
- View/Edit Modes: Toggle between viewing the rendered diagram and editing the source code
- Full ProseMirror Editing: Edit mode supports all ProseMirror features (undo/redo, selection, copy/paste, etc.)
- Error Handling: Invalid Mermaid syntax displays helpful error messages
- Customizable Styling: Full control over appearance via CSS classes
- Configurable: Customize Mermaid rendering options and behavior
Simply use code fences with the mermaid language identifier in your markdown:
```mermaid
sequenceDiagram
participant Alice
participant Bob
Alice->>Bob: Hello Bob!
Bob-->>Alice: Hi Alice!
```Each Mermaid diagram has two modes:
- View Mode: Shows the rendered SVG diagram. Hover over the diagram to reveal the Edit button.
- Edit Mode: Shows the source code with full editing capabilities. Click View to render the diagram.
Empty Mermaid blocks automatically start in edit mode so you can begin typing immediately.
Configure the plugin behavior using the mermaidConfig context:
import { Editor, rootCtx } from '@milkdown/core';
import { commonmark } from '@milkdown/preset-commonmark';
import { mermaid, mermaidConfig } from '@milkdown/plugin-mermaid';
import '@milkdown/plugin-mermaid/style.css';
const editor = await Editor.make()
.config((ctx) => {
ctx.set(rootCtx, document.getElementById('editor'));
// Configure Mermaid plugin
ctx.set(mermaidConfig.key, {
// Change the language identifier (default: 'mermaid')
language: 'mermaid',
// Pass options to Mermaid's initialize() function
mermaidConfig: {
theme: 'dark', // 'default' | 'dark' | 'forest' | 'neutral'
startOnLoad: false, // We handle rendering manually
securityLevel: 'loose', // 'strict' | 'loose' | 'antiscript' | 'sandbox'
// ... see Mermaid documentation for all options
},
// Custom error handler
onError: (error: string) => {
console.error('Mermaid rendering error:', error);
// You could show a toast notification, log to analytics, etc.
},
});
})
.use(commonmark)
.use(mermaid)
.create();You can use a different language identifier if needed:
ctx.set(mermaidConfig.key, {
language: 'diagram', // Now use ```diagram instead of ```mermaid
});The plugin uses stable CSS class names that you can override to match your application's design. Import the default styles first, then add your customizations:
/* Import default styles */
@import '@milkdown/plugin-mermaid/style.css';
/* Your custom overrides */
.milkdown-mermaid-container {
background-color: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 8px;
padding: 16px;
margin: 16px 0;
}
.milkdown-mermaid-controls {
/* Controls container (Edit/View button) */
top: 12px;
right: 12px;
}
.milkdown-mermaid-controls button {
background-color: #007bff;
color: white;
border: none;
padding: 6px 16px;
border-radius: 4px;
font-size: 14px;
cursor: pointer;
transition: background-color 0.2s;
}
.milkdown-mermaid-controls button:hover {
background-color: #0056b3;
}
.milkdown-mermaid-viewer {
/* Container for the rendered SVG diagram */
padding: 16px;
background-color: #fafafa;
border-radius: 4px;
}
.milkdown-mermaid-editor {
/* The code editor panel (pre element) */
background-color: #1e1e1e;
color: #d4d4d4;
padding: 16px;
border-radius: 4px;
font-family: 'Fira Code', 'Consolas', monospace;
font-size: 14px;
line-height: 1.6;
}
.milkdown-mermaid-code {
/* The code element inside the editor */
/* Remove default outline/border styles */
outline: none;
border: none;
}
.milkdown-mermaid-error {
/* Error message display */
background-color: #fff3cd;
border: 1px solid #ffc107;
color: #856404;
padding: 12px;
border-radius: 4px;
font-family: ui-monospace, monospace;
font-size: 13px;
margin-top: 12px;
}| Class Name | Description | Element Type |
|---|---|---|
.milkdown-mermaid-container |
Main wrapper containing all diagram elements | div |
.milkdown-mermaid-controls |
Container for Edit/View toggle button | div |
.milkdown-mermaid-viewer |
Container for the rendered SVG diagram | div |
.milkdown-mermaid-editor |
Code editor panel (the <pre> element) |
pre |
.milkdown-mermaid-code |
The code element inside the editor | code |
.milkdown-mermaid-error |
Error message display panel | div |
@import '@milkdown/plugin-mermaid/style.css';
.milkdown-mermaid-container {
background-color: #1a1a1a;
border: 1px solid #333;
}
.milkdown-mermaid-viewer {
background-color: #0d1117;
}
.milkdown-mermaid-editor {
background-color: #161b22;
color: #c9d1d9;
}
.milkdown-mermaid-controls button {
background-color: #238636;
color: white;
}
.milkdown-mermaid-controls button:hover {
background-color: #2ea043;
}
.milkdown-mermaid-error {
background-color: #3d1f1f;
border-color: #f85149;
color: #ff7b72;
}@import '@milkdown/plugin-mermaid/style.css';
.milkdown-mermaid-container {
background: transparent;
border: none;
padding: 0;
}
.milkdown-mermaid-viewer {
padding: 0;
background: transparent;
}
.milkdown-mermaid-editor {
background: transparent;
padding: 8px;
border: 1px dashed #ccc;
}mermaid- Main plugin export (recommended). Includes both the plugin and config context.mermaidPlugin- The underlying ProseMirror plugin (advanced use cases).mermaidConfig- Context slice for configuring the plugin.renderMermaid(code, config?)- Utility function to render Mermaid code to SVG string.clearMermaidCache()- Clear the internal render cache (useful for testing or memory management).
import type { MermaidPluginOptions } from '@milkdown/plugin-mermaid';
// MermaidPluginOptions includes:
interface MermaidPluginOptions {
language?: string; // Language identifier (default: 'mermaid')
mermaidConfig?: MermaidConfig; // Mermaid configuration options
onError?: (error: string) => void; // Error callback
}- Check that styles are imported: Make sure you've imported
@milkdown/plugin-mermaid/style.css - Verify Mermaid syntax: Check the browser console for error messages
- Check configuration: Ensure
mermaidConfigis set correctly if using custom options
- The plugin uses
!importanton some styles to ensure they work correctly. Override them in your CSS with higher specificity or!importantas needed. - Make sure your custom CSS loads after the plugin's default styles.
- Rendering is debounced (300ms in view mode, 500ms in edit mode) to avoid excessive re-renders while typing.
- The plugin caches rendered SVGs internally for better performance.
This is a monorepo containing the plugin package and a demo application.
- Node.js 18+
- pnpm 9+
pnpm installpnpm devThis starts the demo app at apps/demo/ which demonstrates the plugin in action.
pnpm buildpnpm test[Add your license information here]
[Add contribution guidelines here]