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[结束]
+:::
::: mermaid
+flowchart TD
+A --> B
+:::
+``` + +预期结果: +``` +flowchart TD +A --> B +``` + +### 测试用例 3: 复杂流程图(AI 评论审核) +- 100+ 个节点 +- 多行文本(`` 等)
+- 向后兼容,支持单元素和多元素两种情况
+
+## 相关文件
+
+- `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)