Featured image of post 为 Hugo 博客扩展 Mermaid 图表支持

为 Hugo 博客扩展 Mermaid 图表支持

以及在博客中使用 Mermaid 图表功能的指南

什么是 Mermaid?

Mermaid 是一个基于 JavaScript 的图表和流程图生成工具,它允许你用简单的文本语法创建复杂的图表。但是 Hugo 并未原生提供支持。通过下面的步骤,可以为基于 Hugo 的博客扩展对 Mermaid 的支持。

功能特性

查看 Mermaid 图表测试 来预览效果。

支持多种图表类型:流程图、序列图、甘特图、状态图、类图、饼图等
代码与图表切换:可以在渲染的图表和源码之间自由切换
主题适配:自动适配博客的明暗主题
响应式设计:在移动端和桌面端都能完美显示
缩放与拖拽:支持缩放和拖拽操作

代码编辑

注:以下内容适用于 Stack 主题,若在其他主题使用,可能需要自行调整。

下面的步骤均使用在博客根目录布局文件夹中创建同名文件来覆盖主题的方法(Hugo Module)执行修改。请勿直接修改主题文件,否则可能会被主题更新覆盖。

创建布局文件

  • 创建 <博客根目录>/layouts/partials/article/components/content.html 文件。
1
2
3
4
5
<section class="article-content">
    <!-- Refer to https://discourse.gohugo.io/t/responsive-tables-in-markdown/10639/5 -->
    {{ $wrappedTable := printf "<div class=\"table-wrapper\">${1}</div>" }}
    {{ .Content | replaceRE "(<table>(?:.|\n)+?</table>)" $wrappedTable | safeHTML }}
</section>
  • 创建 <博客根目录>/layouts/partials/head/custom.html 文件。
点击展开代码
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
{{/* Mermaid 图表支持的 CSS 样式 */}}
{{ if .Site.Params.mermaid.enable }}
<style>
/* Mermaid 容器样式 */
.mermaid-container {
    position: relative;
    margin: 1.5em 0;
    margin-left: calc((var(--card-padding)) * -1);
    margin-right: calc((var(--card-padding)) * -1);
    width: calc(100% + var(--card-padding) * 2);
    border-radius: var(--card-border-radius);
    overflow: hidden;
    background: var(--card-background);
    box-shadow: var(--shadow-l1);
}

.mermaid-container:hover .mermaid-copy-btn {
    opacity: 1;
}

/* 右下角 ToggleSwitch 控制区域 */
.mermaid-toggle-control {
    position: absolute;
    bottom: calc(var(--card-padding));
    right: calc(var(--card-padding));
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 8px;
}

/* 右上角 Copy 按钮 */
.mermaid-copy-btn {
    position: absolute;
    top: calc(var(--card-padding));
    right: calc(var(--card-padding));
    background: var(--card-background);
    border: none;
    box-shadow: var(--shadow-l2);
    border-radius: var(--tag-border-radius);
    padding: 8px 16px;
    color: var(--card-text-color-main);
    cursor: pointer;
    font-size: 14px;
    opacity: 0;
    transition: opacity 0.3s ease;
    z-index: 10;
}

/* 左下角缩放控制 */
.mermaid-zoom-controls {
    position: absolute;
    bottom: calc(var(--card-padding));
    left: calc(var(--card-padding));
    z-index: 10;
    display: flex;
    gap: 4px;
}

/* ToggleSwitch 样式 */
.mermaid-toggle-switch {
    position: relative;
    display: inline-block;
    width: 54px;
    height: 28px;
    background: var(--body-background);
    border-radius: 14px;
    border: 1px solid var(--card-border);
    cursor: pointer;
    transition: all 0.3s ease;
    box-shadow: var(--shadow-l1);
}

.mermaid-toggle-switch::before {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 22px;
    height: 22px;
    background: var(--accent-color);
    border-radius: 50%;
    transition: all 0.3s ease;
    box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}

.mermaid-toggle-switch.code-mode::before {
    transform: translateX(24px);
    background: var(--card-text-color-secondary);
}

.mermaid-toggle-switch:hover {
    box-shadow: var(--shadow-l2);
}

/* 标签 */
.mermaid-toggle-label {
    font-size: 12px;
    color: var(--card-text-color-secondary);
    font-weight: 500;
    user-select: none;
}

