From bf8f973e91672bfa3b873e5f0268fb27ff23ac83 Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Sat, 24 Jan 2026 20:56:43 +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=E7=9A=84=E6=8D=A2=E8=A1=8C=E7=AC=A6?= =?UTF-8?q?=E5=92=8C=E7=89=B9=E6=AE=8A=E5=AD=97=E7=AC=A6=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 问题描述 用户报告 Mermaid 图表仍然渲染失败: 1. `flowchart TDStart` - `TD` 和 `Start` 之间没有换行符(有两个空格) 2. 箭头符号变成全角 `–>` 而不是 `-->` ## 根本原因分析 ### 问题 1: 换行符丢失 WP-Markdown 可能将整个容器语法内容放在**一个** `

` 元素中: ```html

::: mermaid
flowchart TD
Start --> End
:::

``` 而不是多个独立的 `

` 元素。之前的代码只处理了多元素的情况。 ### 问题 2: 特殊字符转换 WordPress 的自动格式化功能会将某些字符转换为排版字符: - `--` → `–` (U+2013 EN DASH) - `---` → `—` (U+2014 EM DASH) - `->` → `→` (U+2192 RIGHTWARDS ARROW) 这些字符在 Mermaid 语法中有特殊含义,必须保持原样。 ## 修复方案 ### 1. 支持单元素容器语法 在 `extractContainerContent()` 函数中添加检测逻辑: ```javascript // 检查是否整个内容都在一个元素中 if (startText.includes(':::') && startText.lastIndexOf(':::') > 10) { // 整个容器语法在一个元素中 let fullText = this.htmlToText(startHTML); // 移除开始和结束标记 fullText = fullText.replace(/^:::\s*mermaid\s*/i, '').trim(); fullText = fullText.replace(/:::\s*$/, '').trim(); // 创建容器并返回 } ``` ### 2. 增强 htmlToText() 函数 添加更多字符转换规则: ```javascript // HTML 实体 .replace(/–/g, '-') // EN DASH .replace(/—/g, '--') // EM DASH .replace(/→/g, '->') // RIGHTWARDS ARROW .replace(/–/g, '-') // EN DASH (named entity) .replace(/—/g, '--') // EM DASH (named entity) .replace(/→/g, '->'); // RIGHTWARDS ARROW (named entity) // Unicode 字符 .replace(/–/g, '-') // U+2013 EN DASH .replace(/—/g, '--') // U+2014 EM DASH .replace(/→/g, '->'); // U+2192 RIGHTWARDS ARROW ``` ### 3. 添加详细调试日志 ```javascript this.logDebug('检查元素,textContent: ' + startText.substring(0, 50)); this.logDebug('innerHTML: ' + startHTML.substring(0, 100)); this.logDebug('检测到单元素容器语法'); this.logDebug('转换后的完整文本: ' + fullText.substring(0, 200)); this.logDebug('移除标记后的代码: ' + fullText.substring(0, 200)); ``` ## 处理流程 ### 单元素容器语法 ``` 1. 检测到 ::: mermaid 开始标记 2. 检查 textContent 中是否包含结束标记 ::: 3. 如果包含,说明整个内容在一个元素中 4. 提取 innerHTML 原始: "::: mermaid
flowchart TD
Start –> End
:::" 5. 使用 htmlToText() 转换 -
→ \n - – → - - → → -> 结果: "::: mermaid\nflowchart TD\nStart --> End\n:::" 6. 移除开始和结束标记 结果: "flowchart TD\nStart --> End" 7. 创建容器元素存储代码 ``` ### 多元素容器语法(保持原有逻辑) ``` 1. 检测到 ::: mermaid 开始标记 2. 遍历后续兄弟元素 3. 收集所有内容直到 ::: 结束标记 4. 使用 \n 连接所有行 5. 创建容器元素存储代码 ``` ## 测试验证 ### 测试用例 1: 单元素容器语法 ```html

::: mermaid
flowchart TD
A[开始] –> B[处理]
B –> C[结束]
:::

``` 预期结果: ``` flowchart TD A[开始] --> B[处理] B --> C[结束] ``` ### 测试用例 2: 多元素容器语法 ```html

::: mermaid

flowchart TD

A --> B

:::

