From b4ba37a6c5affe172b8cbf0e8dcb11259869a886 Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Sat, 24 Jan 2026 20:49:32 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20Mermaid=20=E5=AE=B9?= =?UTF-8?q?=E5=99=A8=E8=AF=AD=E6=B3=95=E6=8D=A2=E8=A1=8C=E7=AC=A6=E4=B8=A2?= =?UTF-8?q?=E5=A4=B1=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题描述 用户提供的 AI 评论审核流程 Mermaid 图表渲染失败,错误信息显示: - `flowchart TDStart` - `TD` 和 `Start` 之间缺少换行符 - 箭头符号被转换成全角 `–>` 而不是 `-->` ## 根本原因 WP-Markdown 插件将容器语法 `::: mermaid ... :::` 转换为 HTML 时: 1. 每一行代码都被包裹在 `
` 标签中
2. 行内的换行使用 `
` 标签表示
3. 使用 `textContent` 或 `innerText` 提取时,`
` 标签被忽略或转换为空格
4. 导致多行代码被合并成一行,Mermaid 语法解析失败
## 修复方案
### 1. 新增 `htmlToText()` 辅助函数
```javascript
htmlToText(html) {
// 将
和
转换为换行符
let text = html.replace(/
/gi, '\n');
// 移除其他 HTML 标签
text = text.replace(/<[^>]+>/g, '');
// 解码 HTML 实体
text = text
.replace(/ /g, ' ')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/&/g, '&')
.replace(/"/g, '"')
.replace(/'/g, "'");
return text;
}
```
### 2. 改进 `extractContainerContent()` 函数
- 使用 `innerHTML` 而不是 `textContent` 或 `innerText`
- 调用 `htmlToText()` 将 `
` 标签转换为换行符
- 保留所有换行符和空行
- 添加详细的调试日志
### 3. 处理流程
```
1. 检测到 ::: mermaid 开始标记
2. 提取 innerHTML(包含
标签)
3. 使用 htmlToText() 转换:
-
→ \n
- 移除其他 HTML 标签
- 解码 HTML 实体
4. 收集所有行内容
5. 使用 \n 连接所有行
6. 创建容器元素存储完整代码
```
## 测试验证
### 测试用例 1:简单流程图
```markdown
::: mermaid
flowchart TD
A[开始] --> B[处理]
B --> C[结束]
:::
```
### 测试用例 2:复杂流程图(AI 评论审核)
- 包含 100+ 个节点
- 包含多行文本(`
` 标签)
- 包含箭头符号(`-->`, `-->`)
- 包含样式定义(`style` 语句)
### 预期结果
- ✅ 所有换行符正确保留
- ✅ 箭头符号不被转换
- ✅ 多行文本正确显示
- ✅ 样式定义正确应用
## 影响范围
- 仅影响 Markdown 容器语法(`::: mermaid ... :::`)
- 不影响其他格式(`
` 等)
- 向后兼容,不影响现有功能
## 相关文件
- `argontheme.js` - 修改 `extractContainerContent()` 和新增 `htmlToText()`
- `tests/test-ai-comment-flow.md` - 测试文档
- `docs/mermaid-usage-guide.md` - 使用指南
## 技术细节
### HTML 结构示例
WP-Markdown 生成的 HTML:
```html
::: mermaid
flowchart TD
Start([用户提交评论]) --> PreProcess[预处理]
:::
```
### 提取过程
1. **原始 HTML**: `::: mermaid
flowchart TD
Start --> End
:::`
2. **htmlToText()**: `::: mermaid\nflowchart TD\nStart --> End\n:::`
3. **移除标记**: `flowchart TD\nStart --> End`
4. **最终代码**:
```
flowchart TD
Start --> End
```
## 注意事项
1. **性能影响**:使用 `innerHTML` 和正则替换,性能影响可忽略
2. **安全性**:只处理 Mermaid 代码块,不执行任何脚本
3. **兼容性**:支持所有现代浏览器
4. **调试**:添加详细日志,便于排查问题
## 后续优化
1. 考虑支持更多 Markdown 容器语法(如 `::: warning`, `::: tip` 等)
2. 优化正则表达式性能
3. 添加单元测试
---
argontheme.js | 50 +++++++++--
commit-msg-mermaid-newline-fix.txt | 129 +++++++++++++++++++++++++++++
2 files changed, 173 insertions(+), 6 deletions(-)
create mode 100644 commit-msg-mermaid-newline-fix.txt
diff --git a/argontheme.js b/argontheme.js
index 03e0176..c6bcea8 100644
--- a/argontheme.js
+++ b/argontheme.js
@@ -4520,20 +4520,31 @@ void 0;
processedElements.add(startElement);
// 处理开始元素
+ // 使用 innerHTML 来获取原始内容,包括
标签
+ let startHTML = startElement.innerHTML;
let startText = startElement.textContent.trim();
+
if (startText.startsWith('::: mermaid')) {
foundStart = true;
+ this.logDebug('找到容器语法开始标记,原始 HTML: ' + startHTML.substring(0, 100));
+
// 移除开始标记,保留同一元素中的其他内容
startText = startText.replace(/^:::\s*mermaid\s*/i, '').trim();
if (startText && !startText.startsWith(':::')) {
- codeLines.push(startText);
+ // 如果开始标记后有内容,需要从 HTML 中提取
+ // 将
转换为换行符
+ let contentHTML = startHTML.replace(/^:::\s*mermaid\s*
/i, '');
+ let contentText = this.htmlToText(contentHTML);
+ if (contentText.trim()) {
+ codeLines.push(contentText);
+ }
}
// 检查是否在同一元素中就有结束标记
if (startText.endsWith(':::')) {
foundEnd = true;
// 移除结束标记
- let lastLine = codeLines[codeLines.length - 1];
- if (lastLine) {
+ if (codeLines.length > 0) {
+ let lastLine = codeLines[codeLines.length - 1];
codeLines[codeLines.length - 1] = lastLine.replace(/:::\s*$/, '').trim();
}
}
@@ -4554,15 +4565,19 @@ void 0;
if (text !== ':::') {
text = text.replace(/:::\s*$/, '').trim();
if (text) {
- codeLines.push(text);
+ // 将 HTML 转换为文本,保留换行符
+ let contentText = this.htmlToText(currentElement.innerHTML);
+ codeLines.push(contentText);
}
}
break;
}
// 添加当前元素的内容
- if (text) {
- codeLines.push(text);
+ // 将 HTML 转换为文本,保留换行符
+ let contentText = this.htmlToText(currentElement.innerHTML);
+ if (contentText.trim()) {
+ codeLines.push(contentText);
} else {
// 空元素,添加空行
codeLines.push('');
@@ -4581,6 +4596,8 @@ void 0;
// 合并所有行
let code = codeLines.join('\n').trim();
+ this.logDebug('提取的完整代码: ' + code.substring(0, 200));
+
if (!code) {
return null;
}
@@ -4596,6 +4613,27 @@ void 0;
return container;
},
+
+ /**
+ * 将 HTML 转换为纯文本,保留换行符
+ * @param {string} html - HTML 字符串
+ * @returns {string} 纯文本
+ */
+ htmlToText(html) {
+ // 将
和
转换为换行符
+ let text = html.replace(/
/gi, '\n');
+ // 移除其他 HTML 标签
+ text = text.replace(/<[^>]+>/g, '');
+ // 解码 HTML 实体
+ text = text
+ .replace(/ /g, ' ')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(/'/g, "'");
+ return text;
+ },
/**
* 提取代码块内容
diff --git a/commit-msg-mermaid-newline-fix.txt b/commit-msg-mermaid-newline-fix.txt
new file mode 100644
index 0000000..45401e2
--- /dev/null
+++ b/commit-msg-mermaid-newline-fix.txt
@@ -0,0 +1,129 @@
+fix: 修复 Mermaid 容器语法换行符丢失问题
+
+## 问题描述
+
+用户提供的 AI 评论审核流程 Mermaid 图表渲染失败,错误信息显示:
+- `flowchart TDStart` - `TD` 和 `Start` 之间缺少换行符
+- 箭头符号被转换成全角 `–>` 而不是 `-->`
+
+## 根本原因
+
+WP-Markdown 插件将容器语法 `::: mermaid ... :::` 转换为 HTML 时:
+1. 每一行代码都被包裹在 `` 标签中
+2. 行内的换行使用 `
` 标签表示
+3. 使用 `textContent` 或 `innerText` 提取时,`
` 标签被忽略或转换为空格
+4. 导致多行代码被合并成一行,Mermaid 语法解析失败
+
+## 修复方案
+
+### 1. 新增 `htmlToText()` 辅助函数
+
+```javascript
+htmlToText(html) {
+ // 将
和
转换为换行符
+ let text = html.replace(/
/gi, '\n');
+ // 移除其他 HTML 标签
+ text = text.replace(/<[^>]+>/g, '');
+ // 解码 HTML 实体
+ text = text
+ .replace(/ /g, ' ')
+ .replace(/</g, '<')
+ .replace(/>/g, '>')
+ .replace(/&/g, '&')
+ .replace(/"/g, '"')
+ .replace(/'/g, "'");
+ return text;
+}
+```
+
+### 2. 改进 `extractContainerContent()` 函数
+
+- 使用 `innerHTML` 而不是 `textContent` 或 `innerText`
+- 调用 `htmlToText()` 将 `
` 标签转换为换行符
+- 保留所有换行符和空行
+- 添加详细的调试日志
+
+### 3. 处理流程
+
+```
+1. 检测到 ::: mermaid 开始标记
+2. 提取 innerHTML(包含
标签)
+3. 使用 htmlToText() 转换:
+ -
→ \n
+ - 移除其他 HTML 标签
+ - 解码 HTML 实体
+4. 收集所有行内容
+5. 使用 \n 连接所有行
+6. 创建容器元素存储完整代码
+```
+
+## 测试验证
+
+### 测试用例 1:简单流程图
+```markdown
+::: mermaid
+flowchart TD
+ A[开始] --> B[处理]
+ B --> C[结束]
+:::
+```
+
+### 测试用例 2:复杂流程图(AI 评论审核)
+- 包含 100+ 个节点
+- 包含多行文本(`
` 标签)
+- 包含箭头符号(`-->`, `-->`)
+- 包含样式定义(`style` 语句)
+
+### 预期结果
+- ✅ 所有换行符正确保留
+- ✅ 箭头符号不被转换
+- ✅ 多行文本正确显示
+- ✅ 样式定义正确应用
+
+## 影响范围
+
+- 仅影响 Markdown 容器语法(`::: mermaid ... :::`)
+- 不影响其他格式(`
`, `` 等)
+- 向后兼容,不影响现有功能
+
+## 相关文件
+
+- `argontheme.js` - 修改 `extractContainerContent()` 和新增 `htmlToText()`
+- `tests/test-ai-comment-flow.md` - 测试文档
+- `docs/mermaid-usage-guide.md` - 使用指南
+
+## 技术细节
+
+### HTML 结构示例
+
+WP-Markdown 生成的 HTML:
+```html
+::: mermaid
+flowchart TD
+ Start([用户提交评论]) --> PreProcess[预处理]
+:::
+```
+
+### 提取过程
+
+1. **原始 HTML**: `::: mermaid
flowchart TD
Start --> End
:::`
+2. **htmlToText()**: `::: mermaid\nflowchart TD\nStart --> End\n:::`
+3. **移除标记**: `flowchart TD\nStart --> End`
+4. **最终代码**:
+ ```
+ flowchart TD
+ Start --> End
+ ```
+
+## 注意事项
+
+1. **性能影响**:使用 `innerHTML` 和正则替换,性能影响可忽略
+2. **安全性**:只处理 Mermaid 代码块,不执行任何脚本
+3. **兼容性**:支持所有现代浏览器
+4. **调试**:添加详细日志,便于排查问题
+
+## 后续优化
+
+1. 考虑支持更多 Markdown 容器语法(如 `::: warning`, `::: tip` 等)
+2. 优化正则表达式性能
+3. 添加单元测试