/* 缩放控制按钮 */
.mermaid-zoom-btn {
    width: 28px;
    height: 28px;
    background: var(--card-background);
    border: 1px solid var(--card-border);
    border-radius: var(--tag-border-radius);
    color: var(--card-text-color-main);
    cursor: pointer;
    font-size: 14px;
    font-weight: bold;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.3s ease;
    box-shadow: var(--shadow-l1);
}

.mermaid-zoom-btn:hover {
    background: var(--accent-color);
    color: var(--accent-color-text);
    box-shadow: var(--shadow-l2);
}

.mermaid-zoom-btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

.mermaid-zoom-btn:disabled:hover {
    background: var(--card-background);
    color: var(--card-text-color-main);
    box-shadow: var(--shadow-l1);
}

/* 图表容器样式 */
.mermaid-diagram {
    padding: var(--card-padding);
    background: var(--card-background);
    overflow: auto;
    min-height: 250px;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: grab;
    position: relative;
}

.mermaid-diagram.panning {
    cursor: grabbing;
}

.mermaid-diagram svg {
    max-width: none !important;
    width: auto !important;
    height: auto !important;
    transition: transform 0.3s ease;
    user-select: none;
}

/* 代码容器样式 - 与主题代码块一致 */
.mermaid-code {
    display: none;
    position: relative;
}

.mermaid-code pre {
    margin: 0;
    padding: var(--card-padding);
    background: var(--pre-background-color);
    color: var(--pre-text-color);
    font-family: var(--code-font-family);
    line-height: 1.428571429;
    word-break: break-all;
    overflow-x: auto;
}

.mermaid-code code {
    color: unset;
    border: none;
    background: none;
    padding: 0;
    font-family: var(--code-font-family);
}

/* 错误信息样式 */
.mermaid-error {
    padding: var(--card-padding);
    color: #e74c3c;
    background: rgba(231, 76, 60, 0.1);
    border-left: 4px solid #e74c3c;
    font-family: var(--code-font-family);
    font-size: 0.875rem;
    margin: 0;
}

/* 缩放和拖动状态 */
.mermaid-diagram.zoomed svg {
    transform: scale(var(--mermaid-zoom, 1)) translate(var(--mermaid-pan-x, 0), var(--mermaid-pan-y, 0));
    transform-origin: center;
}

/* SVG 文字修复 */
.mermaid-diagram svg text {
    font-size: 14px !important;
    overflow: visible !important;
}

.mermaid-diagram svg .nodeLabel,
.mermaid-diagram svg .edgeLabel {
    font-size: 14px !important;
    font-weight: 500 !important;
}

.mermaid-diagram svg foreignObject {
    overflow: visible !important;
}

/* 响应式设计 */
@media (max-width: 768px) {
    .mermaid-toggle-control {
        top: 8px;
        left: 8px;
        gap: 6px;
    }
    
    .mermaid-copy-btn {
        top: 8px;
        right: 8px;
        padding: 6px 12px;
        font-size: 12px;
    }
    
    .mermaid-zoom-controls {
        bottom: 8px;
        right: 8px;
        gap: 2px;
    }
    
    .mermaid-toggle-switch {
        width: 48px;
        height: 24px;
    }
    
    .mermaid-toggle-switch::before {
        width: 18px;
        height: 18px;
        top: 2px;
    }
    
    .mermaid-toggle-switch.code-mode::before {
        transform: translateX(22px);
    }
    
    .mermaid-zoom-btn {
        width: 24px;
        height: 24px;
        font-size: 12px;
    }
    
    .mermaid-toggle-label {
        font-size: 11px;
    }
}

/* 明暗主题适配 */
@media (prefers-color-scheme: dark) {
    .mermaid-diagram svg {
        filter: brightness(0.9);
    }
}

/* 主题特定样式 */
[data-scheme="dark"] .mermaid-diagram svg {
    filter: brightness(0.9) contrast(1.1);
}

[data-scheme="light"] .mermaid-diagram svg {
    filter: brightness(1) contrast(1);
}

/* 全屏模式 */
.mermaid-container.fullscreen {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    z-index: 9999;
    background: var(--body-background);
    border-radius: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
}

.mermaid-container.fullscreen .mermaid-diagram {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 40px;
}

.mermaid-container.fullscreen .mermaid-zoom-controls {
    position: absolute;
    bottom: 20px;
    right: 20px;
}

