MermaidBlockNode (Component)
MermaidBlockNode 提供一个易于使用且可扩展的 Mermaid 渲染器,适用于需要在文档中内嵌交互式 Mermaid 图的场景。组件支持渐进式渲染、源码/预览切换、复制源码、导出 SVG,以及伪全屏查看(带缩放与拖拽)。
Props(关键)
node: any— Mermaid 代码节点(必须)isDark?: boolean— 暗色模式开关loading?: boolean— 初始加载占位maxHeight?: string | null— 最大高度estimatedPreviewHeightPx?: number— Mermaid 完成渲染前预留的首屏 preview 高度;通过MarkdownRender渲染 Mermaid 围栏时会自动填入isStrict?: boolean— 默认true;开启securityLevel: 'strict'+ DOMPurify,并禁用 HTML labels。只有可信图表确实需要 Mermaid loose 解析/渲染配置时才设为false;最终 SVG 挂载和导出前仍会清理。enableMermaidInteractions?: boolean— 默认false;在清理后的 SVG 挂载后启用 Mermaid 生成的点击绑定。只建议用于可信图表。- Header/按钮控制(全部可选,默认
true):showHeader/showModeToggle/showCopyButton/showExportButton/showFullscreenButton/showCollapseButton/showZoomControls/showTooltips
enableWheelZoom?: boolean— 开启 Ctrl/Cmd + 滚轮缩放(默认false)- 超时(毫秒):
workerTimeoutMs/parseTimeoutMs/renderTimeoutMs/fullRenderTimeoutMs(默认1400/1800/2500/4000) - 流式调优:
renderDebounceMs/contentStableDelayMs/previewPollDelayMs/previewPollMaxDelayMs/previewPollMaxAttempts
Slots
header-left— 替换左侧(默认是 Mermaid 图标 + 标签)header-center— 替换中间区域(默认 preview/source 切换)header-right— 替换右侧操作按钮(完整接管默认按钮)
Emits
组件发出的事件都使用统一的 MermaidBlockEvent 对象,支持 preventDefault() 来阻止组件默认行为:
copy— 点击复制按钮,处理签名:(ev: MermaidBlockEvent<{ type: 'copy'; text: string }>)(调用ev.preventDefault()可阻止组件默认的复制到剪贴板与 “Copied” 状态)export— 导出按钮点击,处理签名:(ev: MermaidBlockEvent<{ type: 'export' }>)openModal— 请求打开 pseudo-fullscreen,处理签名:(ev: MermaidBlockEvent<{ type: 'open-modal' }>)(组件内部 emit 名称为openModal)toggleMode— 切换source | preview,处理签名:(target: 'source' | 'preview', ev: MermaidBlockEvent<{ type: 'toggle-mode'; target: 'source' | 'preview' }>)(组件内部 emit 名称为toggleMode)
拦截示例
完全替换组件默认导出行为:
vue
<script setup lang="ts">
import type { MermaidBlockEvent } from 'markstream-vue'
import { MermaidBlockNode } from 'markstream-vue'
function onExport(ev: any /* MermaidBlockEvent */) {
ev.preventDefault()
// 组件在事件对象中暴露了 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>注意:
export/openModal事件的事件对象现已同时包含svgElement(DOM 节点)和svgString(已序列化的 SVG 字符串),任选其一使用更方便。
Slot 示例:完全接管右侧操作按钮
vue
<MermaidBlockNode :node="node" :showExportButton="false">
<template #header-right>
<button @click="downloadSvg">Download</button>
<button @click="openCustomModal">Open custom modal</button>
</template>
</MermaidBlockNode>推荐用法
- 如果你要实现自定义导出/上传,最佳做法是:在
export监听器中preventDefault(),并在监听回调中直接从组件渲染的 DOM 中读取svg。 - 如果你想要完全替换头部的 UI,使用
header-*插槽并把相应show*props 设为false来隐藏默认按钮。 - Mermaid 严格模式默认开启,因此用户/LLM 图表会使用 Mermaid strict 配置渲染,并在挂载前清理 SVG。只有可信图表需要 Mermaid loose 配置时,才设置
:is-strict="false";最终 SVG 仍会被清理。 - Mermaid 点击绑定默认关闭。只有可信图表需要 Mermaid
click回调时,才设置:enable-mermaid-interactions="true"。
为可信图表启用 Mermaid loose 配置
如果某个可信 Mermaid 图确实需要 Mermaid loose 解析/渲染配置,可以按组件粒度显式关闭 strict,而不是把更安全的默认值整体改回去。这不会恢复原始 SVG 插入:Markstream 在 strict 和 loose 模式下都会清理 Mermaid SVG 输出,因此 foreignObject 和 active HTML labels 可能会被移除。
vue
<script setup lang="ts">
import { MermaidBlockNode } from 'markstream-vue'
const node = {
type: 'code_block',
language: 'mermaid',
code: 'flowchart TD\n A["<b>可信</b><br/>label"] --> B',
raw: 'flowchart TD\n A["<b>可信</b><br/>label"] --> B',
}
</script>
<template>
<MermaidBlockNode :node="node" :is-strict="false" />
</template>只有 Mermaid 源内容可信时才建议这样做;用户内容或 LLM 输出仍建议保留默认 strict。
参考
- 覆盖
MermaidBlockNode(在MarkdownRender中使用setCustomComponents)的示例(中文):覆盖 MermaidBlockNode(MarkdownRender 示例)
Playground 示例:仓库包含一个可运行的 playground 页面演示如何拦截 export 并上传 ev.svgString —— 路由: mermaid-export-demo (文件:playground/src/pages/mermaid-export-demo.vue)。