MermaidBlockNode (Component)
MermaidBlockNode is a lightweight, extensible renderer for Mermaid diagrams intended for embedding interactive Mermaid charts within documents. The component supports progressive rendering, source/preview toggling, copying source, exporting SVG, and a pseudo-fullscreen modal (with zoom and drag).
Props (key)
node: any— the Mermaid code node (required)isDark?: boolean— dark mode flagloading?: boolean— initial loading placeholdermaxHeight?: string | null— maximum heightisStrict?: boolean— run Mermaid insecurityLevel: 'strict'with DOMPurify + HTML-label hardening; use this when rendering untrusted diagrams to strip inline scripts/javascript:URLs that could otherwise leak into the SVGonRenderError?: (error: unknown, code: string, container: HTMLElement) => boolean | void— custom error handler called when mermaid rendering fails. Returntrueto prevent the default error display. Receives the error, the raw mermaid source code, and the container DOM element so you can render custom content.- Header / control props (all optional, default
true):showHeader,showModeToggle,showCopyButton,showExportButton,showFullscreenButton,showCollapseButton,showZoomControls,showTooltips
enableWheelZoom?: boolean— enable Ctrl/Cmd + wheel zoom in the canvas (defaultfalse)- Timeouts (ms):
workerTimeoutMs,parseTimeoutMs,renderTimeoutMs,fullRenderTimeoutMs(defaults:1400/1800/2500/4000) - Streaming tuning:
renderDebounceMs,contentStableDelayMs,previewPollDelayMs,previewPollMaxDelayMs,previewPollMaxAttempts
Slots
header-left— replace the left area (defaults to Mermaid icon + label)header-center— replace the center area (defaults to preview/source toggle)header-right— replace the right-side action buttons (take full control of the default controls)
Emits
The component emits events using a unified MermaidBlockEvent object. Listeners can call preventDefault() on the event to stop the component's default behavior:
copy— copy button clicked, signature:(ev: MermaidBlockEvent<{ type: 'copy'; text: string }>)(callev.preventDefault()to stop the built-in clipboard write + "Copied" state)export— export button clicked, signature:(ev: MermaidBlockEvent<{ type: 'export' }>)openModal— request to open the pseudo-fullscreen modal, signature:(ev: MermaidBlockEvent<{ type: 'open-modal' }>)toggleMode— toggle betweensourceandpreview, signature:(target: 'source' | 'preview', ev: MermaidBlockEvent<{ type: 'toggle-mode'; target: 'source' | 'preview' }>)
Intercept example
Completely override the component's default export behavior:
<script setup lang="ts">
import type { MermaidBlockEvent } from 'markstream-vue'
import { MermaidBlockNode } from 'markstream-vue'
function onExport(ev: any /* MermaidBlockEvent */) {
ev.preventDefault()
// The component exposes the rendered SVG element on the event as `svgElement`.
const svgEl = ev.svgElement as SVGElement | null
if (!svgEl) {
console.warn('No svg element available')
return
}
const svgString = new XMLSerializer().serializeToString(svgEl)
uploadSvg(svgString)
}
</script>
<template>
<MermaidBlockNode :node="node" @export="onExport" />
</template>Note: The event object includes both
svgElement(DOM node) andsvgString(serialized SVG) onexportandopenModalevents — use whichever is more convenient.
Slot example — fully replace right-side controls
<MermaidBlockNode :node="node" :showExportButton="false">
<template #header-right>
<button @click="downloadSvg">Download</button>
<button @click="openCustomModal">Open custom modal</button>
</template>
</MermaidBlockNode>Recommended usage
- To implement custom export/upload behavior, call
preventDefault()in theexportlistener and extract the SVG from the rendered DOM in your handler. - To fully replace the header UI, use the
header-*slots and set the correspondingshow*props tofalseto hide the default controls. - If Mermaid content originates from users/LLMs or any untrusted source, set
:is-strict="true"so the component sanitizes the SVG and disables HTML labels; this closes the gap where craftedjavascript:URLs or event handlers could sneak into the rendered output. - In AI chat scenarios, use
onRenderErrorto show raw mermaid source instead of the default error message:
<script setup lang="ts">
import { MermaidBlockNode } from 'markstream-vue'
function handleMermaidError(_err: unknown, code: string, container: HTMLElement) {
// Show the raw mermaid text as a code block instead of an error message
const pre = document.createElement('pre')
pre.className = 'text-sm font-mono whitespace-pre-wrap p-4'
pre.textContent = code
container.replaceChildren(pre)
return true // prevent default error display
}
</script>
<template>
<MermaidBlockNode :node="node" :on-render-error="handleMermaidError" />
</template>Notes:
svgStringis already included inexportandopenModalevent payloads (the serialized SVG string is available on the event), so consumers can upload or post the SVG without re-serializing.- This page is linked from the docs sidebar and a runnable playground demo is provided in the repo (route:
/mermaid-export-demo, file:playground/src/pages/mermaid-export-demo.vue).
See also
- Override
MermaidBlockNode(usesetCustomComponentswithMarkdownRender): Override MermaidBlockNode in MarkdownRender
Playground demo: there's a runnable playground page demonstrating how to intercept export and upload ev.svgString — see the playground route mermaid-export-demo (file: playground/src/pages/mermaid-export-demo.vue).
Try this — quick mermaid example you can paste into a component:
<script setup lang="ts">
import MarkdownRender from 'markstream-vue'
const md = `\n\`\`\`mermaid\ngraph TD\nA-->B\n\`\`\`\n`
</script>
<template>
<MarkdownRender :content="md" />
</template>