.mermaid-container.fullscreen .mermaid-toggle-control {
    position: absolute;
    top: 20px;
    left: 20px;
}
</style>
{{ end }}
  • 创建 <博客根目录>/layouts/partials/footer/custom.html 文件。
点击展开代码
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
{{/* Mermaid 图表支持 */}}
{{ if .Site.Params.mermaid.enable }}
<!-- Mermaid 配置信息 -->
<script id="mermaid-config" type="application/json">
{
  "theme": "{{ .Site.Params.mermaid.theme | default "default" }}",
  "showToggle": {{ if .Site.Params.mermaid.showToggle }}true{{ else }}true{{ end }}
}
</script>

<!-- Mermaid.js CDN -->
<script src="https://cdn.jsdelivr.net/npm/mermaid@10.6.1/dist/mermaid.min.js"></script>

<script>
document.addEventListener('DOMContentLoaded', function() {
    // 读取配置
    var configElement = document.getElementById('mermaid-config');
    var config = JSON.parse(configElement.textContent);
    
    // 初始化 Mermaid,改进文字显示
    mermaid.initialize({
        startOnLoad: false,
        theme: config.theme,
        themeVariables: {
            fontFamily: 'inherit',
            fontSize: '16px'
        },
        flowchart: {
            htmlLabels: true,
            curve: 'basis',
            padding: 20
        },
        sequence: {
            actorMargin: 50,
            boxMargin: 10,
            boxTextMargin: 5,
            noteMargin: 10,
            messageMargin: 35
        }
    });

    // 查找所有可能的 Mermaid 代码块
    var codeBlocks = document.querySelectorAll('code.language-mermaid, code.language-fallback, code[data-lang="mermaid"]');
    
    var mermaidIndex = 0;
    
    codeBlocks.forEach(function(codeBlock) {
        var codeContent = codeBlock.textContent.trim();
        
        // 检查是否是 Mermaid 代码(通过关键词判断)
        var isMermaid = /^(graph|sequenceDiagram|gantt|stateDiagram|classDiagram|pie|erDiagram|gitgraph|journey|flowchart|mindmap)/.test(codeContent);
        
        if (!isMermaid) return; // 如果不是 Mermaid 代码,跳过
        
        var preElement = codeBlock.parentElement;
        
        // 创建新的容器
        var container = document.createElement('div');
        container.className = 'mermaid-container';
        
        // 创建左上角 ToggleSwitch 控制(如果启用)
        if (config.showToggle) {
            var toggleControl = document.createElement('div');
            toggleControl.className = 'mermaid-toggle-control';
            
            var toggleLabel = document.createElement('span');
            toggleLabel.className = 'mermaid-toggle-label';
            toggleLabel.textContent = '图表';
            
            var toggleSwitch = document.createElement('div');
            toggleSwitch.className = 'mermaid-toggle-switch';
            toggleSwitch.title = '切换显示模式';
            
            toggleControl.appendChild(toggleLabel);
            toggleControl.appendChild(toggleSwitch);
            container.appendChild(toggleControl);
        }
        
        // 创建右上角 Copy 按钮
        var copyBtn = document.createElement('button');
        copyBtn.className = 'mermaid-copy-btn';
        copyBtn.textContent = 'Copy';
        copyBtn.title = '复制';
        container.appendChild(copyBtn);
        
        // 创建右下角缩放控制
        var zoomControls = document.createElement('div');
        zoomControls.className = 'mermaid-zoom-controls';
        
        var zoomOutBtn = document.createElement('button');
        zoomOutBtn.className = 'mermaid-zoom-btn';
        zoomOutBtn.textContent = '−';
        zoomOutBtn.title = '缩小';
        
        var zoomResetBtn = document.createElement('button');
        zoomResetBtn.className = 'mermaid-zoom-btn';
        zoomResetBtn.textContent = '⌂';
        zoomResetBtn.title = '重置缩放和位置';
        
        var zoomInBtn = document.createElement('button');
        zoomInBtn.className = 'mermaid-zoom-btn';
        zoomInBtn.textContent = '+';
        zoomInBtn.title = '放大';
        
        zoomControls.appendChild(zoomOutBtn);
        zoomControls.appendChild(zoomResetBtn);
        zoomControls.appendChild(zoomInBtn);
        container.appendChild(zoomControls);
        
        // 创建图表容器
        var diagramDiv = document.createElement('div');
        diagramDiv.className = 'mermaid-diagram zoomed';
        diagramDiv.id = 'mermaid-diagram-' + mermaidIndex;
        diagramDiv.style.setProperty('--mermaid-zoom', '1');
        diagramDiv.style.setProperty('--mermaid-pan-x', '0px');
        diagramDiv.style.setProperty('--mermaid-pan-y', '0px');
        container.appendChild(diagramDiv);
        
        // 创建代码容器(如果启用切换)
        var codeDiv;
        if (config.showToggle) {
            codeDiv = document.createElement('div');
            codeDiv.className = 'mermaid-code';
            
            var newPre = document.createElement('pre');
            var newCode = document.createElement('code');
            newCode.className = 'language-mermaid';
            newCode.textContent = codeContent;
            newPre.appendChild(newCode);
            codeDiv.appendChild(newPre);
            container.appendChild(codeDiv);
        }
        
        // 替换原始的整个 highlight 容器
        var highlightContainer = preElement.closest('.highlight') || preElement.closest('.chroma') || preElement;
        highlightContainer.parentNode.replaceChild(container, highlightContainer);
        
        // 渲染 Mermaid 图表
        try {
            mermaid.render('mermaid-diagram-' + mermaidIndex + '-svg', codeContent).then(function(result) {
                diagramDiv.innerHTML = result.svg;
                
                // 修复文字显示问题
                var svg = diagramDiv.querySelector('svg');
                if (svg) {
                    svg.style.maxWidth = 'none';
                    svg.style.width = 'auto';
                    svg.style.height = 'auto';
                }
            }).catch(function(error) {
                console.error('Mermaid render error:', error);
                diagramDiv.innerHTML = '<div class="mermaid-error">图表渲染失败: ' + error.message + '</div>';
            });
        } catch (error) {
            console.error('Mermaid init error:', error);
            diagramDiv.innerHTML = '<div class="mermaid-error">图表初始化失败</div>';
        }
        
        // 缩放和拖动功能
        var currentZoom = 1;
        var maxZoom = 3;
        var minZoom = 0.5;
        var zoomStep = 0.25;
        var panX = 0;
        var panY = 0;
        var isDragging = false;
        var lastMouseX = 0;
        var lastMouseY = 0;
        
        function updateTransform() {
            diagramDiv.style.setProperty('--mermaid-zoom', currentZoom);
            diagramDiv.style.setProperty('--mermaid-pan-x', panX + 'px');
            diagramDiv.style.setProperty('--mermaid-pan-y', panY + 'px');
            
            // 更新按钮状态
            zoomOutBtn.disabled = currentZoom <= minZoom;
            zoomInBtn.disabled = currentZoom >= maxZoom;
        }
        
        // 缩放功能
        zoomInBtn.addEventListener('click', function() {
            if (currentZoom < maxZoom) {
                currentZoom = Math.min(maxZoom, currentZoom + zoomStep);
                updateTransform();
            }
        });
        
        zoomOutBtn.addEventListener('click', function() {
            if (currentZoom > minZoom) {
                currentZoom = Math.max(minZoom, currentZoom - zoomStep);
                updateTransform();
            }
        });
        
        zoomResetBtn.addEventListener('click', function() {
            currentZoom = 1;
            panX = 0;
            panY = 0;
            updateTransform();
        });
        
        // 拖动功能
        diagramDiv.addEventListener('mousedown', function(e) {
            if (currentZoom > 1) {
                isDragging = true;
                lastMouseX = e.clientX;
                lastMouseY = e.clientY;
                diagramDiv.classList.add('panning');
                e.preventDefault();
            }
        });
        
        document.addEventListener('mousemove', function(e) {
            if (isDragging) {
                var deltaX = e.clientX - lastMouseX;
                var deltaY = e.clientY - lastMouseY;
                
                panX += deltaX;
                panY += deltaY;
                
                lastMouseX = e.clientX;
                lastMouseY = e.clientY;
                
                updateTransform();
            }
        });
        
        document.addEventListener('mouseup', function() {
            if (isDragging) {
                isDragging = false;
                diagramDiv.classList.remove('panning');
            }
        });
        
        // 初始化缩放状态
        updateTransform();
        
        // Copy 按钮功能
        copyBtn.addEventListener('click', function() {
            var isDiagramMode = diagramDiv.style.display !== 'none';
            var textToCopy = codeContent;
            
            navigator.clipboard.writeText(textToCopy).then(function() {
                copyBtn.textContent = 'Copied!';
                setTimeout(function() {
                    copyBtn.textContent = 'Copy';
                }, 1000);
            }).catch(function(err) {
                console.error('Copy failed:', err);
                alert('复制失败');
            });
        });
        
        // 切换开关事件(如果启用)
        if (config.showToggle) {
            var isDiagramMode = true;
            
            toggleSwitch.addEventListener('click', function() {
                isDiagramMode = !isDiagramMode;
                
                if (isDiagramMode) {
                    // 切换到图表模式
                    toggleSwitch.classList.remove('code-mode');
                    toggleLabel.textContent = '图表';
                    diagramDiv.style.display = 'flex';
                    codeDiv.style.display = 'none';
                    zoomControls.style.display = 'flex';
                } else {
                    // 切换到源码模式
                    toggleSwitch.classList.add('code-mode');
                    toggleLabel.textContent = '源码';
                    diagramDiv.style.display = 'none';
                    codeDiv.style.display = 'block';
                    zoomControls.style.display = 'none';
                }
                
                // 保存用户偏好
                localStorage.setItem('mermaid-view-preference', isDiagramMode ? 'diagram' : 'code');
            });
            
            // 恢复用户偏好
            var savedPreference = localStorage.getItem('mermaid-view-preference');
            if (savedPreference === 'code') {
                toggleSwitch.click();
            }
        }
        
        mermaidIndex++;
    });
});
</script>
{{ end }}