``` 预期结果: ``` flowchart TD A --> B ``` ### 测试用例 3: 复杂流程图(AI 评论审核) - 100+ 个节点 - 多行文本(`
` 标签) - 箭头符号(`-->`, `-->`) - 样式定义(`style` 语句) ## 影响范围 - 仅影响 Markdown 容器语法(`::: mermaid ... :::`) - 不影响其他格式(`
`, `
` 等)
- 向后兼容,支持单元素和多元素两种情况

## 相关文件

- `argontheme.js` - 修改 `extractContainerContent()` 和 `htmlToText()`
- `tests/test-ai-comment-flow.md` - 测试文档

## 技术细节

### WordPress 自动格式化

WordPress 的 `wptexturize()` 函数会自动转换以下字符:
- `--` → `–` (EN DASH)
- `---` → `—` (EM DASH)
- `->` → `→` (RIGHTWARDS ARROW)
- `(c)` → `©` (COPYRIGHT SIGN)
- `(r)` → `®` (REGISTERED SIGN)
- `(tm)` → `™` (TRADE MARK SIGN)

这些转换对于普通文本是有益的,但对于代码块(如 Mermaid)是有害的。

### 解决方案

1. **禁用自动格式化**(不推荐)
   - 会影响整个网站的排版
   - 需要修改 WordPress 核心代码

2. **在提取时反转换**(推荐)✅
   - 只影响 Mermaid 代码块
   - 不影响其他内容
   - 易于维护

### 字符映射表

| 原始字符 | HTML 实体 | Unicode | 显示 |
|---------|----------|---------|------|
| `-` | `-` | U+002D | - |
| `--` | `–` / `–` | U+2013 | – |
| `---` | `—` / `—` | U+2014 | — |
| `->` | `→` / `→` | U+2192 | → |

## 注意事项

1. **性能影响**:增加了字符串替换操作,但性能影响可忽略
2. **安全性**:只处理 Mermaid 代码块,不执行任何脚本
3. **兼容性**:支持所有现代浏览器
4. **调试**:添加详细日志,便于排查问题

## 后续优化

1. 考虑使用 DOMParser 解析 HTML,更可靠
2. 添加更多特殊字符的转换规则
3. 支持自定义字符映射表
4. 添加单元测试

## 参考资料

- [WordPress wptexturize() 函数](https://developer.wordpress.org/reference/functions/wptexturize/)
- [Unicode 字符表](https://unicode-table.com/)
- [Mermaid 语法文档](https://mermaid.js.org/intro/syntax-reference.html)
---
 argontheme.js                    |  51 +++++++-
 commit-msg-mermaid-final-fix.txt | 207 +++++++++++++++++++++++++++++++
 2 files changed, 256 insertions(+), 2 deletions(-)
 create mode 100644 commit-msg-mermaid-final-fix.txt

diff --git a/argontheme.js b/argontheme.js
index c6bcea8..c8acd42 100644
--- a/argontheme.js
+++ b/argontheme.js
@@ -4524,10 +4524,44 @@ void 0;
 			let startHTML = startElement.innerHTML;
 			let startText = startElement.textContent.trim();
 			
+			this.logDebug('检查元素,textContent: ' + startText.substring(0, 50));
+			this.logDebug('innerHTML: ' + startHTML.substring(0, 100));
+			
 			if (startText.startsWith('::: mermaid')) {
 				foundStart = true;
-				this.logDebug('找到容器语法开始标记,原始 HTML: ' + startHTML.substring(0, 100));
+				this.logDebug('找到容器语法开始标记');
 				
+				// 检查是否整个内容都在一个元素中
+				if (startText.includes(':::') && startText.lastIndexOf(':::') > 10) {
+					// 整个容器语法在一个元素中
+					this.logDebug('检测到单元素容器语法');
+					
+					// 使用 htmlToText 转换整个 HTML
+					let fullText = this.htmlToText(startHTML);
+					this.logDebug('转换后的完整文本: ' + fullText.substring(0, 200));
+					
+					// 移除开始和结束标记
+					fullText = fullText.replace(/^:::\s*mermaid\s*/i, '').trim();
+					fullText = fullText.replace(/:::\s*$/, '').trim();
+					
+					this.logDebug('移除标记后的代码: ' + fullText.substring(0, 200));
+					
+					if (fullText) {
+						// 创建容器
+						const container = document.createElement('div');
+						container.className = 'mermaid-container-block';
+						container.textContent = fullText;
+						container.dataset.containerBlock = 'true';
+						
+						// 替换开始元素
+						startElement.parentNode.replaceChild(container, startElement);
+						
+						return container;
+					}
+					return null;
+				}
+				
+				// 多元素容器语法(原有逻辑)
 				// 移除开始标记,保留同一元素中的其他内容
 				startText = startText.replace(/^:::\s*mermaid\s*/i, '').trim();
 				if (startText && !startText.startsWith(':::')) {
@@ -4631,7 +4665,20 @@ void 0;
 				.replace(/>/g, '>')
 				.replace(/&/g, '&')
 				.replace(/"/g, '"')
-				.replace(/'/g, "'");
+				.replace(/'/g, "'")
+				.replace(/–/g, '-')  // EN DASH
+				.replace(/—/g, '--') // EM DASH
+				.replace(/→/g, '->') // RIGHTWARDS ARROW
+				.replace(/–/g, '-')  // EN DASH (named entity)
+				.replace(/—/g, '--') // EM DASH (named entity)
+				.replace(/→/g, '->'); // RIGHTWARDS ARROW (named entity)
+			
+			// 转换 Unicode 字符(WordPress 可能直接输出 Unicode)
+			text = text
+				.replace(/–/g, '-')   // U+2013 EN DASH
+				.replace(/—/g, '--')  // U+2014 EM DASH
+				.replace(/→/g, '->'); // U+2192 RIGHTWARDS ARROW
+			
 			return text;
 		},
 
diff --git a/commit-msg-mermaid-final-fix.txt b/commit-msg-mermaid-final-fix.txt
new file mode 100644
index 0000000..2faa3ac
--- /dev/null
+++ b/commit-msg-mermaid-final-fix.txt
@@ -0,0 +1,207 @@
+fix: 修复 Mermaid 容器语法的换行符和特殊字符问题
+
+## 问题描述
+
+用户报告 Mermaid 图表仍然渲染失败:
+1. `flowchart TDStart` - `TD` 和 `Start` 之间没有换行符(有两个空格)
+2. 箭头符号变成全角 `–>` 而不是 `-->`
+
+## 根本原因分析
+
+### 问题 1: 换行符丢失
+
+WP-Markdown 可能将整个容器语法内容放在**一个** `

