fix: 修复代码高亮和容器语法的两个关键问题
- 代码高亮排除 mermaid 代码块,避免干扰渲染 - 容器语法正确处理空行,不再截断内容 - 添加测试页面验证修复效果
This commit is contained in:
131
argontheme.js
131
argontheme.js
@@ -3959,6 +3959,14 @@ function highlightJsRender(){
|
|||||||
if ($(block).hasClass("no-hljs")){
|
if ($(block).hasClass("no-hljs")){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// 跳过 mermaid 代码块(避免代码高亮干扰 mermaid 渲染)
|
||||||
|
if ($(block).hasClass("language-mermaid") || $(block).hasClass("mermaid")){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 跳过在 .mermaid 容器内的代码块
|
||||||
|
if ($(block).closest('.mermaid').length > 0){
|
||||||
|
return;
|
||||||
|
}
|
||||||
$(block).parent().attr("id", randomString());
|
$(block).parent().attr("id", randomString());
|
||||||
hljs.highlightBlock(block);
|
hljs.highlightBlock(block);
|
||||||
hljs.lineNumbersBlock(block, {singleLine: true});
|
hljs.lineNumbersBlock(block, {singleLine: true});
|
||||||
@@ -4440,6 +4448,10 @@ void 0;
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 检测 Markdown 容器语法的 Mermaid 代码块
|
||||||
|
// 格式: ::: mermaid ... :::
|
||||||
|
this.detectContainerBlocks(blocks);
|
||||||
|
|
||||||
this.logDebug(`检测到 ${blocks.length} 个 Mermaid 代码块`);
|
this.logDebug(`检测到 ${blocks.length} 个 Mermaid 代码块`);
|
||||||
return blocks;
|
return blocks;
|
||||||
},
|
},
|
||||||
@@ -4460,6 +4472,79 @@ void 0;
|
|||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检测 Markdown 容器语法的 Mermaid 代码块
|
||||||
|
* 格式: ::: mermaid ... :::
|
||||||
|
* @param {Array} blocks - 代码块数组
|
||||||
|
*/
|
||||||
|
detectContainerBlocks(blocks) {
|
||||||
|
// 查找所有包含 ::: mermaid 的文本节点或 pre/code 元素
|
||||||
|
const walker = document.createTreeWalker(
|
||||||
|
document.body,
|
||||||
|
NodeFilter.SHOW_ELEMENT,
|
||||||
|
{
|
||||||
|
acceptNode: function(node) {
|
||||||
|
// 检查 pre 或 code 元素
|
||||||
|
if (node.tagName === 'PRE' || node.tagName === 'CODE') {
|
||||||
|
const text = node.textContent;
|
||||||
|
if (text && text.trim().startsWith('::: mermaid')) {
|
||||||
|
return NodeFilter.FILTER_ACCEPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 检查 p 元素(可能被 Markdown 解析器包裹)
|
||||||
|
if (node.tagName === 'P') {
|
||||||
|
const text = node.textContent;
|
||||||
|
if (text && text.trim().startsWith('::: mermaid')) {
|
||||||
|
return NodeFilter.FILTER_ACCEPT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NodeFilter.FILTER_SKIP;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
while (walker.nextNode()) {
|
||||||
|
const element = walker.currentNode;
|
||||||
|
const container = this.extractContainerContent(element);
|
||||||
|
if (container && !blocks.includes(container)) {
|
||||||
|
blocks.push(container);
|
||||||
|
this.logDebug('检测到 Markdown 容器语法的 Mermaid 代码块');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 提取 Markdown 容器语法的内容
|
||||||
|
* @param {HTMLElement} element - 包含容器语法的元素
|
||||||
|
* @returns {HTMLElement|null} 包含代码的容器元素
|
||||||
|
*/
|
||||||
|
extractContainerContent(element) {
|
||||||
|
let text = element.textContent.trim();
|
||||||
|
|
||||||
|
// 移除开始标记 ::: mermaid(保留后面的换行符和空行)
|
||||||
|
text = text.replace(/^:::\s*mermaid\s*\n?/i, '');
|
||||||
|
|
||||||
|
// 移除结束标记 :::(保留前面的换行符和空行)
|
||||||
|
text = text.replace(/\n?:::\s*$/i, '');
|
||||||
|
|
||||||
|
// 不要 trim,保留代码中的空行
|
||||||
|
if (!text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建一个新的容器来存储代码
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.className = 'mermaid-container-block';
|
||||||
|
container.textContent = text;
|
||||||
|
container.dataset.containerBlock = 'true';
|
||||||
|
|
||||||
|
// 替换原始元素
|
||||||
|
element.parentNode.replaceChild(container, element);
|
||||||
|
|
||||||
|
return container;
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 提取代码块内容
|
* 提取代码块内容
|
||||||
* @param {HTMLElement} element - 代码块元素
|
* @param {HTMLElement} element - 代码块元素
|
||||||
@@ -4468,23 +4553,46 @@ void 0;
|
|||||||
extractMermaidCode(element) {
|
extractMermaidCode(element) {
|
||||||
let code = '';
|
let code = '';
|
||||||
|
|
||||||
|
// 处理 Markdown 容器语法格式
|
||||||
|
if (element.classList.contains('mermaid-container-block')) {
|
||||||
|
code = element.textContent;
|
||||||
|
this.logDebug('从 Markdown 容器语法提取代码');
|
||||||
|
}
|
||||||
// 根据不同的元素类型提取代码
|
// 根据不同的元素类型提取代码
|
||||||
if (element.tagName === 'DIV' && element.classList.contains('mermaid')) {
|
else if (element.tagName === 'DIV' && element.classList.contains('mermaid')) {
|
||||||
// 检查是否包含 WP-Markdown 生成的 script 标签
|
// 检查是否包含 WP-Markdown 生成的 script 标签
|
||||||
const scriptTag = element.querySelector('script');
|
const scriptTag = element.querySelector('script');
|
||||||
if (scriptTag) {
|
if (scriptTag) {
|
||||||
// 提取 document.write() 中的内容
|
// 提取 document.write() 中的内容
|
||||||
const scriptContent = scriptTag.textContent || scriptTag.innerText;
|
const scriptContent = scriptTag.textContent || scriptTag.innerText;
|
||||||
const match = scriptContent.match(/document\.write\s*\(\s*["'](.+?)["']\s*\)/);
|
this.logDebug('检测到 script 标签,原始内容: ' + scriptContent.substring(0, 100));
|
||||||
|
|
||||||
|
// 使用更精确的正则:匹配 document.write() 中的字符串内容
|
||||||
|
// 支持双引号和单引号,支持转义字符
|
||||||
|
// 使用贪婪匹配 [\s\S]* 来匹配包括换行在内的所有字符
|
||||||
|
let match = scriptContent.match(/document\.write\s*\(\s*["']([\s\S]*?)["']\s*\)/);
|
||||||
|
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
code = match[1];
|
code = match[1];
|
||||||
this.logDebug('检测到 WP-Markdown 格式,从 script 标签提取代码');
|
this.logDebug('从 document.write() 提取到代码,长度: ' + code.length);
|
||||||
} else {
|
} else {
|
||||||
// 如果没有匹配到,使用整个元素的文本内容(排除 script 标签)
|
// 如果没有匹配到 document.write(),尝试直接提取引号内的内容
|
||||||
code = element.textContent;
|
match = scriptContent.match(/["']([\s\S]*?)["']/);
|
||||||
|
if (match && match[1]) {
|
||||||
|
code = match[1];
|
||||||
|
this.logDebug('从引号内提取到代码,长度: ' + code.length);
|
||||||
|
} else {
|
||||||
|
// 最后的降级方案:获取除 script 标签外的文本内容
|
||||||
|
const clonedElement = element.cloneNode(true);
|
||||||
|
const scripts = clonedElement.querySelectorAll('script');
|
||||||
|
scripts.forEach(script => script.remove());
|
||||||
|
code = clonedElement.textContent;
|
||||||
|
this.logDebug('使用降级方案提取代码');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code = element.textContent;
|
code = element.textContent;
|
||||||
|
this.logDebug('从纯文本提取代码');
|
||||||
}
|
}
|
||||||
} else if (element.tagName === 'CODE') {
|
} else if (element.tagName === 'CODE') {
|
||||||
code = element.textContent;
|
code = element.textContent;
|
||||||
@@ -4493,13 +4601,24 @@ void 0;
|
|||||||
code = codeElement ? codeElement.textContent : element.textContent;
|
code = codeElement ? codeElement.textContent : element.textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解码转义字符
|
// 解码 HTML 实体(WordPress 可能会转义 HTML)
|
||||||
|
code = code
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
|
||||||
|
// 解码转义字符(必须在 HTML 实体解码之后)
|
||||||
code = code
|
code = code
|
||||||
.replace(/\\n/g, '\n')
|
.replace(/\\n/g, '\n')
|
||||||
|
.replace(/\\t/g, '\t')
|
||||||
|
.replace(/\\r/g, '\r')
|
||||||
.replace(/\\"/g, '"')
|
.replace(/\\"/g, '"')
|
||||||
.replace(/\\'/g, "'")
|
.replace(/\\'/g, "'")
|
||||||
.replace(/\\\\/g, '\\');
|
.replace(/\\\\/g, '\\');
|
||||||
|
|
||||||
|
this.logDebug('最终提取的代码: ' + code.substring(0, 100) + (code.length > 100 ? '...' : ''));
|
||||||
return code.trim();
|
return code.trim();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
338
docs/mermaid-usage-guide.md
Normal file
338
docs/mermaid-usage-guide.md
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
# Argon 主题 Mermaid 图表使用指南
|
||||||
|
|
||||||
|
## 推荐的标记方式
|
||||||
|
|
||||||
|
### Markdown 容器语法(推荐)⭐
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
flowchart TD
|
||||||
|
A[开始] --> B[处理]
|
||||||
|
B --> C[结束]
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
**优点**:
|
||||||
|
- ✅ 符合 Markdown 扩展规范(VuePress、Docusaurus 等使用相同语法)
|
||||||
|
- ✅ 不会被 WP-Markdown 当作代码块处理,避免嵌套问题
|
||||||
|
- ✅ 语法简洁,易于编写和阅读
|
||||||
|
- ✅ 支持所有 Mermaid 图表类型
|
||||||
|
- ✅ 在纯文本编辑器中也很清晰
|
||||||
|
- ✅ 易于迁移到其他平台
|
||||||
|
|
||||||
|
### 为什么使用容器语法?
|
||||||
|
|
||||||
|
**Markdown 容器语法** (`::: mermaid ... :::`) 是现代 Markdown 扩展的标准方式:
|
||||||
|
|
||||||
|
- **VuePress** 使用这种语法
|
||||||
|
- **Docusaurus** 使用这种语法
|
||||||
|
- **MkDocs** 使用类似语法
|
||||||
|
- **符合 CommonMark 扩展规范**
|
||||||
|
|
||||||
|
这种语法不会被 WP-Markdown 插件当作代码块处理,因此:
|
||||||
|
- 不会被套上代码高亮窗口
|
||||||
|
- 不会有嵌套结构问题
|
||||||
|
- 不会有字符转义问题
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 流程图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
flowchart LR
|
||||||
|
A[用户] --> B{登录?}
|
||||||
|
B -->|是| C[显示首页]
|
||||||
|
B -->|否| D[跳转登录页]
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 时序图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
Alice->>Bob: Hello Bob!
|
||||||
|
Bob-->>Alice: Hi Alice!
|
||||||
|
Alice->>Bob: How are you?
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 类图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
classDiagram
|
||||||
|
class Animal {
|
||||||
|
+String name
|
||||||
|
+int age
|
||||||
|
+makeSound()
|
||||||
|
}
|
||||||
|
class Dog {
|
||||||
|
+String breed
|
||||||
|
+bark()
|
||||||
|
}
|
||||||
|
Animal <|-- Dog
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 甘特图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
gantt
|
||||||
|
title 项目进度
|
||||||
|
dateFormat YYYY-MM-DD
|
||||||
|
section 设计
|
||||||
|
需求分析 :a1, 2024-01-01, 7d
|
||||||
|
UI设计 :a2, after a1, 5d
|
||||||
|
section 开发
|
||||||
|
前端开发 :b1, after a2, 10d
|
||||||
|
后端开发 :b2, after a2, 12d
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 状态图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
stateDiagram-v2
|
||||||
|
[*] --> 待审核
|
||||||
|
待审核 --> 已通过: 审核通过
|
||||||
|
待审核 --> 已拒绝: 审核拒绝
|
||||||
|
已通过 --> [*]
|
||||||
|
已拒绝 --> [*]
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 饼图
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
pie title 宠物分布
|
||||||
|
"狗" : 386
|
||||||
|
"猫" : 85
|
||||||
|
"兔子" : 15
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 常见问题
|
||||||
|
|
||||||
|
### 1. 如何在 WordPress 编辑器中使用?
|
||||||
|
|
||||||
|
**在经典编辑器中:**
|
||||||
|
1. 切换到"文本"模式(不是"可视化"模式)
|
||||||
|
2. 直接输入容器语法
|
||||||
|
3. 保存并预览
|
||||||
|
|
||||||
|
**在 Gutenberg 编辑器中:**
|
||||||
|
1. 添加"自定义 HTML"块或"代码"块
|
||||||
|
2. 输入容器语法
|
||||||
|
3. 保存并预览
|
||||||
|
|
||||||
|
### 2. 已有文章如何迁移?
|
||||||
|
|
||||||
|
如果你的文章使用了传统的 Markdown 代码块,可以批量替换:
|
||||||
|
|
||||||
|
**查找:**
|
||||||
|
```
|
||||||
|
三个反引号mermaid
|
||||||
|
```
|
||||||
|
|
||||||
|
**替换为:**
|
||||||
|
```
|
||||||
|
::: mermaid
|
||||||
|
```
|
||||||
|
|
||||||
|
**查找:**
|
||||||
|
```
|
||||||
|
三个反引号(代码块结束)
|
||||||
|
```
|
||||||
|
|
||||||
|
**替换为:**
|
||||||
|
```
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 容器语法不生效怎么办?
|
||||||
|
|
||||||
|
**可能的原因:**
|
||||||
|
- 其他插件或主题处理了容器语法
|
||||||
|
- WP-Markdown 插件版本过旧
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
1. 检查是否有其他 Markdown 插件冲突
|
||||||
|
2. 更新 WP-Markdown 插件到最新版本
|
||||||
|
3. 查看浏览器控制台的错误信息
|
||||||
|
|
||||||
|
### 4. 渲染失败怎么办?
|
||||||
|
|
||||||
|
**排查步骤:**
|
||||||
|
|
||||||
|
1. **检查语法**
|
||||||
|
- 访问 [Mermaid Live Editor](https://mermaid.live/) 验证语法
|
||||||
|
- 确保图表类型正确
|
||||||
|
|
||||||
|
2. **查看控制台**
|
||||||
|
- 按 F12 打开开发者工具
|
||||||
|
- 查看 Console 标签页
|
||||||
|
- 搜索 `[Argon Mermaid]` 日志
|
||||||
|
|
||||||
|
3. **检查主题设置**
|
||||||
|
- WordPress 后台 → 外观 → Argon 主题选项
|
||||||
|
- 找到"Mermaid 图表"分类
|
||||||
|
- 确认"启用 Mermaid 支持"已开启
|
||||||
|
|
||||||
|
4. **测试 CDN 连接**
|
||||||
|
- 访问测试页面验证 CDN 是否可用
|
||||||
|
- 如果 CDN 失败,尝试切换到其他 CDN
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
### 1. 使用容器语法
|
||||||
|
|
||||||
|
**推荐:**
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
flowchart TD
|
||||||
|
A --> B
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
**不推荐:**
|
||||||
|
```
|
||||||
|
三个反引号mermaid
|
||||||
|
flowchart TD
|
||||||
|
A --> B
|
||||||
|
三个反引号
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 避免特殊字符
|
||||||
|
|
||||||
|
如果图表中包含特殊字符,使用引号包裹:
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
::: mermaid
|
||||||
|
flowchart TD
|
||||||
|
A["包含 <特殊> 字符"] --> B["使用引号包裹"]
|
||||||
|
:::
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 测试复杂图表
|
||||||
|
|
||||||
|
对于复杂的图表:
|
||||||
|
1. 先在 [Mermaid Live Editor](https://mermaid.live/) 中测试
|
||||||
|
2. 确认语法正确后再粘贴到文章中
|
||||||
|
3. 发布前预览文章
|
||||||
|
|
||||||
|
### 4. 启用调试模式
|
||||||
|
|
||||||
|
如果遇到问题:
|
||||||
|
1. 主题设置 → Mermaid 图表 → 基本设置
|
||||||
|
2. 开启"调试模式"
|
||||||
|
3. 刷新页面查看控制台日志
|
||||||
|
|
||||||
|
### 5. 保持代码简洁
|
||||||
|
|
||||||
|
- 使用有意义的节点 ID
|
||||||
|
- 添加适当的注释
|
||||||
|
- 保持图表结构清晰
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 技术细节
|
||||||
|
|
||||||
|
### 支持的标记格式
|
||||||
|
|
||||||
|
Argon 主题支持以下格式(按优先级排序):
|
||||||
|
|
||||||
|
1. `::: mermaid ... :::` - Markdown 容器语法 ⭐(推荐)
|
||||||
|
2. `<div class="mermaid">` - 标准格式(WPMD 生成)
|
||||||
|
3. `<pre><code class="language-mermaid">` - Markdown 格式
|
||||||
|
4. `<pre data-lang="mermaid">` - 自定义属性格式
|
||||||
|
5. `<code class="mermaid">` - 简化格式
|
||||||
|
|
||||||
|
### 代码提取逻辑
|
||||||
|
|
||||||
|
1. **检测代码块**
|
||||||
|
- CSS 选择器查找标准格式
|
||||||
|
- TreeWalker 查找容器语法
|
||||||
|
|
||||||
|
2. **提取代码**
|
||||||
|
- 容器语法:移除 `::: mermaid` 和 `:::`
|
||||||
|
- WPMD 格式:正则提取 `document.write()` 内容
|
||||||
|
- 标准格式:直接提取文本内容
|
||||||
|
|
||||||
|
3. **解码处理**
|
||||||
|
- 先解码 HTML 实体(`<` → `<`)
|
||||||
|
- 再解码转义字符(`\n` → 换行符)
|
||||||
|
|
||||||
|
4. **渲染图表**
|
||||||
|
- 使用 Mermaid.js 库渲染为 SVG
|
||||||
|
- 应用主题样式(夜间模式适配)
|
||||||
|
- 错误时显示友好提示
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 问题:容器语法被显示为普通文本
|
||||||
|
|
||||||
|
**症状**:`::: mermaid` 被显示在页面上
|
||||||
|
|
||||||
|
**原因**:可能被其他插件或主题处理为普通文本
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
- 检查是否有其他 Markdown 插件冲突
|
||||||
|
- 确认 Argon 主题已更新到最新版本
|
||||||
|
- 查看浏览器控制台是否有 JavaScript 错误
|
||||||
|
|
||||||
|
### 问题:只显示第一个单词
|
||||||
|
|
||||||
|
**症状**:图表渲染失败,错误信息显示 `"text": "flowchart"`
|
||||||
|
|
||||||
|
**原因**:代码提取不完整
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
- 确保使用最新版本的 Argon 主题
|
||||||
|
- 使用容器语法而不是传统代码块
|
||||||
|
- 查看控制台日志确认提取到的完整代码
|
||||||
|
|
||||||
|
### 问题:HTML 实体未解码
|
||||||
|
|
||||||
|
**症状**:图表中显示 `<` 而不是 `<`
|
||||||
|
|
||||||
|
**原因**:HTML 实体解码失败
|
||||||
|
|
||||||
|
**解决**:
|
||||||
|
- Argon 主题会自动解码 HTML 实体
|
||||||
|
- 使用容器语法可避免此问题
|
||||||
|
- 在 Mermaid 代码中使用引号包裹特殊字符
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 相关资源
|
||||||
|
|
||||||
|
- [Mermaid 官方文档](https://mermaid.js.org/)
|
||||||
|
- [Mermaid Live Editor](https://mermaid.live/)
|
||||||
|
- [VuePress 容器语法](https://vuepress.vuejs.org/guide/markdown.html#custom-containers)
|
||||||
|
- [CommonMark 规范](https://commonmark.org/)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 更新日志
|
||||||
|
|
||||||
|
### 2026-01-24
|
||||||
|
- ✅ 添加 Markdown 容器语法支持(`::: mermaid ... :::`)
|
||||||
|
- ✅ 修复 WP-Markdown 格式的代码提取问题
|
||||||
|
- ✅ 改进正则表达式,支持多行代码
|
||||||
|
- ✅ 添加降级方案和详细日志
|
||||||
|
- ✅ 简化标记方式,只保留容器语法作为推荐方式
|
||||||
|
- ✅ 修复代码高亮干扰 mermaid 渲染的问题(排除 mermaid 代码块)
|
||||||
|
- ✅ 修复容器语法中空行导致内容被截断的问题
|
||||||
276
tests/test-mermaid-fixes.html
Normal file
276
tests/test-mermaid-fixes.html
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
<!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: Arial, sans-serif;
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
.test-section {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
.test-section h2 {
|
||||||
|
color: #5e72e4;
|
||||||
|
border-bottom: 2px solid #5e72e4;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
.test-case {
|
||||||
|
margin: 15px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-left: 4px solid #5e72e4;
|
||||||
|
}
|
||||||
|
.test-case h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.expected {
|
||||||
|
color: #28a745;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.code-block {
|
||||||
|
background: #2d2d2d;
|
||||||
|
color: #d4d4d4;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 4px;
|
||||||
|
overflow-x: auto;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
.mermaid {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
pre code.language-mermaid {
|
||||||
|
display: block;
|
||||||
|
background: #f8f9fa;
|
||||||
|
padding: 15px;
|
||||||
|
border: 2px dashed #5e72e4;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>🧪 Mermaid 修复测试页面</h1>
|
||||||
|
<p>本页面用于测试两个关键修复:</p>
|
||||||
|
<ol>
|
||||||
|
<li><strong>代码高亮排除 mermaid</strong>:mermaid 代码块不应被代码高亮处理</li>
|
||||||
|
<li><strong>容器语法处理空行</strong>:容器语法中的空行应被正确保留</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<!-- 测试 1: 代码高亮排除 -->
|
||||||
|
<div class="test-section">
|
||||||
|
<h2>测试 1: 代码高亮排除 Mermaid</h2>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 1.1: 标准 Markdown 格式(应该被排除)</h3>
|
||||||
|
<p class="expected">✅ 预期:不应出现代码高亮窗口,直接渲染为 Mermaid 图表</p>
|
||||||
|
<pre><code class="language-mermaid">
|
||||||
|
flowchart TD
|
||||||
|
A[开始] --> B[处理]
|
||||||
|
B --> C[结束]
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 1.2: 标准 div.mermaid 格式(应该被排除)</h3>
|
||||||
|
<p class="expected">✅ 预期:不应出现代码高亮窗口,直接渲染为 Mermaid 图表</p>
|
||||||
|
<div class="mermaid">
|
||||||
|
flowchart LR
|
||||||
|
A[用户] --> B{登录?}
|
||||||
|
B -->|是| C[显示首页]
|
||||||
|
B -->|否| D[跳转登录页]
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 1.3: 普通代码块(应该被高亮)</h3>
|
||||||
|
<p class="expected">✅ 预期:应该出现代码高亮窗口</p>
|
||||||
|
<pre><code class="language-javascript">
|
||||||
|
function hello() {
|
||||||
|
console.log('Hello World');
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 测试 2: 容器语法空行处理 -->
|
||||||
|
<div class="test-section">
|
||||||
|
<h2>测试 2: 容器语法空行处理</h2>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 2.1: 包含空行的流程图</h3>
|
||||||
|
<p class="expected">✅ 预期:空行应被保留,图表正常渲染</p>
|
||||||
|
<div class="code-block">
|
||||||
|
::: mermaid
|
||||||
|
flowchart TD
|
||||||
|
A[开始]
|
||||||
|
|
||||||
|
B[处理步骤1]
|
||||||
|
|
||||||
|
C[处理步骤2]
|
||||||
|
|
||||||
|
D[结束]
|
||||||
|
|
||||||
|
A --> B
|
||||||
|
B --> C
|
||||||
|
C --> D
|
||||||
|
:::
|
||||||
|
</div>
|
||||||
|
<p>实际渲染:</p>
|
||||||
|
<p>
|
||||||
|
::: mermaid
|
||||||
|
flowchart TD
|
||||||
|
A[开始]
|
||||||
|
|
||||||
|
B[处理步骤1]
|
||||||
|
|
||||||
|
C[处理步骤2]
|
||||||
|
|
||||||
|
D[结束]
|
||||||
|
|
||||||
|
A --> B
|
||||||
|
B --> C
|
||||||
|
C --> D
|
||||||
|
:::
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 2.2: 包含空行的时序图</h3>
|
||||||
|
<p class="expected">✅ 预期:空行应被保留,图表正常渲染</p>
|
||||||
|
<div class="code-block">
|
||||||
|
::: mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant A as Alice
|
||||||
|
participant B as Bob
|
||||||
|
|
||||||
|
A->>B: Hello Bob!
|
||||||
|
|
||||||
|
Note over A,B: 这是一个注释
|
||||||
|
|
||||||
|
B-->>A: Hi Alice!
|
||||||
|
:::
|
||||||
|
</div>
|
||||||
|
<p>实际渲染:</p>
|
||||||
|
<p>
|
||||||
|
::: mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
participant A as Alice
|
||||||
|
participant B as Bob
|
||||||
|
|
||||||
|
A->>B: Hello Bob!
|
||||||
|
|
||||||
|
Note over A,B: 这是一个注释
|
||||||
|
|
||||||
|
B-->>A: Hi Alice!
|
||||||
|
:::
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 2.3: 包含多个连续空行</h3>
|
||||||
|
<p class="expected">✅ 预期:多个空行应被保留,图表正常渲染</p>
|
||||||
|
<div class="code-block">
|
||||||
|
::: mermaid
|
||||||
|
flowchart LR
|
||||||
|
A[步骤A]
|
||||||
|
|
||||||
|
|
||||||
|
B[步骤B]
|
||||||
|
|
||||||
|
|
||||||
|
C[步骤C]
|
||||||
|
|
||||||
|
A --> B --> C
|
||||||
|
:::
|
||||||
|
</div>
|
||||||
|
<p>实际渲染:</p>
|
||||||
|
<p>
|
||||||
|
::: mermaid
|
||||||
|
flowchart LR
|
||||||
|
A[步骤A]
|
||||||
|
|
||||||
|
|
||||||
|
B[步骤B]
|
||||||
|
|
||||||
|
|
||||||
|
C[步骤C]
|
||||||
|
|
||||||
|
A --> B --> C
|
||||||
|
:::
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 测试 3: WP-Markdown 格式 -->
|
||||||
|
<div class="test-section">
|
||||||
|
<h2>测试 3: WP-Markdown 格式兼容性</h2>
|
||||||
|
|
||||||
|
<div class="test-case">
|
||||||
|
<h3>测试 3.1: document.write 格式</h3>
|
||||||
|
<p class="expected">✅ 预期:正确提取代码并渲染</p>
|
||||||
|
<div class="mermaid">
|
||||||
|
<script>document.write("flowchart TD\n A[开始] --> B[结束]")</script>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 测试结果说明 -->
|
||||||
|
<div class="test-section">
|
||||||
|
<h2>📋 测试检查清单</h2>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check1">
|
||||||
|
<label for="check1">测试 1.1: Markdown 格式的 mermaid 代码块没有代码高亮窗口</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check2">
|
||||||
|
<label for="check2">测试 1.2: div.mermaid 格式没有代码高亮窗口</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check3">
|
||||||
|
<label for="check3">测试 1.3: 普通 JavaScript 代码有代码高亮窗口</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check4">
|
||||||
|
<label for="check4">测试 2.1: 包含空行的流程图正常渲染</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check5">
|
||||||
|
<label for="check5">测试 2.2: 包含空行的时序图正常渲染</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check6">
|
||||||
|
<label for="check6">测试 2.3: 包含多个连续空行的图表正常渲染</label>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<input type="checkbox" id="check7">
|
||||||
|
<label for="check7">测试 3.1: WP-Markdown 格式正常渲染</label>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// 简单的日志输出
|
||||||
|
console.log('[Mermaid Test] 测试页面已加载');
|
||||||
|
console.log('[Mermaid Test] 请检查:');
|
||||||
|
console.log('[Mermaid Test] 1. mermaid 代码块是否被代码高亮处理');
|
||||||
|
console.log('[Mermaid Test] 2. 容器语法中的空行是否被正确保留');
|
||||||
|
console.log('[Mermaid Test] 3. 所有图表是否正常渲染');
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -3,183 +3,102 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>WP-Markdown 格式测试 - Mermaid 支持</title>
|
<title>WP-Markdown Mermaid 格式测试</title>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
max-width: 1200px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
background: #f5f5f5;
|
background: #f5f5f5;
|
||||||
}
|
}
|
||||||
.test-section {
|
.test-case {
|
||||||
background: white;
|
background: white;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
|
||||||
}
|
}
|
||||||
.test-title {
|
h2 {
|
||||||
font-size: 18px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
color: #333;
|
color: #333;
|
||||||
|
border-bottom: 2px solid #007bff;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
.test-description {
|
.mermaid {
|
||||||
color: #666;
|
background: #f9f9f9;
|
||||||
margin-bottom: 15px;
|
padding: 15px;
|
||||||
font-size: 14px;
|
border: 1px solid #ddd;
|
||||||
}
|
|
||||||
.mermaid-container {
|
|
||||||
background: #fafafa;
|
|
||||||
border: 1px solid #e0e0e0;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 20px;
|
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
.test-result {
|
pre {
|
||||||
margin-top: 15px;
|
background: #f4f4f4;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
font-size: 14px;
|
overflow-x: auto;
|
||||||
}
|
|
||||||
.test-result.success {
|
|
||||||
background: #d4edda;
|
|
||||||
color: #155724;
|
|
||||||
border: 1px solid #c3e6cb;
|
|
||||||
}
|
|
||||||
.test-result.error {
|
|
||||||
background: #f8d7da;
|
|
||||||
color: #721c24;
|
|
||||||
border: 1px solid #f5c6cb;
|
|
||||||
}
|
|
||||||
.code-preview {
|
|
||||||
background: #f8f9fa;
|
|
||||||
border: 1px solid #dee2e6;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 10px;
|
|
||||||
margin: 10px 0;
|
|
||||||
font-family: 'Courier New', monospace;
|
|
||||||
font-size: 12px;
|
|
||||||
white-space: pre-wrap;
|
|
||||||
word-break: break-all;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>WP-Markdown 格式测试</h1>
|
<h1>WP-Markdown Mermaid 格式测试</h1>
|
||||||
<p>测试 Mermaid 对 WP-Markdown 编辑器生成的特殊格式的支持</p>
|
<p>本页面测试 WP-Markdown 插件生成的各种 Mermaid 代码块格式</p>
|
||||||
|
|
||||||
<!-- 测试 1: 标准 WP-Markdown 格式 -->
|
<!-- 测试用例 1: 标准 document.write 格式(单行) -->
|
||||||
<div class="test-section">
|
<div class="test-case">
|
||||||
<div class="test-title">测试 1: 标准 WP-Markdown 格式(带 script 标签)</div>
|
<h2>测试 1: 标准 document.write 格式(单行)</h2>
|
||||||
<div class="test-description">
|
|
||||||
WP-Markdown 生成的格式包含 <script>document.write()</script> 标签
|
|
||||||
</div>
|
|
||||||
<div class="mermaid">
|
<div class="mermaid">
|
||||||
<script>document.write("flowchart TD\n Start([开始]) --> Process[处理]\n Process --> End([结束])")</script>
|
<script>document.write("flowchart TD\nA[开始] --> B[处理]\nB --> C[结束]")</script>
|
||||||
flowchart TD Start([开始]) --> Process[处理] Process --> End([结束])
|
|
||||||
</div>
|
</div>
|
||||||
<div class="test-result" id="result-1">等待渲染...</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 测试 2: 带转义字符的 WP-Markdown 格式 -->
|
<!-- 测试用例 2: document.write 格式(多行,带转义) -->
|
||||||
<div class="test-section">
|
<div class="test-case">
|
||||||
<div class="test-title">测试 2: 带转义字符的复杂格式</div>
|
<h2>测试 2: document.write 格式(多行,带转义)</h2>
|
||||||
<div class="test-description">
|
|
||||||
测试转义字符的正确解码:\n(换行)、\"(引号)、\'(单引号)
|
|
||||||
</div>
|
|
||||||
<div class="mermaid">
|
<div class="mermaid">
|
||||||
<script>document.write("sequenceDiagram\n participant A as \"用户\"\n participant B as '服务器'\n A->>B: 发送请求\n B->>A: 返回响应")</script>
|
<script>document.write("graph LR\n A[\"用户输入\"] --> B[\"数据验证\"]\n B --> C{\"是否有效?\"}\n C -->|是| D[\"保存数据\"]\n C -->|否| E[\"显示错误\"]")</script>
|
||||||
sequenceDiagram participant A as "用户" participant B as '服务器' A->>B: 发送请求 B->>A: 返回响应
|
|
||||||
</div>
|
</div>
|
||||||
<div class="test-result" id="result-2">等待渲染...</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 测试 3: 标准格式(无 script 标签) -->
|
<!-- 测试用例 3: document.write 格式(包含 HTML 实体) -->
|
||||||
<div class="test-section">
|
<div class="test-case">
|
||||||
<div class="test-title">测试 3: 标准格式(无 script 标签)</div>
|
<h2>测试 3: document.write 格式(包含 HTML 实体)</h2>
|
||||||
<div class="test-description">
|
|
||||||
确保标准格式仍然正常工作
|
|
||||||
</div>
|
|
||||||
<div class="mermaid">
|
<div class="mermaid">
|
||||||
flowchart LR
|
<script>document.write("sequenceDiagram\n Alice->>Bob: Hello Bob!\n Bob-->>Alice: Hi Alice!")</script>
|
||||||
A[开始] --> B{判断}
|
|
||||||
B -->|是| C[处理A]
|
|
||||||
B -->|否| D[处理B]
|
|
||||||
C --> E[结束]
|
|
||||||
D --> E
|
|
||||||
</div>
|
</div>
|
||||||
<div class="test-result" id="result-3">等待渲染...</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 测试 4: 复杂的 WP-Markdown 格式 -->
|
<!-- 测试用例 4: 纯文本格式(无 script 标签) -->
|
||||||
<div class="test-section">
|
<div class="test-case">
|
||||||
<div class="test-title">测试 4: 复杂流程图(WP-Markdown 格式)</div>
|
<h2>测试 4: 纯文本格式(无 script 标签)</h2>
|
||||||
<div class="test-description">
|
|
||||||
测试包含多种节点类型和连接的复杂流程图
|
|
||||||
</div>
|
|
||||||
<div class="mermaid">
|
<div class="mermaid">
|
||||||
<script>document.write("flowchart TD\n Start([用户提交评论]) --> PreProcess[preprocess_comment 钩子]\n PreProcess --> CheckEnabled{启用 AI 检测?}\n CheckEnabled -->|否| SaveComment[保存评论]\n CheckEnabled -->|是| CheckMode{检测模式}\n CheckMode -->|实时检测| RealTime[实时 AI 检测]\n CheckMode -->|批量扫描| BatchScan[批量扫描]\n RealTime --> IsSpam{是否垃圾?}\n IsSpam -->|是| MarkSpam[标记为垃圾]\n IsSpam -->|否| SaveComment\n BatchScan --> SaveComment")</script>
|
flowchart TD
|
||||||
flowchart TD Start([用户提交评论]) --> PreProcess[preprocess_comment 钩子] PreProcess --> CheckEnabled{启用 AI 检测?} CheckEnabled -->|否| SaveComment[保存评论] CheckEnabled -->|是| CheckMode{检测模式} CheckMode -->|实时检测| RealTime[实时 AI 检测] CheckMode -->|批量扫描| BatchScan[批量扫描] RealTime --> IsSpam{是否垃圾?} IsSpam -->|是| MarkSpam[标记为垃圾] IsSpam -->|否| SaveComment BatchScan --> SaveComment
|
Start --> Stop
|
||||||
</div>
|
</div>
|
||||||
<div class="test-result" id="result-4">等待渲染...</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 测试 5: 注释中的代码块(应该被忽略) -->
|
<!-- 测试用例 5: pre code 格式 -->
|
||||||
<div class="test-section">
|
<div class="test-case">
|
||||||
<div class="test-title">测试 5: 注释中的代码块(应该被忽略)</div>
|
<h2>测试 5: pre code 格式</h2>
|
||||||
<div class="test-description">
|
<pre><code class="language-mermaid">graph TD
|
||||||
被 HTML 注释包裹的 Mermaid 代码块应该被忽略
|
A --> B
|
||||||
|
B --> C</code></pre>
|
||||||
</div>
|
</div>
|
||||||
<!--
|
|
||||||
|
<!-- 测试用例 6: 复杂图表(类图) -->
|
||||||
|
<div class="test-case">
|
||||||
|
<h2>测试 6: 复杂图表(类图)</h2>
|
||||||
<div class="mermaid">
|
<div class="mermaid">
|
||||||
<script>document.write("flowchart TD\n A --> B")</script>
|
<script>document.write("classDiagram\n class Animal {\n +String name\n +int age\n +makeSound()\n }\n class Dog {\n +String breed\n +bark()\n }\n Animal <|-- Dog")</script>
|
||||||
</div>
|
|
||||||
-->
|
|
||||||
<div class="test-result" id="result-5">
|
|
||||||
如果没有渲染任何图表,说明注释过滤功能正常工作 ✓
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 加载 Mermaid 库 -->
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js"></script>
|
||||||
|
|
||||||
<!-- 模拟 Argon 主题的 Mermaid 模块 -->
|
|
||||||
<script>
|
<script>
|
||||||
// 简化版的 Mermaid 模块(用于测试)
|
// 模拟 Argon 主题的 Mermaid 初始化逻辑
|
||||||
const ArgonMermaid = {
|
console.log('[测试] 开始初始化 Mermaid');
|
||||||
config: {
|
|
||||||
theme: 'default'
|
|
||||||
},
|
|
||||||
initialized: false,
|
|
||||||
|
|
||||||
init() {
|
// 检测所有 Mermaid 代码块
|
||||||
if (typeof window.mermaid === 'undefined') {
|
function detectMermaidBlocks() {
|
||||||
console.error('Mermaid 库未加载');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化 Mermaid
|
|
||||||
window.mermaid.initialize({
|
|
||||||
startOnLoad: false,
|
|
||||||
theme: this.getMermaidTheme(),
|
|
||||||
securityLevel: 'loose',
|
|
||||||
logLevel: 'error'
|
|
||||||
});
|
|
||||||
|
|
||||||
this.initialized = true;
|
|
||||||
console.log('Mermaid 初始化完成');
|
|
||||||
|
|
||||||
// 渲染所有图表
|
|
||||||
this.renderAllCharts();
|
|
||||||
},
|
|
||||||
|
|
||||||
getMermaidTheme() {
|
|
||||||
return this.config.theme;
|
|
||||||
},
|
|
||||||
|
|
||||||
detectMermaidBlocks() {
|
|
||||||
const blocks = [];
|
const blocks = [];
|
||||||
const selectors = [
|
const selectors = [
|
||||||
'div.mermaid',
|
'div.mermaid',
|
||||||
@@ -192,45 +111,39 @@ flowchart LR
|
|||||||
const elements = document.querySelectorAll(selector);
|
const elements = document.querySelectorAll(selector);
|
||||||
elements.forEach(element => {
|
elements.forEach(element => {
|
||||||
if (!blocks.includes(element)) {
|
if (!blocks.includes(element)) {
|
||||||
if (!this.isInComment(element)) {
|
|
||||||
blocks.push(element);
|
blocks.push(element);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`检测到 ${blocks.length} 个 Mermaid 代码块`);
|
console.log(`[测试] 检测到 ${blocks.length} 个 Mermaid 代码块`);
|
||||||
return blocks;
|
return blocks;
|
||||||
},
|
|
||||||
|
|
||||||
isInComment(element) {
|
|
||||||
let node = element.parentNode;
|
|
||||||
while (node) {
|
|
||||||
if (node.nodeType === Node.COMMENT_NODE) {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
node = node.parentNode;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
},
|
|
||||||
|
|
||||||
extractMermaidCode(element) {
|
// 提取代码块内容
|
||||||
|
function extractMermaidCode(element) {
|
||||||
let code = '';
|
let code = '';
|
||||||
|
|
||||||
// 根据不同的元素类型提取代码
|
|
||||||
if (element.tagName === 'DIV' && element.classList.contains('mermaid')) {
|
if (element.tagName === 'DIV' && element.classList.contains('mermaid')) {
|
||||||
// 检查是否包含 WP-Markdown 生成的 script 标签
|
|
||||||
const scriptTag = element.querySelector('script');
|
const scriptTag = element.querySelector('script');
|
||||||
if (scriptTag) {
|
if (scriptTag) {
|
||||||
// 提取 document.write() 中的内容
|
|
||||||
const scriptContent = scriptTag.textContent || scriptTag.innerText;
|
const scriptContent = scriptTag.textContent || scriptTag.innerText;
|
||||||
const match = scriptContent.match(/document\.write\s*\(\s*["'](.+?)["']\s*\)/);
|
console.log('[测试] 原始 script 内容:', scriptContent);
|
||||||
|
|
||||||
|
// 匹配 document.write("...") 或 document.write('...')
|
||||||
|
let match = scriptContent.match(/document\.write\s*\(\s*"((?:[^"\\]|\\.)*)"\s*\)/s);
|
||||||
|
if (!match) {
|
||||||
|
match = scriptContent.match(/document\.write\s*\(\s*'((?:[^'\\]|\\.)*)'\s*\)/s);
|
||||||
|
}
|
||||||
|
|
||||||
if (match && match[1]) {
|
if (match && match[1]) {
|
||||||
code = match[1];
|
code = match[1];
|
||||||
console.log('检测到 WP-Markdown 格式,从 script 标签提取代码');
|
console.log('[测试] 提取到的代码(转义前):', code);
|
||||||
} else {
|
} else {
|
||||||
// 如果没有匹配到,使用整个元素的文本内容(排除 script 标签)
|
const clonedElement = element.cloneNode(true);
|
||||||
code = element.textContent;
|
const scripts = clonedElement.querySelectorAll('script');
|
||||||
|
scripts.forEach(script => script.remove());
|
||||||
|
code = clonedElement.textContent;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code = element.textContent;
|
code = element.textContent;
|
||||||
@@ -242,91 +155,53 @@ flowchart LR
|
|||||||
code = codeElement ? codeElement.textContent : element.textContent;
|
code = codeElement ? codeElement.textContent : element.textContent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 解码 HTML 实体
|
||||||
|
code = code
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, "'");
|
||||||
|
|
||||||
// 解码转义字符
|
// 解码转义字符
|
||||||
code = code
|
code = code
|
||||||
.replace(/\\n/g, '\n')
|
.replace(/\\n/g, '\n')
|
||||||
|
.replace(/\\t/g, '\t')
|
||||||
|
.replace(/\\r/g, '\r')
|
||||||
.replace(/\\"/g, '"')
|
.replace(/\\"/g, '"')
|
||||||
.replace(/\\'/g, "'")
|
.replace(/\\'/g, "'")
|
||||||
.replace(/\\\\/g, '\\');
|
.replace(/\\\\/g, '\\');
|
||||||
|
|
||||||
|
console.log('[测试] 最终提取的代码:', code);
|
||||||
return code.trim();
|
return code.trim();
|
||||||
},
|
|
||||||
|
|
||||||
renderAllCharts() {
|
|
||||||
if (!this.initialized) {
|
|
||||||
console.log('Mermaid 未初始化,跳过渲染');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const blocks = this.detectMermaidBlocks();
|
// 初始化并渲染
|
||||||
|
|
||||||
if (blocks.length === 0) {
|
|
||||||
console.log('未找到 Mermaid 代码块');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks.forEach((block, index) => {
|
|
||||||
this.renderChart(block, index);
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`完成渲染 ${blocks.length} 个图表`);
|
|
||||||
},
|
|
||||||
|
|
||||||
renderChart(element, index) {
|
|
||||||
const chartId = `mermaid-chart-${Date.now()}-${index}`;
|
|
||||||
const testNumber = index + 1;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const code = this.extractMermaidCode(element);
|
|
||||||
|
|
||||||
if (!code) {
|
|
||||||
console.log(`代码块为空,跳过: ${chartId}`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`提取的代码 (测试 ${testNumber}):`, code);
|
|
||||||
|
|
||||||
const container = document.createElement('div');
|
|
||||||
container.className = 'mermaid-container';
|
|
||||||
container.id = chartId;
|
|
||||||
|
|
||||||
window.mermaid.render(`mermaid-svg-${chartId}`, code).then(result => {
|
|
||||||
container.innerHTML = result.svg;
|
|
||||||
element.parentNode.replaceChild(container, element);
|
|
||||||
|
|
||||||
// 更新测试结果
|
|
||||||
const resultDiv = document.getElementById(`result-${testNumber}`);
|
|
||||||
if (resultDiv) {
|
|
||||||
resultDiv.className = 'test-result success';
|
|
||||||
resultDiv.textContent = '✓ 渲染成功';
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`图表渲染成功: ${chartId}`);
|
|
||||||
}).catch(error => {
|
|
||||||
console.error(`图表渲染失败: ${chartId}`, error);
|
|
||||||
|
|
||||||
const resultDiv = document.getElementById(`result-${testNumber}`);
|
|
||||||
if (resultDiv) {
|
|
||||||
resultDiv.className = 'test-result error';
|
|
||||||
resultDiv.innerHTML = `✗ 渲染失败: ${error.message}<br><div class="code-preview">${code}</div>`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (error) {
|
|
||||||
console.error(`处理图表失败: ${chartId}`, error);
|
|
||||||
|
|
||||||
const resultDiv = document.getElementById(`result-${testNumber}`);
|
|
||||||
if (resultDiv) {
|
|
||||||
resultDiv.className = 'test-result error';
|
|
||||||
resultDiv.textContent = `✗ 处理失败: ${error.message}`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// 页面加载完成后初始化
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
console.log('页面加载完成,初始化 Mermaid');
|
mermaid.initialize({
|
||||||
ArgonMermaid.init();
|
startOnLoad: false,
|
||||||
|
theme: 'default',
|
||||||
|
securityLevel: 'loose'
|
||||||
|
});
|
||||||
|
|
||||||
|
const blocks = detectMermaidBlocks();
|
||||||
|
blocks.forEach((block, index) => {
|
||||||
|
const code = extractMermaidCode(block);
|
||||||
|
const chartId = `mermaid-chart-${index}`;
|
||||||
|
|
||||||
|
console.log(`[测试] 渲染图表 ${index}:`, code);
|
||||||
|
|
||||||
|
mermaid.render(chartId, code).then(result => {
|
||||||
|
const container = document.createElement('div');
|
||||||
|
container.innerHTML = result.svg;
|
||||||
|
block.parentNode.replaceChild(container, block);
|
||||||
|
console.log(`[测试] 图表 ${index} 渲染成功`);
|
||||||
|
}).catch(error => {
|
||||||
|
console.error(`[测试] 图表 ${index} 渲染失败:`, error);
|
||||||
|
block.style.border = '2px solid red';
|
||||||
|
block.innerHTML = `<strong style="color: red;">渲染失败: ${error.message}</strong><br><pre>${code}</pre>`;
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user