配置选项

hugo.yaml 中可以配置以下选项:

1
2
3
4
5
params:
  mermaid:
    enable: true          # 是否启用 Mermaid 功能
    theme: "default"      # 主题:default, dark, forest, neutral
    showToggle: true      # 是否显示切换按钮

使用方法

在 Markdown 文件中使用 mermaid 代码块:

1
2
3
4
5
```mermaid
graph TD
    A[开始] --> B[处理]
    B --> C[结束]
```

基本语法示例

简单流程图

1
2
3
4
```mermaid
graph LR
    A --> B --> C
```

带标签的流程图

1
2
3
4
5
6
7
```mermaid
graph TD
    A[方形] --> B(圆角)
    B --> C{菱形}
    C -->|是| D[结果1]
    C -->|否| E[结果2]
```

简单序列图

1
2
3
4
5
```mermaid
sequenceDiagram
    Alice->>Bob: 你好
    Bob-->>Alice: 你好
```

简单甘特图

1
2
3
4
5
6
7
```mermaid
gantt
    title 项目计划
    section 阶段一
        任务1: 2024-01-01, 5d
        任务2: after 任务1, 3d
```

高级用法

自定义样式

1
2
3
4
5
6
graph TD
    A[开始] --> B[处理]
    B --> C[结束]
    
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style C fill:#bbf,stroke:#333,stroke-width:2px

