lexical-mermaid
v0.5.0
Published
Mermaid plugin for Lexical Editor
Readme
lexical-mermaid
A Mermaid diagram plugin for Lexical Editor.
Features
- 📊 Interactive Diagrams - Embed editable Mermaid diagrams in your editor with click-to-edit functionality
- 🚀 Easy Integration - Simply add the plugin and node to get started
- ⌨️ Markdown Syntax Support - Auto-insert diagrams with
```mermaid+ Enter - 📥 Export Functionality - Export diagrams as SVG or PNG with hover buttons
- 🎨 Customizable - Configure themes and security levels
- 📦 Lightweight - Minimal bundle size using peer dependencies
- 🔧 Full TypeScript Support - Type definitions included
Installation
npm install lexical-mermaidPeer Dependencies
This package requires the following peer dependencies:
npm install lexical @lexical/react mermaid react react-domMinimum versions:
lexical>= 0.17.0@lexical/react>= 0.17.0mermaid>= 11.0.0react>= 18.0.0react-dom>= 18.0.0
Basic Usage
1. Add Plugin to Lexical Editor
import { useEffect } from 'react'
import { LexicalComposer } from '@lexical/react/LexicalComposer'
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin'
import { ContentEditable } from '@lexical/react/LexicalContentEditable'
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin'
import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary'
import {
MermaidNode,
MermaidPlugin,
MermaidMarkdownPlugin,
initMermaid,
} from 'lexical-mermaid'
const editorConfig = {
namespace: 'MyEditor',
nodes: [MermaidNode], // Register MermaidNode
onError: (error: Error) => {
console.error(error)
},
}
function Editor() {
useEffect(() => {
// Initialize Mermaid
initMermaid()
}, [])
return (
<LexicalComposer initialConfig={editorConfig}>
<RichTextPlugin
contentEditable={<ContentEditable />}
placeholder={<div>Enter some text...</div>}
ErrorBoundary={LexicalErrorBoundary}
/>
<HistoryPlugin />
<MermaidPlugin /> {/* Mermaid insertion plugin */}
<MermaidMarkdownPlugin /> {/* ```mermaid syntax support */}
</LexicalComposer>
)
}2. Insert Mermaid Diagram from Button
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { INSERT_MERMAID_COMMAND, getDefaultMermaidCode } from 'lexical-mermaid'
function Toolbar() {
const [editor] = useLexicalComposerContext()
const insertMermaid = () => {
editor.dispatchCommand(INSERT_MERMAID_COMMAND, getDefaultMermaidCode())
}
return (
<button onClick={insertMermaid}>
Insert Mermaid Diagram
</button>
)
}3. Insert with Markdown Syntax
Type the following in the editor:
```mermaidPress Enter, and it will automatically convert to a Mermaid diagram.
4. Use Custom Templates
import { INSERT_MERMAID_COMMAND } from 'lexical-mermaid'
const flowchartTemplate = `graph TD
A[Start] --> B{Decision}
B -->|Yes| C[Process A]
B -->|No| D[Process B]
C --> E[End]
D --> E`
function insertFlowchart() {
editor.dispatchCommand(INSERT_MERMAID_COMMAND, flowchartTemplate)
}5. Export Diagrams
Diagrams can be exported as SVG or PNG files. Export buttons appear when you hover over a diagram.
Using the built-in UI:
- Hover over any Mermaid diagram
- Click the "SVG" or "PNG" button in the top-right corner
- The file will be automatically downloaded with a timestamp
Programmatic export:
import { exportSVG, exportPNG } from 'lexical-mermaid'
// Export as SVG
const result = await exportSVG(svgString)
if (!result.success) {
console.error('Export failed:', result.error)
}
// Export as PNG with custom filename
const result = await exportPNG(svgString, 'my-diagram.png')Export filename format:
- Default:
mermaid-diagram-YYYY-MM-DD-HHMMSS.svgor.png - Example:
mermaid-diagram-2025-12-29-153045.png
API
Exports
Nodes
MermaidNode- Lexical node representing a Mermaid diagram$createMermaidNode(code: string)- Create a MermaidNode$isMermaidNode(node)- Check if a node is a MermaidNode
Plugins
MermaidPlugin- Register Mermaid insertion commandMermaidMarkdownPlugin- Detect and auto-convert```mermaidsyntax
Commands
INSERT_MERMAID_COMMAND- Command to insert Mermaid diagrams
Components
MermaidComponent- Mermaid diagram display componentMermaidEditor- Mermaid code editor component
Utilities
initMermaid(config?: MermaidConfig)- Initialize Mermaid libraryvalidateMermaidCode(code: string)- Validate Mermaid coderenderMermaid(code: string, elementId: string)- Render Mermaid diagramgetDefaultMermaidCode()- Get default Mermaid codeexportSVG(svgString: string, filename?: string)- Export diagram as SVG fileexportPNG(svgString: string, filename?: string)- Export diagram as PNG file
Type Definitions
MermaidTheme- Mermaid theme configurationMermaidConfig- Mermaid configuration optionsMermaidNodeData- MermaidNode data typeSerializedMermaidNode- Serialized MermaidNodeExportFormat- Export format type ('svg' | 'png')ExportResult- Export operation resultExportOptions- Export configuration optionsMermaidComponentStyles- Style customization for MermaidComponentMermaidComponentClassNames- ClassName customization for MermaidComponentMermaidEditorStyles- Style customization for MermaidEditorMermaidEditorClassNames- ClassName customization for MermaidEditorMermaidErrorRenderer- Custom error renderer function typeMermaidLoadingRenderer- Custom loading renderer function type
Context
MermaidStyleProvider- Context provider for style customizationuseMermaidStyle()- Hook to access style contextMermaidStyleContextValue- Context value type
Configuration
Mermaid Initialization Options
import { initMermaid } from 'lexical-mermaid'
initMermaid({
theme: 'dark', // 'default' | 'dark' | 'forest' | 'neutral'
securityLevel: 'strict', // 'strict' | 'loose' | 'antiscript'
startOnLoad: false,
logLevel: 'error',
})Supported Diagram Types
All Mermaid diagram types are supported:
- Flowchart
- Sequence Diagram
- Class Diagram
- State Diagram
- Entity Relationship Diagram
- Gantt Chart
- Pie Chart
- Git Graph
- And more
See Mermaid Documentation for details.
Style Customization
You can customize the appearance of Mermaid diagrams and editors by providing styles and classNames through the MermaidPlugin.
Using inline styles:
import { MermaidPlugin } from 'lexical-mermaid'
function Editor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<MermaidPlugin
componentStyles={{
diagramContainer: {
padding: '2rem',
backgroundColor: '#f5f5f5',
},
exportButton: {
backgroundColor: '#ff5722',
},
}}
editorStyles={{
container: {
borderColor: '#ff5722',
},
saveButton: {
backgroundColor: '#4caf50',
},
}}
/>
{/* ... */}
</LexicalComposer>
)
}Using CSS classes:
<MermaidPlugin
componentClassNames={{
container: 'my-mermaid-container',
diagramContainer: 'my-diagram',
exportButton: 'my-export-btn',
}}
editorClassNames={{
container: 'my-editor-container',
textarea: 'my-textarea',
}}
/>Customizable elements:
MermaidComponent (Display Mode):
container- Outer wrapperdiagramContainer- Diagram display areadiagramContent- SVG content wrapperexportButtonContainer- Export buttons wrapperexportButton- SVG/PNG export buttonserrorContainer- Error message arealoadingContainer- Loading state display
MermaidEditor (Edit Mode):
container- Editor wrapperhint- Hint texttextarea- Code input areabuttonContainer- Button wrappersaveButton- Save buttoncancelButton- Cancel buttondeleteButton- Delete button
Note: Both styles and classNames can be used together. Inline styles take precedence over default styles.
Custom Error and Loading Components
You can provide custom render functions for error and loading states:
import type { MermaidErrorRenderer, MermaidLoadingRenderer } from 'lexical-mermaid'
const customErrorRenderer: MermaidErrorRenderer = (error) => (
<div style={{ padding: '1rem', backgroundColor: '#ffe0e0', color: '#cc0000' }}>
<h3>Oops! Something went wrong</h3>
<p>{error}</p>
<button onClick={() => console.log('Retry')}>Retry</button>
</div>
)
const customLoadingRenderer: MermaidLoadingRenderer = () => (
<div style={{ textAlign: 'center', padding: '2rem' }}>
<div className="spinner" />
<p>Loading diagram...</p>
</div>
)
function Editor() {
return (
<LexicalComposer initialConfig={editorConfig}>
<MermaidPlugin
renderError={customErrorRenderer}
renderLoading={customLoadingRenderer}
/>
{/* ... */}
</LexicalComposer>
)
}Renderer function signatures:
MermaidErrorRenderer: (error: string) => React.ReactNodeMermaidLoadingRenderer: () => React.ReactNode
These custom renderers completely replace the default error and loading UI, giving you full control over their appearance and behavior.
Development
Testing with Storybook
# Start Storybook
npm run storybook
# Open http://localhost:6006 in your browserBuilding
# Build the plugin
npm run build
# Development with watch mode
npm run dev
# Type checking
npm run type-checkProject Structure
lexical-mermaid/
├── src/
│ ├── components/ # React components
│ ├── nodes/ # Lexical nodes
│ ├── plugins/ # Lexical plugins
│ ├── stories/ # Storybook stories
│ ├── types/ # TypeScript type definitions
│ ├── utils/ # Utilities
│ └── index.ts # Entry point
├── .storybook/ # Storybook configuration
└── dist/ # Build outputLicense
MIT License - See LICENSE for details.
Contributing
Bug reports and feature requests are welcome on GitHub Issues.
References
- Lexical Documentation
- Mermaid Documentation
- Storybook - Local development