` 元素中: +```html +

::: mermaid
flowchart TD
Start --> End
:::

+``` + +而不是多个独立的 `

` 元素。之前的代码只处理了多元素的情况。 + +### 问题 2: 特殊字符转换 + +WordPress 的自动格式化功能会将某些字符转换为排版字符: +- `--` → `–` (U+2013 EN DASH) +- `---` → `—` (U+2014 EM DASH) +- `->` → `→` (U+2192 RIGHTWARDS ARROW) + +这些字符在 Mermaid 语法中有特殊含义,必须保持原样。 + +## 修复方案 + +### 1. 支持单元素容器语法 + +在 `extractContainerContent()` 函数中添加检测逻辑: + +```javascript +// 检查是否整个内容都在一个元素中 +if (startText.includes(':::') && startText.lastIndexOf(':::') > 10) { + // 整个容器语法在一个元素中 + let fullText = this.htmlToText(startHTML); + // 移除开始和结束标记 + fullText = fullText.replace(/^:::\s*mermaid\s*/i, '').trim(); + fullText = fullText.replace(/:::\s*$/, '').trim(); + // 创建容器并返回 +} +``` + +### 2. 增强 htmlToText() 函数 + +添加更多字符转换规则: + +```javascript +// HTML 实体 +.replace(/–/g, '-') // EN DASH +.replace(/—/g, '--') // EM DASH +.replace(/→/g, '->') // RIGHTWARDS ARROW +.replace(/–/g, '-') // EN DASH (named entity) +.replace(/—/g, '--') // EM DASH (named entity) +.replace(/→/g, '->'); // RIGHTWARDS ARROW (named entity) + +// Unicode 字符 +.replace(/–/g, '-') // U+2013 EN DASH +.replace(/—/g, '--') // U+2014 EM DASH +.replace(/→/g, '->'); // U+2192 RIGHTWARDS ARROW +``` + +### 3. 添加详细调试日志 + +```javascript +this.logDebug('检查元素,textContent: ' + startText.substring(0, 50)); +this.logDebug('innerHTML: ' + startHTML.substring(0, 100)); +this.logDebug('检测到单元素容器语法'); +this.logDebug('转换后的完整文本: ' + fullText.substring(0, 200)); +this.logDebug('移除标记后的代码: ' + fullText.substring(0, 200)); +``` + +## 处理流程 + +### 单元素容器语法 + +``` +1. 检测到 ::: mermaid 开始标记 +2. 检查 textContent 中是否包含结束标记 ::: +3. 如果包含,说明整个内容在一个元素中 +4. 提取 innerHTML + 原始: "::: mermaid
flowchart TD
Start –> End
:::" +5. 使用 htmlToText() 转换 + -
→ \n + - – → - + - → → -> + 结果: "::: mermaid\nflowchart TD\nStart --> End\n:::" +6. 移除开始和结束标记 + 结果: "flowchart TD\nStart --> End" +7. 创建容器元素存储代码 +``` + +### 多元素容器语法(保持原有逻辑) + +``` +1. 检测到 ::: mermaid 开始标记 +2. 遍历后续兄弟元素 +3. 收集所有内容直到 ::: 结束标记 +4. 使用 \n 连接所有行 +5. 创建容器元素存储代码 +``` + +## 测试验证 + +### 测试用例 1: 单元素容器语法 +```html +