复杂的序列图

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
sequenceDiagram
    participant A as 用户
    participant B as 系统
    participant C as 数据库
    
    A->>B: 登录请求
    B->>C: 验证用户
    C-->>B: 返回结果
    alt 验证成功
        B-->>A: 登录成功
    else 验证失败
        B-->>A: 登录失败
    end

支持的图表类型

图表类型关键词用途
流程图graph / flowchart流程展示
序列图sequenceDiagram交互过程
甘特图gantt项目计划
状态图stateDiagram状态转换
类图classDiagram类关系
饼图pie数据占比
ER图erDiagram数据库设计
用户旅程图journey用户体验

切换功能说明

每个 Mermaid 图表都会显示两个切换按钮:

  • 图表:显示渲染后的 SVG 图表
  • 源码:显示原始的 Mermaid 代码

你的选择偏好会自动保存,下次访问时会记住你的选择。

故障排除

图表不显示?

  1. 检查配置:确保 hugo.yamlparams.mermaid.enabletrue
  2. 检查语法:确保 Mermaid 语法正确
  3. 查看控制台:打开浏览器开发者工具查看错误信息

图表显示异常?

  1. 刷新页面重新加载
  2. 检查网络:确保 CDN 资源能正常加载
  3. 尝试不同的图表主题

更多资源


享受用 Mermaid 创建漂亮图表的乐趣吧!🎨