2026-01-24 21:35:12 +08:00
|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
|
<title>Mermaid 代码块魔改测试</title>
|
|
|
|
|
|
<style>
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
|
|
|
|
max-width: 1200px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
background: #f5f5f5;
|
|
|
|
|
|
}
|
|
|
|
|
|
.test-case {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
padding: 20px;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
|
|
|
|
}
|
|
|
|
|
|
.test-case h3 {
|
|
|
|
|
|
margin-top: 0;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
border-bottom: 2px solid #007bff;
|
|
|
|
|
|
padding-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.test-case .description {
|
|
|
|
|
|
color: #666;
|
|
|
|
|
|
margin-bottom: 15px;
|
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.mermaid-from-codeblock {
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: 1px solid #dee2e6;
|
|
|
|
|
|
}
|
|
|
|
|
|
pre {
|
|
|
|
|
|
background: #f8f9fa;
|
|
|
|
|
|
padding: 15px;
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
border: 1px solid #dee2e6;
|
|
|
|
|
|
overflow-x: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
code {
|
|
|
|
|
|
font-family: 'Courier New', Courier, monospace;
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
<!-- Mermaid 库 -->
|
|
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
|
|
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<h1>Mermaid 代码块魔改测试</h1>
|
|
|
|
|
|
<p>本页面用于测试标准 Markdown 代码块 (<code>```mermaid</code>) 的 Mermaid 图表渲染功能。</p>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 1:标准格式 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 1:标准 Markdown 格式</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
格式:<code><pre><code class="language-mermaid"></code>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A[开始] --> B{判断}
|
|
|
|
|
|
B -->|是| C[执行操作]
|
|
|
|
|
|
B -->|否| D[跳过]
|
|
|
|
|
|
C --> E[结束]
|
|
|
|
|
|
D --> E
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 2:多个代码块 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 2:多个代码块(批量处理)</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
测试同一页面中多个 Mermaid 代码块的处理
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
graph LR
|
|
|
|
|
|
A[客户端] --> B[服务器]
|
|
|
|
|
|
B --> C[数据库]
|
|
|
|
|
|
C --> B
|
|
|
|
|
|
B --> A
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
<br>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
sequenceDiagram
|
|
|
|
|
|
participant 用户
|
|
|
|
|
|
participant 系统
|
|
|
|
|
|
用户->>系统: 发送请求
|
|
|
|
|
|
系统->>用户: 返回响应
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 3:特殊字符 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 3:特殊字符保留</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
测试箭头符号 <code>--></code>、双横线 <code>--</code>、等号 <code>==</code> 等特殊字符是否正确保留
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
flowchart TD
|
|
|
|
|
|
A --> B
|
|
|
|
|
|
B -- 文本 --> C
|
|
|
|
|
|
C ==> D
|
|
|
|
|
|
D -.-> E
|
|
|
|
|
|
E ~~~ F
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 4:空代码块 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 4:空代码块(边界情况)</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
测试空代码块是否会导致错误
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid"></code></pre>
|
|
|
|
|
|
<p style="color: #666; font-size: 14px;">空代码块应该被跳过,不会创建容器</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 5:多行代码块 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 5:多行代码块(换行符保留)</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
测试多行代码块中的换行符是否正确保留
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
graph TB
|
|
|
|
|
|
subgraph 子图1
|
|
|
|
|
|
A1[节点A1]
|
|
|
|
|
|
A2[节点A2]
|
|
|
|
|
|
end
|
|
|
|
|
|
subgraph 子图2
|
|
|
|
|
|
B1[节点B1]
|
|
|
|
|
|
B2[节点B2]
|
|
|
|
|
|
end
|
|
|
|
|
|
A1 --> B1
|
|
|
|
|
|
A2 --> B2
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 6:简化格式 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 6:简化格式</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
格式:<code><pre><code class="mermaid"></code>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="mermaid">
|
|
|
|
|
|
pie title 数据分布
|
|
|
|
|
|
"类别A" : 45
|
|
|
|
|
|
"类别B" : 30
|
|
|
|
|
|
"类别C" : 25
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 7:无 pre 包裹 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 7:无 pre 包裹</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
格式:<code><code class="language-mermaid"></code>(无 pre 标签)
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<code class="language-mermaid">
|
|
|
|
|
|
flowchart LR
|
|
|
|
|
|
Start --> Stop
|
|
|
|
|
|
</code>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 8:自定义属性格式 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 8:自定义属性格式</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
格式:<code><pre data-lang="mermaid"></code>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre data-lang="mermaid">
|
|
|
|
|
|
stateDiagram-v2
|
|
|
|
|
|
[*] --> 状态1
|
|
|
|
|
|
状态1 --> 状态2
|
|
|
|
|
|
状态2 --> [*]
|
|
|
|
|
|
</pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 测试用例 9:复杂图表 -->
|
|
|
|
|
|
<div class="test-case">
|
|
|
|
|
|
<h3>测试用例 9:复杂图表</h3>
|
|
|
|
|
|
<div class="description">
|
|
|
|
|
|
测试复杂的 Mermaid 图表渲染
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<pre><code class="language-mermaid">
|
|
|
|
|
|
classDiagram
|
|
|
|
|
|
Animal <|-- Duck
|
|
|
|
|
|
Animal <|-- Fish
|
|
|
|
|
|
Animal <|-- Zebra
|
|
|
|
|
|
Animal : +int age
|
|
|
|
|
|
Animal : +String gender
|
|
|
|
|
|
Animal: +isMammal()
|
|
|
|
|
|
Animal: +mate()
|
|
|
|
|
|
class Duck{
|
|
|
|
|
|
+String beakColor
|
|
|
|
|
|
+swim()
|
|
|
|
|
|
+quack()
|
|
|
|
|
|
}
|
|
|
|
|
|
class Fish{
|
|
|
|
|
|
-int sizeInFeet
|
|
|
|
|
|
-canEat()
|
|
|
|
|
|
}
|
|
|
|
|
|
class Zebra{
|
|
|
|
|
|
+bool is_wild
|
|
|
|
|
|
+run()
|
|
|
|
|
|
}
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// 初始化 Mermaid
|
|
|
|
|
|
mermaid.initialize({
|
|
|
|
|
|
startOnLoad: false,
|
|
|
|
|
|
theme: 'default',
|
|
|
|
|
|
securityLevel: 'loose'
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
// 模拟主题的 convertMermaidCodeblocks 函数
|
|
|
|
|
|
function convertMermaidCodeblocks(){
|
|
|
|
|
|
const selectors = [
|
|
|
|
|
|
'pre > code.language-mermaid',
|
|
|
|
|
|
'pre > code.mermaid',
|
|
|
|
|
|
'code.language-mermaid',
|
|
|
|
|
|
'pre[data-lang="mermaid"]'
|
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
|
|
let processedCount = 0;
|
|
|
|
|
|
|
|
|
|
|
|
selectors.forEach(selector => {
|
|
|
|
|
|
document.querySelectorAll(selector).forEach(element => {
|
|
|
|
|
|
if (element.dataset.mermaidProcessed) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let code = element.textContent.trim();
|
|
|
|
|
|
if (!code) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const container = document.createElement('div');
|
|
|
|
|
|
container.className = 'mermaid-from-codeblock';
|
|
|
|
|
|
container.textContent = code;
|
|
|
|
|
|
container.dataset.processed = 'true';
|
|
|
|
|
|
|
|
|
|
|
|
const targetElement = element.closest('pre') || element;
|
|
|
|
|
|
if (targetElement.parentNode) {
|
|
|
|
|
|
targetElement.parentNode.replaceChild(container, targetElement);
|
|
|
|
|
|
processedCount++;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
element.dataset.mermaidProcessed = 'true';
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[Mermaid] 转换了 ' + processedCount + ' 个代码块');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 渲染 Mermaid 图表
|
|
|
|
|
|
function renderMermaidCharts(){
|
|
|
|
|
|
const blocks = document.querySelectorAll('.mermaid-from-codeblock');
|
|
|
|
|
|
console.log('[Mermaid] 找到 ' + blocks.length + ' 个待渲染的图表');
|
|
|
|
|
|
|
|
|
|
|
|
blocks.forEach((block, index) => {
|
|
|
|
|
|
const id = 'mermaid-' + Date.now() + '-' + index;
|
|
|
|
|
|
const code = block.textContent;
|
|
|
|
|
|
|
|
|
|
|
|
try {
|
2026-01-24 21:43:42 +08:00
|
|
|
|
// Mermaid 10.x 使用 render 方法,返回 Promise
|
|
|
|
|
|
mermaid.render(id, code).then(function(result) {
|
2026-01-24 21:35:12 +08:00
|
|
|
|
block.innerHTML = result.svg;
|
|
|
|
|
|
console.log('[Mermaid] 成功渲染图表 ' + (index + 1));
|
2026-01-24 21:43:42 +08:00
|
|
|
|
}).catch(function(error) {
|
2026-01-24 21:35:12 +08:00
|
|
|
|
console.error('[Mermaid] 渲染失败:', error);
|
|
|
|
|
|
block.innerHTML = '<div style="color: red; padding: 10px; border: 1px solid red; border-radius: 4px;">渲染失败: ' + error.message + '</div>';
|
|
|
|
|
|
});
|
|
|
|
|
|
} catch (error) {
|
|
|
|
|
|
console.error('[Mermaid] 渲染异常:', error);
|
2026-01-24 21:43:42 +08:00
|
|
|
|
block.innerHTML = '<div style="color: red; padding: 10px; border: 1px solid red; border-radius: 4px;">渲染异常: ' + error.message + '</div>';
|
2026-01-24 21:35:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 页面加载完成后执行
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
|
|
|
|
console.log('[测试] 开始执行代码块转换');
|
|
|
|
|
|
convertMermaidCodeblocks();
|
|
|
|
|
|
|
|
|
|
|
|
console.log('[测试] 开始渲染 Mermaid 图表');
|
|
|
|
|
|
setTimeout(renderMermaidCharts, 100);
|
|
|
|
|
|
});
|
|
|
|
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
</html>
|