::: mermaid
+flowchart TD
+ A[开始] –> B[处理]
+ B –> C[结束]
+:::

+``` + +预期结果: +``` +flowchart TD + A[开始] --> B[处理] + B --> C[结束] +``` + +### 测试用例 2: 多元素容器语法 +```html +

::: mermaid

+

flowchart TD

+

A --> B

+

:::

+``` + +预期结果: +``` +flowchart TD +A --> B +``` + +### 测试用例 3: 复杂流程图(AI 评论审核) +- 100+ 个节点 +- 多行文本(`
` 标签) +- 箭头符号(`-->`, `-->`) +- 样式定义(`style` 语句) + +## 影响范围 + +- 仅影响 Markdown 容器语法(`::: mermaid ... :::`) +- 不影响其他格式(`
`, `
` 等)
+- 向后兼容,支持单元素和多元素两种情况
+
+## 相关文件
+
+- `argontheme.js` - 修改 `extractContainerContent()` 和 `htmlToText()`
+- `tests/test-ai-comment-flow.md` - 测试文档
+
+## 技术细节
+
+### WordPress 自动格式化
+
+WordPress 的 `wptexturize()` 函数会自动转换以下字符:
+- `--` → `–` (EN DASH)
+- `---` → `—` (EM DASH)
+- `->` → `→` (RIGHTWARDS ARROW)
+- `(c)` → `©` (COPYRIGHT SIGN)
+- `(r)` → `®` (REGISTERED SIGN)
+- `(tm)` → `™` (TRADE MARK SIGN)
+
+这些转换对于普通文本是有益的,但对于代码块(如 Mermaid)是有害的。
+
+### 解决方案
+
+1. **禁用自动格式化**(不推荐)
+   - 会影响整个网站的排版
+   - 需要修改 WordPress 核心代码
+
+2. **在提取时反转换**(推荐)✅
+   - 只影响 Mermaid 代码块
+   - 不影响其他内容
+   - 易于维护
+
+### 字符映射表
+
+| 原始字符 | HTML 实体 | Unicode | 显示 |
+|---------|----------|---------|------|
+| `-` | `-` | U+002D | - |
+| `--` | `–` / `–` | U+2013 | – |
+| `---` | `—` / `—` | U+2014 | — |
+| `->` | `→` / `→` | U+2192 | → |
+
+## 注意事项
+
+1. **性能影响**:增加了字符串替换操作,但性能影响可忽略
+2. **安全性**:只处理 Mermaid 代码块,不执行任何脚本
+3. **兼容性**:支持所有现代浏览器
+4. **调试**:添加详细日志,便于排查问题
+
+## 后续优化
+
+1. 考虑使用 DOMParser 解析 HTML,更可靠
+2. 添加更多特殊字符的转换规则
+3. 支持自定义字符映射表
+4. 添加单元测试
+
+## 参考资料
+
+- [WordPress wptexturize() 函数](https://developer.wordpress.org/reference/functions/wptexturize/)
+- [Unicode 字符表](https://unicode-table.com/)
+- [Mermaid 语法文档](https://mermaid.js.org/intro/syntax-reference.html)