From 29bfd284e065cf88607f2c1af580b773a97cf6b7 Mon Sep 17 00:00:00 2001 From: nanhaoluo <3075912108@qq.com> Date: Sat, 24 Jan 2026 21:35:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=9E=E7=8E=B0=20Mermaid=20?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=9D=97=E9=AD=94=E6=94=B9=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 convertMermaidCodeblocks() 函数,在代码高亮前拦截 mermaid 代码块 - 支持标准 Markdown 代码块 (\\\mermaid) 渲染 - 更新 detectMermaidBlocks() 添加 mermaid-from-codeblock 选择器 - 更新 extractMermaidCode() 支持新容器类型 - 创建测试文件 test-codeblock-magic.html - 更新用户文档、开发者文档和 FAQ - 完全绕过代码高亮和 WordPress 格式化 - 支持 PJAX 页面切换 - 特殊字符和换行符正确保留 --- .kiro/specs/mermaid-codeblock-magic/README.md | 50 + .kiro/specs/mermaid-codeblock-magic/design.md | 821 +++++++++++ .../mermaid-codeblock-magic/requirements.md | 501 +++++++ .kiro/specs/mermaid-codeblock-magic/tasks.md | 188 +++ .kiro/specs/mermaid-support/tasks.md | 12 +- argontheme.js | 64 +- commit-msg-container-fixes.txt | 171 +++ commit-msg-final.txt | 69 + commit-msg-mermaid-fixes.txt | 96 ++ commit-msg-mermaid-new.txt | 78 ++ docs/mermaid-developer-guide.md | 1230 +++++++++++++++++ docs/mermaid-faq.md | 712 ++++++++++ docs/mermaid-usage-guide.md | 158 ++- docs/mermaid-user-guide.md | 719 ++++++++++ settings.php | 233 ++++ tests/test-ai-comment-flow.md | 187 +++ tests/test-codeblock-magic.html | 295 ++++ tests/test-wp-markdown-format.html | 32 +- 18 files changed, 5566 insertions(+), 50 deletions(-) create mode 100644 .kiro/specs/mermaid-codeblock-magic/README.md create mode 100644 .kiro/specs/mermaid-codeblock-magic/design.md create mode 100644 .kiro/specs/mermaid-codeblock-magic/requirements.md create mode 100644 .kiro/specs/mermaid-codeblock-magic/tasks.md create mode 100644 commit-msg-container-fixes.txt create mode 100644 commit-msg-final.txt create mode 100644 commit-msg-mermaid-fixes.txt create mode 100644 commit-msg-mermaid-new.txt create mode 100644 docs/mermaid-developer-guide.md create mode 100644 docs/mermaid-faq.md create mode 100644 docs/mermaid-user-guide.md create mode 100644 tests/test-ai-comment-flow.md create mode 100644 tests/test-codeblock-magic.html diff --git a/.kiro/specs/mermaid-codeblock-magic/README.md b/.kiro/specs/mermaid-codeblock-magic/README.md new file mode 100644 index 0000000..d724a6e --- /dev/null +++ b/.kiro/specs/mermaid-codeblock-magic/README.md @@ -0,0 +1,50 @@ +# Mermaid 代码块魔改支持 + +## 概述 + +本 spec 旨在实现对标准 Markdown 代码块 ` ```mermaid ` 的支持,通过在代码高亮之前拦截并转换代码块,完全绕过 WordPress、WP-Markdown 插件和代码高亮的干扰。 + +## 核心思路 + +参考主题中数学公式的实现方式: +- **数学公式**:使用特殊分隔符(`$...$`),不会被 WordPress 和代码高亮干扰 +- **Mermaid**:使用代码块(` ```mermaid `),需要在代码高亮前拦截并转换 + +## 实现方案 + +1. **代码块拦截**:在 `highlightJsRender()` 函数开始处添加预处理 +2. **格式转换**:将 `
` 转换为 `
` +3. **渲染检测**:在 `detectMermaidBlocks()` 中添加新的选择器 +4. **代码提取**:在 `extractMermaidCode()` 中支持新的容器类型 + +## 优势 + +- ✅ 使用标准 Markdown 语法 +- ✅ 在编辑器中清晰可见 +- ✅ 不被 WordPress 格式化干扰 +- ✅ 不被代码高亮干扰 +- ✅ 支持 PJAX 页面切换 +- ✅ 兼容现有的 Shortcode 和容器语法 + +## 文件结构 + +``` +.kiro/specs/mermaid-codeblock-magic/ +├── README.md # 本文件 +├── requirements.md # 详细需求文档 +├── design.md # 设计文档(待创建) +└── tasks.md # 任务列表(待创建) +``` + +## 下一步 + +1. 审核 `requirements.md` 需求文档 +2. 创建 `design.md` 设计文档 +3. 创建 `tasks.md` 任务列表 +4. 开始实现 + +## 参考 + +- 数学公式实现:`footer.php` 第 36-147 行 +- 代码高亮实现:`argontheme.js` 第 3942-4000 行 +- Mermaid 渲染实现:`argontheme.js` 第 4430-4750 行 diff --git a/.kiro/specs/mermaid-codeblock-magic/design.md b/.kiro/specs/mermaid-codeblock-magic/design.md new file mode 100644 index 0000000..8029b94 --- /dev/null +++ b/.kiro/specs/mermaid-codeblock-magic/design.md @@ -0,0 +1,821 @@ +# Mermaid 代码块魔改支持 - 设计文档 + +## 1. 设计概述 + +### 1.1 设计目标 +实现标准 Markdown 代码块 (` ```mermaid `) 的 Mermaid 图表渲染,通过在代码高亮之前拦截并转换代码块,完全绕过 WordPress 和代码高亮的干扰。 + +### 1.2 核心设计理念 +**提前拦截,转换容器**:在代码高亮处理之前,将 `
` 转换为 `
`,使其不被代码高亮处理,同时能被 Mermaid 渲染系统识别。 + +### 1.3 设计参考 +参考主题中数学公式的实现方式: +- 数学公式使用特殊分隔符(`$...$`),不会被代码高亮处理 +- Mermaid 代码块通过提前转换,达到类似效果 +- 两者都在 PJAX 加载后重新处理 + +### 1.4 技术栈 +- **JavaScript**:原生 JavaScript + jQuery(主题现有技术栈) +- **Mermaid.js**:主题已集成的图表渲染库 +- **执行时机**:代码高亮之前(`highlightJsRender()` 函数开始处) + +## 2. 架构设计 + +### 2.1 整体流程 + +```mermaid +flowchart TD + A[页面加载/PJAX切换] --> B[highlightJsRender 调用] + B --> C[convertMermaidCodeblocks 执行] + C --> D[查找 mermaid 代码块] + D --> E{找到代码块?} + E -->|是| F[提取纯文本代码] + E -->|否| G[继续代码高亮] + F --> H[创建 mermaid-from-codeblock 容器] + H --> I[替换原始代码块] + I --> J[标记已处理] + J --> G + G --> K[代码高亮处理其他代码块] + K --> L[detectMermaidBlocks 检测] + L --> M[提取 Mermaid 代码] + M --> N[mermaid.init 渲染] +``` + +### 2.2 模块设计 + +#### 模块 1:代码块转换器 (convertMermaidCodeblocks) +**职责**:在代码高亮前拦截并转换 mermaid 代码块 + +**输入**:DOM 树(包含未处理的代码块) +**输出**:转换后的 DOM 树(mermaid 代码块已替换为容器) + +**核心逻辑**: +1. 使用多个选择器查找代码块 +2. 提取纯文本代码 +3. 创建新容器 +4. 替换原始元素 + +#### 模块 2:代码提取器 (extractMermaidCode) +**职责**:从不同格式的容器中提取 Mermaid 代码 + +**输入**:DOM 元素(可能是 div、pre、code) +**输出**:纯文本 Mermaid 代码 + +**支持格式**: +- `
`(新增) +- `
` +- `
` +- `
`(降级)
+
+#### 模块 3:Mermaid 检测器 (detectMermaidBlocks)
+**职责**:检测页面中所有需要渲染的 Mermaid 容器
+
+**输入**:DOM 树
+**输出**:需要渲染的元素列表
+
+**检测优先级**:
+1. `div.mermaid-shortcode`(Shortcode 格式)
+2. `div.mermaid-from-codeblock`(代码块魔改格式)
+3. `div.mermaid`(标准格式)
+4. `pre code.language-mermaid`(降级格式)
+
+### 2.3 数据流设计
+
+```
+原始 HTML:
+

+flowchart TD
+    A --> B
+
+ +↓ convertMermaidCodeblocks() + +转换后 HTML: +
+flowchart TD + A --> B +
+ +↓ detectMermaidBlocks() + +检测到的代码: +"flowchart TD\n A --> B" + +↓ mermaid.init() + +渲染后 HTML: +
+ ... +
+``` + +## 3. 详细设计 + +### 3.1 代码块转换函数 + +#### 函数签名 +```javascript +function convertMermaidCodeblocks() +``` + +#### 实现位置 +`argontheme.js` 第 3942 行之前(`highlightJsRender()` 函数开始处) + +#### 选择器设计 + +```javascript +const selectors = [ + 'pre > code.language-mermaid', // 标准 Markdown 格式(最常见) + 'pre > code.mermaid', // 简化格式 + 'code.language-mermaid', // 无 pre 包裹 + 'pre[data-lang="mermaid"]' // 自定义属性格式 +]; +``` + +**设计理由**: +- 支持多种插件生成的 HTML 结构 +- 优先匹配最常见的格式 +- 提供降级支持 + +#### 重复处理防护 +```javascript +if (element.dataset.mermaidProcessed) { + return; // 跳过已处理的元素 +} +``` + +**设计理由**: +- 避免 PJAX 切换时重复处理 +- 防止多次调用导致的错误 +- 使用 data 属性标记状态 + +#### 代码提取逻辑 +```javascript +let code = element.textContent.trim(); +``` + +**设计理由**: +- `textContent` 获取纯文本,避免 HTML 实体 +- `trim()` 移除前后空白 +- 不进行任何字符转换,保持原始内容 + +#### 容器创建逻辑 +```javascript +const container = document.createElement('div'); +container.className = 'mermaid-from-codeblock'; +container.textContent = code; +container.dataset.processed = 'true'; +``` + +**设计理由**: +- 使用 `textContent` 而非 `innerHTML`,避免 XSS +- 添加特定类名,便于识别来源 +- 标记已处理状态 + +#### 元素替换逻辑 +```javascript +const targetElement = element.closest('pre') || element; +targetElement.parentNode.replaceChild(container, targetElement); +``` + +**设计理由**: +- 优先替换整个 `
` 元素
+- 如果没有 `
` 包裹,替换 `` 元素
+- 保留原始位置和上下文
+
+### 3.2 集成点设计
+
+#### 集成点 1:highlightJsRender() 函数
+**位置**:`argontheme.js` 第 3942 行
+
+**修改前**:
+```javascript
+function highlightJsRender(){
+	if (typeof(hljs) == "undefined"){
+		return;
+	}
+	// ... 代码高亮逻辑
+}
+```
+
+**修改后**:
+```javascript
+function highlightJsRender(){
+	// 在代码高亮之前,先处理 Mermaid 代码块
+	convertMermaidCodeblocks();
+	
+	if (typeof(hljs) == "undefined"){
+		return;
+	}
+	// ... 代码高亮逻辑
+}
+```
+
+**设计理由**:
+- 在代码高亮之前执行,确保 mermaid 代码块不被处理
+- 不影响其他代码块的高亮
+- 执行顺序:转换 → 高亮 → 渲染
+
+#### 集成点 2:detectMermaidBlocks() 函数
+**位置**:`argontheme.js` 第 4430 行
+
+**修改前**:
+```javascript
+const selectors = [
+	'div.mermaid-shortcode',
+	'div.mermaid',
+	'pre code.language-mermaid',
+	// ...
+];
+```
+
+**修改后**:
+```javascript
+const selectors = [
+	'div.mermaid-shortcode',         // Shortcode 格式
+	'div.mermaid-from-codeblock',    // 代码块魔改格式(新增)
+	'div.mermaid',                   // 标准格式
+	'pre code.language-mermaid',     // Markdown 格式(降级)
+	'pre[data-lang="mermaid"]',      // 自定义属性格式
+	'code.mermaid'                   // 简化格式
+];
+```
+
+**设计理由**:
+- 添加新的容器类型到检测列表
+- 优先级高于标准 `mermaid` 类
+- 保留降级选择器,确保兼容性
+
+#### 集成点 3:extractMermaidCode() 函数
+**位置**:`argontheme.js` 第 4650 行
+
+**修改前**:
+```javascript
+// 处理 Shortcode 格式
+if (element.classList.contains('mermaid-shortcode')) {
+	code = element.textContent;
+	this.logDebug('从 Shortcode 格式提取代码');
+}
+```
+
+**修改后**:
+```javascript
+// 处理 Shortcode 格式
+if (element.classList.contains('mermaid-shortcode')) {
+	code = element.textContent;
+	this.logDebug('从 Shortcode 格式提取代码');
+}
+// 处理代码块魔改格式
+else if (element.classList.contains('mermaid-from-codeblock')) {
+	code = element.textContent;
+	this.logDebug('从代码块魔改格式提取代码');
+}
+```
+
+**设计理由**:
+- 与 Shortcode 格式使用相同的提取方式
+- 添加调试日志,便于追踪
+- 保持代码一致性
+
+### 3.3 PJAX 兼容设计
+
+#### 执行时机
+PJAX 加载完成后的回调链(`argontheme.js` 第 2862-2890 行):
+```javascript
+$(document).on('pjax:complete', function() {
+	// ... 其他初始化
+	try { highlightJsRender(); } catch (err) { ... }  // 包含代码块转换
+	// ... 其他初始化
+});
+```
+
+**设计理由**:
+- `highlightJsRender()` 已在 PJAX 回调中调用
+- 代码块转换自动在每次 PJAX 切换后执行
+- 无需额外修改 PJAX 逻辑
+
+#### 重复处理防护
+使用 `data-processed` 属性标记已处理的元素:
+```javascript
+if (element.dataset.mermaidProcessed) {
+	return;
+}
+// ... 处理逻辑
+element.dataset.mermaidProcessed = 'true';
+```
+
+**设计理由**:
+- 避免同一元素被多次转换
+- 支持 PJAX 页面切换
+- 轻量级标记,不影响性能
+
+### 3.4 错误处理设计
+
+#### 空代码检查
+```javascript
+let code = element.textContent.trim();
+if (!code) {
+	return; // 跳过空代码块
+}
+```
+
+**设计理由**:
+- 避免创建空容器
+- 减少不必要的 DOM 操作
+- 提高性能
+
+#### Try-Catch 包裹
+```javascript
+try {
+	convertMermaidCodeblocks();
+} catch (err) {
+	console.error('Mermaid 代码块转换失败:', err);
+}
+```
+
+**设计理由**:
+- 捕获异常,不中断其他代码块的处理
+- 记录错误日志,便于调试
+- 提供降级方案(代码块仍可通过降级选择器检测)
+
+#### 降级支持
+如果代码块转换失败,仍可通过降级选择器检测:
+```javascript
+'pre code.language-mermaid'  // 降级选择器
+```
+
+**设计理由**:
+- 确保即使转换失败,仍能渲染
+- 提供多层保障
+- 增强系统健壮性
+
+## 4. 接口设计
+
+### 4.1 公共函数
+
+#### convertMermaidCodeblocks()
+```javascript
+/**
+ * 在代码高亮之前转换 Mermaid 代码块
+ * 将 
 转换为 
+ * + * @returns {void} + */ +function convertMermaidCodeblocks() { + // 实现逻辑 +} +``` + +### 4.2 数据结构 + +#### 容器元素结构 +```html +
+ flowchart TD + A --> B +
+``` + +**属性说明**: +- `class="mermaid-from-codeblock"`:标识来源于代码块 +- `data-processed="true"`:标记已处理 +- 内容:纯文本 Mermaid 代码 + +### 4.3 选择器优先级 + +| 优先级 | 选择器 | 用途 | +|--------|--------|------| +| 1 | `pre > code.language-mermaid` | 标准 Markdown 格式 | +| 2 | `pre > code.mermaid` | 简化格式 | +| 3 | `code.language-mermaid` | 无 pre 包裹 | +| 4 | `pre[data-lang="mermaid"]` | 自定义属性格式 | + +## 5. 性能设计 + +### 5.1 性能目标 +- 单个代码块处理时间 < 10ms +- 不影响页面加载速度 +- 不增加额外的 HTTP 请求 + +### 5.2 性能优化策略 + +#### 优化 1:使用原生 JavaScript +```javascript +document.querySelectorAll(selector) // 而非 $(selector) +``` + +**理由**:原生方法性能更好,减少 jQuery 开销 + +#### 优化 2:提前返回 +```javascript +if (element.dataset.mermaidProcessed) { + return; // 提前返回,避免不必要的处理 +} +``` + +**理由**:减少重复处理,提高效率 + +#### 优化 3:批量处理 +```javascript +selectors.forEach(selector => { + document.querySelectorAll(selector).forEach(element => { + // 处理逻辑 + }); +}); +``` + +**理由**:一次性查找所有元素,减少 DOM 查询次数 + +#### 优化 4:最小化 DOM 操作 +```javascript +const container = document.createElement('div'); +container.className = 'mermaid-from-codeblock'; +container.textContent = code; +container.dataset.processed = 'true'; +targetElement.parentNode.replaceChild(container, targetElement); +``` + +**理由**:一次性创建和替换,减少重排和重绘 + +### 5.3 性能监控 + +#### 调试日志 +```javascript +this.logDebug('处理了 ' + count + ' 个 Mermaid 代码块'); +this.logDebug('代码内容(前100字符): ' + code.substring(0, 100)); +``` + +**理由**:便于追踪性能问题,不影响生产环境 + +## 6. 安全设计 + +### 6.1 XSS 防护 + +#### 使用 textContent 而非 innerHTML +```javascript +container.textContent = code; // 安全 +// container.innerHTML = code; // 不安全 +``` + +**理由**:`textContent` 会自动转义 HTML,防止 XSS 攻击 + +#### 代码来源验证 +```javascript +let code = element.textContent.trim(); +if (!code) { + return; // 拒绝空代码 +} +``` + +**理由**:避免处理恶意或无效的代码块 + +### 6.2 DOM 操作安全 + +#### 安全的元素替换 +```javascript +const targetElement = element.closest('pre') || element; +if (targetElement.parentNode) { + targetElement.parentNode.replaceChild(container, targetElement); +} +``` + +**理由**:检查父节点存在,避免 null 引用错误 + +## 7. 测试设计 + +### 7.1 单元测试 + +#### 测试用例 1:标准代码块转换 +```javascript +// 输入 +

+flowchart TD
+    A --> B
+
+ +// 预期输出 +
+flowchart TD + A --> B +
+``` + +#### 测试用例 2:空代码块处理 +```javascript +// 输入 +
+ +// 预期输出 +
// 不转换 +``` + +#### 测试用例 3:重复处理防护 +```javascript +// 第一次处理 +convertMermaidCodeblocks(); // 转换成功 + +// 第二次处理 +convertMermaidCodeblocks(); // 跳过已处理的元素 +``` + +#### 测试用例 4:特殊字符保留 +```javascript +// 输入 +

+A --> B
+C -- text --> D
+
+ +// 预期输出 +代码中的 --> 和 -- 保持不变 +``` + +### 7.2 集成测试 + +#### 测试场景 1:与代码高亮集成 +1. 页面包含 mermaid 代码块和其他代码块 +2. 调用 `highlightJsRender()` +3. 验证 mermaid 代码块被转换,其他代码块被高亮 + +#### 测试场景 2:与 Mermaid 渲染集成 +1. 页面包含转换后的容器 +2. 调用 `detectMermaidBlocks()` +3. 验证容器被检测到 +4. 调用 `mermaid.init()` +5. 验证图表正确渲染 + +#### 测试场景 3:PJAX 兼容性 +1. 初始页面加载,代码块正确转换和渲染 +2. PJAX 切换到新页面 +3. 验证新页面的代码块正确转换和渲染 +4. 验证已转换的代码块不被重复处理 + +### 7.3 浏览器测试 + +#### 测试矩阵 +| 浏览器 | 版本 | 测试项 | +|--------|------|--------| +| Chrome | 最新版 | 全部功能 | +| Firefox | 最新版 | 全部功能 | +| Safari | 最新版 | 全部功能 | +| Edge | 最新版 | 全部功能 | + +#### 测试项 +- 代码块转换 +- 图表渲染 +- PJAX 切换 +- 性能表现 + +### 7.4 测试文件 + +创建 `tests/test-codeblock-magic.html`: +```html + + + + Mermaid 代码块魔改测试 + + + +

+	flowchart TD
+	    A --> B
+	
+ + +

+	graph LR
+	    C --> D
+	
+ + +

+	flowchart TD
+	    A -- text --> B
+	    C ==> D
+	
+ + +
+ + +``` + +## 8. 部署设计 + +### 8.1 部署步骤 + +#### 步骤 1:修改 argontheme.js +1. 在 `highlightJsRender()` 函数开始处添加 `convertMermaidCodeblocks()` 调用 +2. 实现 `convertMermaidCodeblocks()` 函数 +3. 修改 `detectMermaidBlocks()` 函数,添加新选择器 +4. 修改 `extractMermaidCode()` 函数,支持新容器类型 + +#### 步骤 2:测试验证 +1. 创建测试文件 `tests/test-codeblock-magic.html` +2. 在本地环境测试所有用例 +3. 验证 PJAX 兼容性 +4. 检查浏览器控制台无错误 + +#### 步骤 3:文档更新 +1. 更新 `docs/mermaid-usage-guide.md` +2. 更新 `docs/mermaid-developer-guide.md` +3. 更新 `docs/mermaid-faq.md` + +#### 步骤 4:发布 +1. 提交代码到 Git +2. 更新版本号 +3. 发布更新 + +### 8.2 回滚方案 + +如果出现问题,可以快速回滚: +1. 移除 `convertMermaidCodeblocks()` 调用 +2. 移除新添加的选择器 +3. 恢复原始代码 + +**降级方案**: +- 用户仍可使用 Shortcode 格式 +- 用户仍可使用容器语法 +- 不影响现有功能 + +### 8.3 兼容性保证 + +#### 向后兼容 +- 不影响现有的 Shortcode 格式 +- 不影响现有的容器语法 +- 不影响其他代码块的高亮 + +#### 向前兼容 +- 预留扩展接口 +- 支持未来的新格式 +- 易于维护和升级 + +## 9. 监控与维护 + +### 9.1 日志设计 + +#### 调试日志 +```javascript +this.logDebug('开始转换 Mermaid 代码块'); +this.logDebug('找到 ' + elements.length + ' 个代码块'); +this.logDebug('代码内容: ' + code.substring(0, 100)); +this.logDebug('转换完成'); +``` + +#### 错误日志 +```javascript +console.error('Mermaid 代码块转换失败:', err); +console.error('元素:', element); +console.error('代码:', code); +``` + +### 9.2 性能监控 + +#### 性能指标 +- 代码块转换时间 +- 页面加载时间 +- 内存使用情况 + +#### 监控方法 +```javascript +const startTime = performance.now(); +convertMermaidCodeblocks(); +const endTime = performance.now(); +console.log('转换耗时:', endTime - startTime, 'ms'); +``` + +### 9.3 维护计划 + +#### 定期检查 +- 每月检查浏览器兼容性 +- 每季度检查性能表现 +- 每半年检查代码质量 + +#### 更新策略 +- 跟进 Mermaid.js 版本更新 +- 跟进 WordPress 版本更新 +- 跟进浏览器标准更新 + +## 10. 风险与缓解 + +### 10.1 技术风险 + +#### 风险 1:与其他插件冲突 +**影响**:中等 +**概率**:低 +**缓解措施**: +- 使用唯一的类名 `mermaid-from-codeblock` +- 添加命名空间,避免冲突 +- 提供配置选项,允许禁用 + +#### 风险 2:性能问题 +**影响**:低 +**概率**:低 +**缓解措施**: +- 优化选择器,减少 DOM 查询 +- 使用缓存,避免重复处理 +- 添加性能监控 + +#### 风险 3:浏览器兼容性 +**影响**:中等 +**概率**:低 +**缓解措施**: +- 使用标准 API +- 添加 polyfill +- 提供降级方案 + +### 10.2 用户体验风险 + +#### 风险 1:误转换其他代码块 +**影响**:高 +**概率**:极低 +**缓解措施**: +- 使用精确的选择器 +- 添加类名检查 +- 提供白名单机制 + +#### 风险 2:特殊字符丢失 +**影响**:高 +**概率**:极低 +**缓解措施**: +- 使用 `textContent` 保留原始内容 +- 不进行任何字符转换 +- 添加测试用例验证 + +## 11. 未来扩展 + +### 11.1 短期扩展(1-2 周) + +#### 配置选项 +添加主题设置选项: +- 是否启用代码块魔改 +- 选择器优先级配置 +- 调试模式开关 + +#### 性能优化 +- 添加缓存机制 +- 批量处理优化 +- 延迟加载支持 + +### 11.2 中期扩展(1-2 月) + +#### 编辑器支持 +- 添加编辑器预览功能 +- 支持实时渲染 +- 提供语法提示 + +#### 移动端优化 +- 优化移动端显示 +- 支持触摸交互 +- 响应式布局 + +### 11.3 长期扩展(3-6 月) + +#### 多图表库支持 +- 支持 PlantUML +- 支持 GraphViz +- 支持 D3.js + +#### 高级功能 +- 图表编辑器 +- 图表导出(PNG、SVG) +- 图表分享 + +## 12. 总结 + +### 12.1 设计优势 + +1. **简单高效**:只需添加一个函数,修改三个位置 +2. **兼容性好**:不影响现有功能,支持多种格式 +3. **性能优秀**:使用原生 JavaScript,优化 DOM 操作 +4. **易于维护**:代码清晰,注释详细,易于理解 +5. **安全可靠**:防止 XSS,处理异常,提供降级 + +### 12.2 关键决策 + +| 决策 | 理由 | +|------|------| +| 在代码高亮前拦截 | 避免代码高亮干扰 | +| 使用 textContent | 保留原始内容,防止 XSS | +| 创建新容器类型 | 便于识别来源,支持多种格式 | +| 添加重复处理防护 | 支持 PJAX,避免重复转换 | +| 提供降级支持 | 确保即使转换失败仍能渲染 | + +### 12.3 实施建议 + +1. **分步实施**:先实现核心功能,再添加优化 +2. **充分测试**:创建完整的测试用例,覆盖所有场景 +3. **文档完善**:更新用户文档和开发者文档 +4. **监控反馈**:收集用户反馈,持续优化 + +### 12.4 成功标准 + +- ✅ 可以使用 ` ```mermaid ` 代码块编写图表 +- ✅ 代码块不会被代码高亮处理 +- ✅ 图表正确渲染 +- ✅ 特殊字符不被转换 +- ✅ 换行符正确保留 +- ✅ PJAX 切换正常工作 +- ✅ 性能无明显影响 +- ✅ 兼容所有主流浏览器 diff --git a/.kiro/specs/mermaid-codeblock-magic/requirements.md b/.kiro/specs/mermaid-codeblock-magic/requirements.md new file mode 100644 index 0000000..a576fdf --- /dev/null +++ b/.kiro/specs/mermaid-codeblock-magic/requirements.md @@ -0,0 +1,501 @@ +# Mermaid 代码块魔改支持 - 需求文档 + +## 1. 项目概述 + +### 1.1 背景 +当前 Argon 主题支持 Mermaid 图表渲染,但存在多个标记方式的兼容性问题: +- **标准 Markdown 代码块** (` ```mermaid `):被 WP-Markdown 插件和代码高亮干扰 +- **容器语法** (`::: mermaid ... :::`):空行导致内容截断 +- **Shortcode** (`[mermaid]...[/mermaid]`):可用但不符合 Markdown 标准 + +用户希望使用标准 Markdown 语法 ` ```mermaid `,但需要绕过所有干扰。 + +### 1.2 核心问题 +1. WP-Markdown 插件会将 ` ```mermaid ` 代码块用 `document.write()` 包裹 +2. WordPress 的 `wptexturize()` 会自动转换特殊字符(`--` → `–`) +3. 主题的代码高亮会处理 mermaid 代码块,添加行号和控制按钮 +4. 三方冲突导致 Mermaid 代码无法正确渲染 + +### 1.3 解决方案 +**魔改代码块显示**:在代码高亮之前拦截 mermaid 代码块,将其转换为 Mermaid 渲染容器,完全绕过代码高亮和 WordPress 格式化。 + +### 1.4 参考实现 +主题中数学公式的实现方式可以作为参考: +- **MathJax/KaTeX**:使用特定分隔符(`$...$`、`\(...\)`)标记数学公式 +- **渲染时机**:在 PJAX 加载完成后调用 `MathJax.typeset()` 或 `renderMathInElement()` +- **不干扰代码高亮**:数学公式使用特殊标记,不会被代码高亮处理 +- **WordPress 兼容**:数学公式分隔符不会被 WordPress 自动转换 + +**关键差异**: +- 数学公式使用**内联标记**(`$...$`),不需要代码块 +- Mermaid 需要使用**代码块**(` ```mermaid `),需要在代码高亮前拦截 +- 数学公式库自动扫描页面,Mermaid 需要手动检测和渲染 + +## 2. 用户故事 + +### 2.1 作为博客作者 +**我想要**:使用标准 Markdown 语法 ` ```mermaid ` 编写流程图 +**以便**:在原生编辑器中清晰可见,符合 Markdown 标准,无需学习特殊语法 + +**验收标准**: +- 可以使用 ` ```mermaid ` 代码块编写 Mermaid 图表 +- 代码块不会被代码高亮处理(无行号、无控制按钮) +- 代码块会被正确转换为 Mermaid 图表 +- 支持所有 Mermaid 语法(flowchart, sequence, class, state 等) + +### 2.2 作为博客作者 +**我想要**:Mermaid 代码中的特殊字符不被 WordPress 转换 +**以便**:箭头符号 `-->` 不会变成 `–>`,图表能正确渲染 + +**验收标准**: +- 箭头符号 `-->` 保持不变 +- 双横线 `--` 保持不变 +- 其他特殊字符(`==`, `~~`, `::` 等)保持不变 +- 换行符正确保留 + +### 2.3 作为博客作者 +**我想要**:Mermaid 代码块在编辑器中显示为代码块 +**以便**:编辑时能清晰看到代码结构,方便修改 + +**验收标准**: +- 在 WordPress 原生编辑器中显示为代码块 +- 在 WP-Markdown 编辑器中显示为代码块 +- 代码块有语法高亮(编辑器层面) +- 保存后前端正确渲染为图表 + +### 2.4 作为开发者 +**我想要**:拦截逻辑在代码高亮之前执行 +**以便**:避免代码高亮干扰 Mermaid 渲染 + +**验收标准**: +- 在 `highlightJsRender()` 函数开始处添加预处理 +- 查找所有 `pre > code.language-mermaid` 元素 +- 提取纯文本代码(不经过任何处理) +- 创建 Mermaid 渲染容器 +- 替换原始代码块元素 + +### 2.5 作为开发者 +**我想要**:支持多种 Mermaid 代码块格式 +**以便**:兼容不同插件和编辑器生成的 HTML 结构 + +**验收标准**: +- 支持 `
` 格式
+- 支持 `
` 格式
+- 支持 `` 格式(无 pre 包裹)
+- 支持 `
` 格式
+
+## 3. 功能需求
+
+### 3.1 代码块拦截(核心功能)
+
+**需求描述**:在代码高亮之前拦截 mermaid 代码块
+
+**实现位置**:`argontheme.js` 的 `highlightJsRender()` 函数开始处(第 3942 行)
+
+**参考实现**:类似数学公式在 PJAX 加载后的处理方式(第 2862-2880 行)
+
+**处理流程**:
+1. 在 `highlightJsRender()` 函数开始处添加预处理
+2. 查找所有 mermaid 代码块(多种选择器)
+3. 遍历每个代码块
+4. 提取纯文本代码
+5. 创建 Mermaid 渲染容器
+6. 替换原始代码块元素
+7. 标记已处理(避免重复处理)
+
+**选择器优先级**:
+```javascript
+const selectors = [
+	'pre > code.language-mermaid',  // 标准格式(最常见)
+	'pre > code.mermaid',           // 简化格式
+	'code.language-mermaid',        // 无 pre 包裹
+	'pre[data-lang="mermaid"]'      // 自定义属性格式
+];
+```
+
+**实现示例**:
+```javascript
+function highlightJsRender(){
+	// 在代码高亮之前,先处理 Mermaid 代码块
+	convertMermaidCodeblocks();
+	
+	// 原有的代码高亮逻辑
+	if (typeof(hljs) == "undefined"){
+		return;
+	}
+	// ...
+}
+
+function convertMermaidCodeblocks(){
+	// 查找所有 mermaid 代码块
+	const selectors = [
+		'pre > code.language-mermaid',
+		'pre > code.mermaid',
+		'code.language-mermaid',
+		'pre[data-lang="mermaid"]'
+	];
+	
+	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;
+			targetElement.parentNode.replaceChild(container, targetElement);
+		});
+	});
+}
+```
+
+### 3.2 代码提取
+
+**需求描述**:从不同格式的代码块中提取纯文本代码
+
+**处理逻辑**:
+- 使用 `textContent` 获取纯文本(避免 HTML 实体)
+- 移除前后空白字符(`trim()`)
+- 不进行任何字符转换(保持原始内容)
+- 检查代码是否为空
+
+**特殊处理**:
+- 如果代码块包含 `flowchart TD ...
` +- script 标签后面还有一份重复的代码 +- 当前代码只提取了 script 内容,但没有移除 script 标签 +- 导致后续的 `element.textContent` 包含了重复内容 + +### 问题 2: 容器语法空行导致内容截断 + +**错误信息**: +``` +Parse error on line 1: flowchart TD Sta +Expecting 'NEWLINE', 'SPACE', 'GRAPH', got 'ALPHA' +``` + +**原因分析**: +- 使用 `::: mermaid ... :::` 语法时,WP-Markdown 遇到空行会分割内容 +- 空行后的内容被识别为新的段落或代码块 +- 原有的单元素检测逻辑无法处理跨多个元素的情况 +- 导致只提取到第一个元素的内容("flowchart TD Sta") + +## 修复方案 + +### 修复 1: 移除 script 标签避免重复(argontheme.js:4575-4578) + +在 `extractMermaidCode()` 函数中,提取完 script 内容后立即移除标签: + +```javascript +// 重要:移除 script 标签,避免重复渲染 +// WP-Markdown 会在 script 后面再输出一次代码 +scriptTag.remove(); +``` + +**效果**: +- ✅ 避免 document.write 内容和后续文本重复 +- ✅ 确保只提取一次完整代码 +- ✅ 不影响其他格式的提取 + +### 修复 2: 跨元素收集容器语法内容(argontheme.js:4468-4570) + +完全重写 `detectContainerBlocks()` 和 `extractContainerContent()` 函数: + +**新的检测逻辑**: +1. 查找所有可能包含 `::: mermaid` 的元素(p, pre, code, div) +2. 找到开始标记后,收集所有后续兄弟元素 +3. 直到遇到 `:::` 结束标记 +4. 合并所有内容,保留空行 + +**关键代码**: +```javascript +// 收集所有内容直到结束标记 +while (currentElement) { + processedElements.add(currentElement); + let text = currentElement.textContent.trim(); + + // 检查是否是结束标记 + if (text === ':::' || text.endsWith(':::')) { + foundEnd = true; + break; + } + + // 添加当前元素的内容 + if (text) { + codeLines.push(text); + } else { + // 空元素,添加空行 + codeLines.push(''); + } + + currentElement = currentElement.nextElementSibling; +} + +// 合并所有行 +let code = codeLines.join('\n').trim(); +``` + +**效果**: +- ✅ 支持跨多个元素收集内容 +- ✅ 正确处理空行(保留为空字符串) +- ✅ 完整提取所有 mermaid 代码 +- ✅ 避免内容截断 + +## 测试场景 + +### 场景 1: WP-Markdown 格式 +```html +
+ + flowchart TD + A --> B +
+``` +**预期**:只提取 script 中的内容,忽略后面的重复文本 + +### 场景 2: 容器语法(无空行) +``` +::: mermaid +flowchart TD + A --> B +::: +``` +**预期**:正常提取完整代码 + +### 场景 3: 容器语法(有空行) +``` +::: mermaid +flowchart TD + A[开始] + + B[处理] + + C[结束] + + A --> B --> C +::: +``` +**预期**:保留所有空行,完整提取代码 + +### 场景 4: 容器语法(被分割成多个元素) +```html +

::: mermaid

+

flowchart TD

+

A[开始]

+

+

B[处理]

+

:::

+``` +**预期**:跨元素收集,合并为完整代码 + +## 影响范围 + +- ✅ 修复了两个严重的渲染错误 +- ✅ 不影响其他标记格式 +- ✅ 向后兼容 +- ✅ 提升容器语法的鲁棒性 + +## 相关文件 + +- `argontheme.js` - 核心修复 +- `docs/mermaid-usage-guide.md` - 更新文档 + +## 提交信息 + +``` +fix: 修复容器语法和 WP-Markdown 的两个关键问题 + +- 修复 WP-Markdown document.write 重复输出问题 +- 改进容器语法检测,支持跨多个元素收集内容 +- 解决空行导致内容被分割成多个元素的问题 +``` + +Commit: b6d9f8c + +## 后续建议 + +1. **测试验证**:在实际文章中测试包含空行的复杂 mermaid 图表 +2. **性能优化**:如果页面有大量元素,可以考虑优化查找算法 +3. **错误处理**:添加更详细的日志,帮助调试边缘情况 diff --git a/commit-msg-final.txt b/commit-msg-final.txt new file mode 100644 index 0000000..36cf331 --- /dev/null +++ b/commit-msg-final.txt @@ -0,0 +1,69 @@ +feat: 添加 Markdown 容器语法支持,修复 WPMD 代码提取问题 + +问题描述: +- WP-Markdown 插件将 Markdown 代码块转换为特殊格式 +- 传统标记方式会被 WPMD 套上代码高亮窗口,导致嵌套结构 +- 某些字符被自动转义,导致渲染失败 +- 之前的正则表达式只能提取到第一个单词 + +解决方案: +添加 Markdown 容器语法支持(::: mermaid ... :::) +- 符合 Markdown 扩展规范(VuePress、Docusaurus 等使用相同语法) +- 不会被 WPMD 当作代码块处理,避免嵌套问题 +- 语法简洁,易于编写和阅读 +- 易于迁移到其他平台 + +修复内容: +1. 改进正则表达式为 ([\s\S]*?),匹配包括换行在内的所有字符 +2. 添加三层降级方案: + - 方案1: 匹配 document.write("...") + - 方案2: 直接提取引号内容 + - 方案3: 纯文本提取 +3. 增加详细的调试日志(原始内容、提取长度、最终代码) +4. 优化解码顺序(先 HTML 实体,后转义字符) +5. 添加容器语法检测逻辑(TreeWalker) + +代码变更: +- functions.php: + * argon_has_mermaid_content(): 添加容器语法检测 + +- argontheme.js: + * detectMermaidBlocks(): 添加容器语法检测 + * detectContainerBlocks(): 新增函数,检测 ::: mermaid 容器 + * extractContainerContent(): 新增函数,提取容器内容 + * extractMermaidCode(): 支持容器语法的代码提取 + +- tests/test-wp-markdown-format.html: + * 添加 7 种测试场景 + * 包含容器语法和标准格式测试 + +- docs/mermaid-usage-guide.md: + * 详细说明容器语法使用方法 + * 提供使用示例和最佳实践 + * 包含故障排除指南 + +支持的标记格式(按优先级): +1. ::: mermaid ... ::: - Markdown 容器语法 ⭐(推荐) +2.
- 标准格式(WPMD 生成) +3.
 - Markdown 格式
+4. 
 - 自定义属性格式
+5.  - 简化格式
+
+推荐使用方式:
+::: mermaid
+flowchart TD
+    A[开始] --> B[处理]
+    B --> C[结束]
+:::
+
+测试方法:
+1. 访问测试页面:https://blog.cartol.top/wp-content/themes/argon/tests/test-wp-markdown-format.html
+2. 查看控制台日志,确认所有测试用例都能正确提取和渲染
+3. 在文章中使用推荐的容器语法
+4. 如果还有问题,查看控制台的详细日志
+
+注意事项:
+- 强烈推荐使用 Markdown 容器语法,避免 WPMD 处理
+- 传统 Markdown 代码块仍然支持,但可能有嵌套问题
+- 所有标记方式都会自动解码 HTML 实体和转义字符
+- 容器语法符合现代 Markdown 扩展规范,易于迁移
diff --git a/commit-msg-mermaid-fixes.txt b/commit-msg-mermaid-fixes.txt
new file mode 100644
index 0000000..26236e8
--- /dev/null
+++ b/commit-msg-mermaid-fixes.txt
@@ -0,0 +1,96 @@
+fix: 修复代码高亮和容器语法的两个关键问题
+
+## 问题描述
+
+1. **代码高亮干扰 mermaid 渲染**
+   - 传统 Markdown 代码块(```mermaid)使用 document.write
+   - 代码高亮会处理这些代码块,导致 mermaid 无法正常渲染
+
+2. **容器语法空行处理错误**
+   - 使用 ::: mermaid 语法时,空行会导致内容被截断
+   - WPMD 将空行后的内容识别为代码块
+
+## 修复方案
+
+### 1. 代码高亮排除 mermaid(argontheme.js:3942-3962)
+
+在 `highlightJsRender()` 函数中添加检查:
+
+```javascript
+// 跳过 mermaid 代码块(避免代码高亮干扰 mermaid 渲染)
+if ($(block).hasClass("language-mermaid") || $(block).hasClass("mermaid")){
+    return;
+}
+// 跳过在 .mermaid 容器内的代码块
+if ($(block).closest('.mermaid').length > 0){
+    return;
+}
+```
+
+**效果**:
+- ✅ mermaid 代码块不会被代码高亮处理
+- ✅ 避免嵌套结构和渲染冲突
+- ✅ 普通代码块仍正常高亮
+
+### 2. 容器语法保留空行(argontheme.js:4508-4530)
+
+修改 `extractContainerContent()` 函数:
+
+```javascript
+// 移除开始标记 ::: mermaid(保留后面的换行符和空行)
+text = text.replace(/^:::\s*mermaid\s*\n?/i, '');
+
+// 移除结束标记 :::(保留前面的换行符和空行)
+text = text.replace(/\n?:::\s*$/i, '');
+
+// 不要 trim,保留代码中的空行
+if (!text) {
+    return null;
+}
+```
+
+**效果**:
+- ✅ 空行被正确保留
+- ✅ 多行 mermaid 代码完整提取
+- ✅ 避免内容被截断
+
+## 测试验证
+
+创建了 `tests/test-mermaid-fixes.html` 测试页面,包含:
+
+1. **代码高亮排除测试**
+   - Markdown 格式 mermaid(应排除)
+   - div.mermaid 格式(应排除)
+   - 普通代码块(应高亮)
+
+2. **容器语法空行测试**
+   - 包含空行的流程图
+   - 包含空行的时序图
+   - 包含多个连续空行
+
+3. **WP-Markdown 兼容性测试**
+   - document.write 格式
+
+## 影响范围
+
+- ✅ 不影响现有功能
+- ✅ 向后兼容所有标记格式
+- ✅ 提升用户体验
+
+## 相关文件
+
+- `argontheme.js` - 核心修复
+- `docs/mermaid-usage-guide.md` - 更新文档
+- `tests/test-mermaid-fixes.html` - 测试页面
+
+## 提交信息
+
+```
+fix: 修复代码高亮和容器语法的两个关键问题
+
+- 代码高亮排除 mermaid 代码块,避免干扰渲染
+- 容器语法正确处理空行,不再截断内容
+- 添加测试页面验证修复效果
+```
+
+Commit: 0ac5794
diff --git a/commit-msg-mermaid-new.txt b/commit-msg-mermaid-new.txt
new file mode 100644
index 0000000..ba71cfe
--- /dev/null
+++ b/commit-msg-mermaid-new.txt
@@ -0,0 +1,78 @@
+feat: 添加多种 Mermaid 标记方式,避免 WPMD 处理问题
+
+问题描述:
+- WP-Markdown 插件将 Markdown 代码块转换为特殊格式
+- 传统标记方式会被 WPMD 套上代码高亮窗口,导致嵌套结构
+- 某些字符被自动转义,导致渲染失败
+- 之前的正则表达式只能提取到第一个单词
+
+新增功能:
+1. Argon 自定义标记(推荐):
...
+ - 不会被 WPMD 处理 + - 语法简单清晰 + - 支持所有 Mermaid 图表类型 + +2. HTML 注释标记:... + - 在编辑器中不可见 + - 不会被任何插件处理 + - 适合需要隐藏标记的场景 + +3. data 属性标记:
...
+ - 符合 HTML5 规范 + - 语义化标记 + - 不会被 WPMD 处理 + +修复内容: +1. 改进正则表达式为 ([\s\S]*?),匹配包括换行在内的所有字符 +2. 添加三层降级方案: + - 方案1: 匹配 document.write("...") + - 方案2: 直接提取引号内容 + - 方案3: 纯文本提取 +3. 增加详细的调试日志(原始内容、提取长度、最终代码) +4. 优化解码顺序(先 HTML 实体,后转义字符) +5. 添加 HTML 注释标记检测逻辑(TreeWalker) + +代码变更: +- argontheme.js: + * detectMermaidBlocks(): 添加新选择器和注释检测 + * detectCommentBlocks(): 新增函数,检测 HTML 注释标记 + * extractCommentContent(): 新增函数,提取注释之间的内容 + * extractMermaidCode(): 支持新标记格式的代码提取 + +- tests/test-wp-markdown-format.html: + * 添加 9 种测试场景 + * 包含所有支持的标记格式 + * 使用改进后的提取逻辑 + +- docs/mermaid-wpmd-usage.md: + * 详细说明所有标记方式 + * 提供使用示例和最佳实践 + * 包含故障排除指南 + +支持的标记格式(按优先级): +1.
- WPMD 标准格式 +2.
- Argon 自定义格式 ⭐ +3.
- data 属性格式 +4. ... - HTML 注释格式 +5.
 - Markdown 格式
+6. 
 - 自定义属性格式
+7.  - 简化格式
+
+测试方法:
+1. 访问测试页面:https://blog.cartol.top/wp-content/themes/argon/tests/test-wp-markdown-format.html
+2. 查看控制台日志,确认所有测试用例都能正确提取和渲染
+3. 在文章中使用推荐的标记方式:
...
+4. 如果还有问题,查看控制台的详细日志 + +推荐使用方式: +
+flowchart TD + A[开始] --> B[处理] + B --> C[结束] +
+ +注意事项: +- 强烈推荐使用 Argon 自定义标记,避免 WPMD 处理 +- HTML 注释标记适合需要隐藏标记的场景 +- 传统 Markdown 代码块仍然支持,但可能有嵌套问题 +- 所有标记方式都会自动解码 HTML 实体和转义字符 diff --git a/docs/mermaid-developer-guide.md b/docs/mermaid-developer-guide.md new file mode 100644 index 0000000..4023ada --- /dev/null +++ b/docs/mermaid-developer-guide.md @@ -0,0 +1,1230 @@ +# Mermaid 功能开发者文档 + +## 目录 + +1. [架构概述](#架构概述) +2. [PHP 函数参考](#php-函数参考) +3. [JavaScript API 参考](#javascript-api-参考) +4. [配置系统](#配置系统) +5. [扩展开发](#扩展开发) +6. [测试指南](#测试指南) + +--- + +## 架构概述 + +### 系统组成 + +Mermaid 功能由以下几个部分组成: + +``` +┌─────────────────────────────────────────┐ +│ WordPress 后台设置 │ +│ (settings.php) │ +└──────────────┬──────────────────────────┘ + │ + ├─> 配置管理 (functions.php) + │ ├─ argon_get_mermaid_option() + │ ├─ argon_update_mermaid_option() + │ └─ argon_validate_mermaid_settings() + │ + ├─> 库加载器 (functions.php) + │ ├─ argon_enqueue_mermaid_scripts() + │ ├─ argon_has_mermaid_content() + │ └─ argon_get_mermaid_library_url() + │ + ├─> 插件兼容层 (functions.php) + │ ├─ argon_detect_mermaid_plugins() + │ ├─ argon_is_mermaid_library_enqueued() + │ └─ argon_should_load_mermaid_library() + │ + └─> 前端渲染引擎 (argontheme.js) + ├─ MermaidRenderer.init() + ├─ MermaidRenderer.detectMermaidBlocks() + ├─ MermaidRenderer.renderChart() + └─ MermaidRenderer.handleThemeSwitch() +``` + +### 工作流程 + +```mermaid +flowchart TD + A[页面加载] --> B{检查是否启用} + B -->|否| Z[结束] + B -->|是| C[检测页面内容] + C --> D{包含 Mermaid?} + D -->|否| Z + D -->|是| E[检测插件] + E --> F{插件已加载?} + F -->|是| G[只提供样式] + F -->|否| H[加载 Mermaid 库] + H --> I[初始化配置] + G --> I + I --> J[检测代码块] + J --> K[渲染图表] + K --> L[监听主题切换] + L --> Z +``` + +--- + +## PHP 函数参考 + +### 配置管理函数 + +#### argon_get_mermaid_option() + +获取 Mermaid 配置选项。 + +**函数签名:** +```php +function argon_get_mermaid_option($option_name, $default = null) +``` + +**参数:** +- `$option_name` (string) - 配置选项名称,支持简短名称或完整名称 +- `$default` (mixed) - 默认值,当选项不存在时返回 + +**返回值:** +- (mixed) 配置选项值 + +**支持的选项名称:** +| 简短名称 | 完整名称 | 说明 | +|---------|---------|------| +| `enabled` | `argon_enable_mermaid` | 是否启用 Mermaid | +| `cdn_source` | `argon_mermaid_cdn_source` | CDN 来源 | +| `custom_cdn_url` | `argon_mermaid_cdn_custom_url` | 自定义 CDN URL | +| `theme` | `argon_mermaid_theme` | 图表主题 | +| `use_local` | `argon_mermaid_use_local` | 使用本地镜像 | +| `debug_mode` | `argon_mermaid_debug_mode` | 调试模式 | + +**示例:** +```php +// 使用简短名称 +$enabled = argon_get_mermaid_option('enabled', false); + +// 使用完整名称 +$theme = argon_get_mermaid_option('argon_mermaid_theme', 'auto'); + +// 获取不存在的选项,返回默认值 +$custom = argon_get_mermaid_option('custom_option', 'default_value'); +``` + +--- + +#### argon_update_mermaid_option() + +保存 Mermaid 配置选项。 + +**函数签名:** +```php +function argon_update_mermaid_option($option_name, $value) +``` + +**参数:** +- `$option_name` (string) - 配置选项名称 +- `$value` (mixed) - 配置选项值 + +**返回值:** +- (bool) 是否保存成功 + +**示例:** +```php +// 启用 Mermaid +argon_update_mermaid_option('enabled', true); + +// 设置主题 +argon_update_mermaid_option('theme', 'dark'); + +// 设置 CDN 来源 +argon_update_mermaid_option('cdn_source', 'jsdelivr'); +``` + +--- + +#### argon_validate_mermaid_cdn_url() + +验证 Mermaid CDN URL 格式。 + +**函数签名:** +```php +function argon_validate_mermaid_cdn_url($url) +``` + +**参数:** +- `$url` (string) - CDN URL + +**返回值:** +- (bool) 是否为有效的 CDN URL + +**验证规则:** +1. URL 不能为空 +2. 必须是有效的 URL 格式 +3. 必须以 `.js` 结尾 +4. 必须使用 `http://` 或 `https://` 协议 + +**示例:** +```php +// 有效的 URL +$valid = argon_validate_mermaid_cdn_url('https://cdn.example.com/mermaid.min.js'); +// 返回: true + +// 无效的 URL(不以 .js 结尾) +$invalid = argon_validate_mermaid_cdn_url('https://cdn.example.com/mermaid'); +// 返回: false +``` + +--- + +#### argon_get_mermaid_theme() + +获取当前主题模式对应的 Mermaid 主题。 + +**函数签名:** +```php +function argon_get_mermaid_theme() +``` + +**返回值:** +- (string) Mermaid 主题名称 + +**说明:** +- 如果配置为固定主题,直接返回配置的主题 +- 如果配置为 `auto`,在 PHP 端返回 `default`,实际切换在 JavaScript 中实现 + +**示例:** +```php +$theme = argon_get_mermaid_theme(); +// 返回: 'default', 'dark', 'forest', 'neutral' 之一 +``` + +--- + +### 库加载函数 + +#### argon_has_mermaid_content() + +检测页面内容是否包含 Mermaid 代码块。 + +**函数签名:** +```php +function argon_has_mermaid_content($content) +``` + +**参数:** +- `$content` (string) - 页面内容 + +**返回值:** +- (bool) 是否包含 Mermaid 代码块 + +**支持的格式:** +- `
` +- `
`
+- `
`
+- ``
+
+**示例:**
+```php
+global $post;
+if (argon_has_mermaid_content($post->post_content)) {
+    // 页面包含 Mermaid 代码块
+    echo '检测到 Mermaid 图表';
+}
+```
+
+---
+
+#### argon_get_mermaid_library_url()
+
+获取 Mermaid 库的 URL。
+
+**函数签名:**
+```php
+function argon_get_mermaid_library_url()
+```
+
+**返回值:**
+- (string) Mermaid 库 URL
+
+**说明:**
+- 根据配置返回对应的 CDN 或本地路径
+- 如果自定义 URL 无效,自动降级到 jsDelivr
+
+**示例:**
+```php
+$url = argon_get_mermaid_library_url();
+// 返回: 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js'
+```
+
+---
+
+#### argon_enqueue_mermaid_scripts()
+
+加载 Mermaid JavaScript 库。
+
+**函数签名:**
+```php
+function argon_enqueue_mermaid_scripts()
+```
+
+**说明:**
+- 在 `wp_enqueue_scripts` 钩子中调用
+- 只在启用 Mermaid 且页面包含代码块时加载
+- 自动检测插件,避免重复加载
+
+**钩子:**
+```php
+add_action('wp_enqueue_scripts', 'argon_enqueue_mermaid_scripts');
+```
+
+---
+
+### 插件兼容函数
+
+#### argon_detect_mermaid_plugins()
+
+检测已安装的 Mermaid 相关插件。
+
+**函数签名:**
+```php
+function argon_detect_mermaid_plugins()
+```
+
+**返回值:**
+- (array) 插件检测结果数组
+
+**返回格式:**
+```php
+[
+    'wp-githuber-md' => false,
+    'markdown-block' => false,
+    'code-syntax-block' => false,
+    'mermaid-loaded' => false
+]
+```
+
+**示例:**
+```php
+$plugins = argon_detect_mermaid_plugins();
+if ($plugins['wp-githuber-md']) {
+    echo 'WP Githuber MD 插件已安装';
+}
+```
+
+---
+
+#### argon_is_mermaid_library_enqueued()
+
+检查是否有插件已经加载了 Mermaid 库。
+
+**函数签名:**
+```php
+function argon_is_mermaid_library_enqueued()
+```
+
+**返回值:**
+- (bool) 是否已加载
+
+**说明:**
+- 检测常见的 Mermaid 脚本句柄
+- 包括:`mermaid`, `mermaid-js`, `githuber-mermaid`, `wp-mermaid`, `markdown-mermaid`
+
+**示例:**
+```php
+if (argon_is_mermaid_library_enqueued()) {
+    echo 'Mermaid 库已由其他来源加载';
+}
+```
+
+---
+
+#### argon_should_load_mermaid_library()
+
+判断是否应该加载 Mermaid 库。
+
+**函数签名:**
+```php
+function argon_should_load_mermaid_library()
+```
+
+**返回值:**
+- (bool) 是否应该加载
+
+**说明:**
+- 检测插件和已加载的库
+- 避免重复加载
+- 在调试模式下输出日志
+
+**示例:**
+```php
+if (argon_should_load_mermaid_library()) {
+    // 主题负责加载 Mermaid 库
+    wp_enqueue_script('mermaid', $url);
+}
+```
+
+---
+
+## JavaScript API 参考
+
+### MermaidRenderer 对象
+
+前端渲染引擎,负责检测和渲染 Mermaid 图表。
+
+#### 属性
+
+| 属性 | 类型 | 说明 |
+|------|------|------|
+| `initialized` | boolean | 是否已初始化 |
+| `rendered` | Set | 已渲染的图表 ID 集合 |
+| `config` | Object | 配置对象 |
+
+---
+
+#### init()
+
+初始化 Mermaid 配置并渲染所有图表。
+
+**函数签名:**
+```javascript
+MermaidRenderer.init()
+```
+
+**返回值:**
+- (boolean) 是否初始化成功
+
+**说明:**
+- 检查 Mermaid 库是否已加载
+- 初始化 Mermaid 配置
+- 渲染所有图表
+- 监听主题切换事件
+
+**示例:**
+```javascript
+// 页面加载完成后初始化
+document.addEventListener('DOMContentLoaded', function() {
+    if (typeof MermaidRenderer !== 'undefined') {
+        MermaidRenderer.init();
+    }
+});
+```
+
+---
+
+#### detectMermaidBlocks()
+
+检测所有 Mermaid 代码块。
+
+**函数签名:**
+```javascript
+MermaidRenderer.detectMermaidBlocks()
+```
+
+**返回值:**
+- (Array) Mermaid 代码块元素数组
+
+**检测规则:**
+1. `div.mermaid` - 标准格式
+2. `pre code.language-mermaid` - Markdown 格式
+3. `pre[data-lang="mermaid"]` - 自定义属性格式
+4. `code.mermaid` - 简化格式
+
+**示例:**
+```javascript
+const blocks = MermaidRenderer.detectMermaidBlocks();
+console.log(`检测到 ${blocks.length} 个 Mermaid 代码块`);
+```
+
+---
+
+#### extractMermaidCode()
+
+提取代码块内容。
+
+**函数签名:**
+```javascript
+MermaidRenderer.extractMermaidCode(element)
+```
+
+**参数:**
+- `element` (HTMLElement) - 代码块元素
+
+**返回值:**
+- (string) Mermaid 代码
+
+**说明:**
+- 支持多种代码块格式
+- 自动处理 WP-Markdown 生成的 `document.write()` 格式
+- 解码转义字符(`\n`, `\"`, `\'`)
+
+**示例:**
+```javascript
+const element = document.querySelector('.mermaid');
+const code = MermaidRenderer.extractMermaidCode(element);
+console.log(code);
+```
+
+---
+
+#### renderChart()
+
+渲染单个图表。
+
+**函数签名:**
+```javascript
+MermaidRenderer.renderChart(element, index)
+```
+
+**参数:**
+- `element` (HTMLElement) - 代码块元素
+- `index` (number) - 图表索引
+
+**说明:**
+- 生成唯一的图表 ID
+- 避免重复渲染
+- 渲染成功后替换原始代码块
+- 渲染失败时显示错误提示
+
+**示例:**
+```javascript
+const blocks = MermaidRenderer.detectMermaidBlocks();
+blocks.forEach((block, index) => {
+    MermaidRenderer.renderChart(block, index);
+});
+```
+
+---
+
+#### handleThemeSwitch()
+
+处理主题切换事件。
+
+**函数签名:**
+```javascript
+MermaidRenderer.handleThemeSwitch()
+```
+
+**说明:**
+- 检测页面主题变化
+- 重新渲染所有图表
+- 使用新的主题配置
+
+**示例:**
+```javascript
+// 监听主题切换
+document.addEventListener('themeChanged', function() {
+    MermaidRenderer.handleThemeSwitch();
+});
+```
+
+---
+
+### 配置对象
+
+#### argonMermaidConfig
+
+全局配置对象,由 PHP 传递到前端。
+
+**属性:**
+```javascript
+{
+    enabled: true,                    // 是否启用
+    theme: 'auto',                    // 图表主题
+    debugMode: false,                 // 调试模式
+    fallbackUrls: [],                 // 备用 CDN URL 列表
+    libraryLoadedByPlugin: false      // 库是否由插件加载
+}
+```
+
+**访问方式:**
+```javascript
+if (window.argonMermaidConfig) {
+    console.log('Mermaid 已启用:', argonMermaidConfig.enabled);
+    console.log('当前主题:', argonMermaidConfig.theme);
+}
+```
+
+---
+
+## 配置系统
+
+### 配置选项
+
+| 选项名称 | 类型 | 默认值 | 说明 |
+|---------|------|--------|------|
+| `argon_enable_mermaid` | boolean | false | 是否启用 Mermaid |
+| `argon_mermaid_cdn_source` | string | 'jsdelivr' | CDN 来源 |
+| `argon_mermaid_cdn_custom_url` | string | '' | 自定义 CDN URL |
+| `argon_mermaid_theme` | string | 'auto' | 图表主题 |
+| `argon_mermaid_use_local` | boolean | false | 使用本地镜像 |
+| `argon_mermaid_debug_mode` | boolean | false | 调试模式 |
+
+### CDN 来源选项
+
+| 值 | 说明 | URL |
+|----|------|-----|
+| `jsdelivr` | jsDelivr CDN | `https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.min.js` |
+| `unpkg` | unpkg CDN | `https://unpkg.com/mermaid@10/dist/mermaid.min.js` |
+| `custom` | 自定义 CDN | 用户指定的 URL |
+| `local` | 本地文件 | `{theme_url}/assets/vendor/mermaid/mermaid.min.js` |
+
+### 主题选项
+
+| 值 | 说明 |
+|----|------|
+| `auto` | 自动切换(跟随页面主题) |
+| `default` | 默认主题(浅色) |
+| `dark` | 深色主题 |
+| `forest` | 森林主题(绿色) |
+| `neutral` | 中性主题(灰色) |
+
+---
+
+## 扩展开发
+
+### 添加新的图表类型支持
+
+Mermaid 支持的所有图表类型都已自动支持,无需额外配置。
+
+### 自定义样式
+
+在 `style.css` 中添加自定义样式:
+
+```css
+/* 自定义 Mermaid 容器样式 */
+.mermaid-container {
+    background: #f5f5f5;
+    padding: 20px;
+    border-radius: 8px;
+    box-shadow: 0 2px 8px rgba(0,0,0,0.1);
+}
+
+/* 自定义错误提示样式 */
+.mermaid-error-container {
+    background: #fff3cd;
+    border-left: 4px solid #ffc107;
+    padding: 15px;
+    border-radius: 4px;
+}
+
+/* 夜间模式样式 */
+html.darkmode .mermaid-container {
+    background: #2d2d2d;
+}
+```
+
+### 添加自定义钩子
+
+在 `functions.php` 中添加钩子:
+
+```php
+/**
+ * Mermaid 渲染前钩子
+ * 
+ * @param string $content 页面内容
+ * @return string 修改后的内容
+ */
+function my_custom_mermaid_before_render($content) {
+    // 自定义处理逻辑
+    return $content;
+}
+add_filter('argon_mermaid_before_render', 'my_custom_mermaid_before_render');
+
+/**
+ * Mermaid 渲染后钩子
+ * 
+ * @param string $content 渲染后的内容
+ * @return string 修改后的内容
+ */
+function my_custom_mermaid_after_render($content) {
+    // 自定义处理逻辑
+    return $content;
+}
+add_filter('argon_mermaid_after_render', 'my_custom_mermaid_after_render');
+```
+
+---
+
+## 测试指南
+
+### 单元测试
+
+运行 PHP 单元测试:
+
+```bash
+cd tests
+php run-mermaid-config-tests.php
+```
+
+### 测试用例
+
+测试文件位于 `tests/` 目录:
+
+- `test-mermaid-config.php` - 配置管理测试
+- `test-mermaid-loader.php` - 库加载测试
+- `test-mermaid-fallback.php` - CDN 降级测试
+- `test-wp-markdown-format.html` - WP-Markdown 格式测试
+
+### 手动测试
+
+1. **基础功能测试**
+   - 启用 Mermaid 支持
+   - 创建包含 Mermaid 代码的文章
+   - 验证图表是否正确渲染
+
+2. **主题切换测试**
+   - 切换页面主题(日间/夜间)
+   - 验证图表主题是否自动切换
+
+3. **CDN 降级测试**
+   - 模拟 CDN 加载失败
+   - 验证是否自动尝试备用 CDN
+
+4. **插件兼容测试**
+   - 安装 Mermaid 相关插件
+   - 验证是否正确检测并避免冲突
+
+5. **错误处理测试**
+   - 输入错误的 Mermaid 代码
+   - 验证错误提示是否友好
+
+---
+
+## 调试技巧
+
+### 启用调试模式
+
+在主题设置中启用调试模式,查看详细日志:
+
+```javascript
+[Argon Mermaid] Mermaid 配置初始化成功 {theme: "default"}
+[Argon Mermaid] 检测到 3 个 Mermaid 代码块
+[Argon Mermaid] 渲染图表 #mermaid-chart-1234567890-0
+[Argon Mermaid] 图表渲染成功
+```
+
+### 浏览器控制台
+
+打开浏览器开发者工具(F12),查看:
+
+1. **控制台日志** - 查看 Mermaid 相关日志
+2. **网络请求** - 查看 CDN 加载状态
+3. **元素检查** - 查看渲染后的 SVG 结构
+
+### PHP 错误日志
+
+在 `wp-config.php` 中启用调试:
+
+```php
+define('WP_DEBUG', true);
+define('WP_DEBUG_LOG', true);
+define('WP_DEBUG_DISPLAY', false);
+```
+
+查看日志文件:`wp-content/debug.log`
+
+---
+
+## 性能优化
+
+### 按需加载
+
+主题已实现按需加载,只在包含 Mermaid 代码的页面加载库。
+
+### 异步加载
+
+Mermaid 库使用 `async` 属性异步加载,不阻塞页面渲染。
+
+### CDN 缓存
+
+使用 CDN 加速加载,浏览器会自动缓存库文件。
+
+### 避免重复渲染
+
+使用 `rendered` Set 记录已渲染的图表,避免重复渲染。
+
+---
+
+## 贡献指南
+
+### 代码规范
+
+遵循 Argon 主题的代码规范:
+
+- **PHP**: 遵循 WordPress Coding Standards
+- **JavaScript**: 使用 Tab 缩进,严格相等运算符
+- **CSS**: 使用 Tab 缩进,属性独占一行
+
+### 提交规范
+
+- **功能添加**: `feat: 添加 XXX 功能`
+- **Bug 修复**: `fix: 修复 XXX 问题`
+- **文档更新**: `docs: 更新 XXX 文档`
+
+### 测试要求
+
+- 添加新功能时,必须添加对应的测试用例
+- 修复 Bug 时,必须添加回归测试
+- 所有测试必须通过
+
+---
+
+## 相关资源
+
+- [Mermaid 官方文档](https://mermaid.js.org/)
+- [WordPress 开发文档](https://developer.wordpress.org/)
+- [Argon 主题 GitHub](https://github.com/solstice23/argon-theme)
+
+---
+
+**最后更新:** 2024-01-22  
+**文档版本:** 1.0.0
+
+
+---
+
+## 代码块魔改技术
+
+### 概述
+
+代码块魔改是一种在代码高亮之前拦截并转换 Mermaid 代码块的技术,使得标准 Markdown 代码块 (` ```mermaid `) 能够正确渲染为 Mermaid 图表,而不被代码高亮处理。
+
+### 实现原理
+
+#### 1. 执行顺序
+
+```
+页面加载/PJAX切换
+    ↓
+highlightJsRender() 调用
+    ↓
+convertMermaidCodeblocks() 执行 ← 【拦截阶段】
+    ↓
+代码高亮处理其他代码块
+    ↓
+MermaidRenderer.detectMermaidBlocks() ← 【检测阶段】
+    ↓
+MermaidRenderer.renderChart() ← 【渲染阶段】
+```
+
+#### 2. 核心函数
+
+**convertMermaidCodeblocks()**
+
+在代码高亮之前转换 Mermaid 代码块。
+
+**位置:** `argontheme.js` 第 3942 行之前
+
+**功能:**
+- 使用多个选择器查找 mermaid 代码块
+- 提取纯文本代码(使用 `textContent`)
+- 创建 `
` 容器 +- 替换原始代码块元素 +- 添加 `data-processed="true"` 标记防止重复处理 + +**代码示例:** +```javascript +function convertMermaidCodeblocks(){ + // 支持多种代码块格式 + const selectors = [ + 'pre > code.language-mermaid', // 标准 Markdown 格式(最常见) + 'pre > code.mermaid', // 简化格式 + 'code.language-mermaid', // 无 pre 包裹 + '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'; + }); + }); + + if (processedCount > 0 && typeof console !== 'undefined' && console.log) { + console.log('[Mermaid] 转换了 ' + processedCount + ' 个代码块'); + } +} +``` + +#### 3. 集成点 + +**集成点 1:highlightJsRender() 函数** + +在函数开始处调用 `convertMermaidCodeblocks()`: + +```javascript +function highlightJsRender(){ + // 在代码高亮之前,先处理 Mermaid 代码块 + convertMermaidCodeblocks(); + + if (typeof(hljs) == "undefined"){ + return; + } + // ... 原有的代码高亮逻辑 +} +``` + +**集成点 2:detectMermaidBlocks() 函数** + +在 selectors 数组中添加新的容器类型: + +```javascript +const selectors = [ + 'div.mermaid-shortcode', // Shortcode 格式(推荐) + 'div.mermaid-from-codeblock', // 代码块魔改格式(新增) + 'div.mermaid', // 标准格式 + 'pre code.language-mermaid', // Markdown 格式(降级) + 'pre[data-lang="mermaid"]', // 自定义属性格式 + 'code.mermaid' // 简化格式 +]; +``` + +**集成点 3:extractMermaidCode() 函数** + +添加对新容器类型的处理: + +```javascript +// 处理代码块魔改格式(新增) +else if (element.classList.contains('mermaid-from-codeblock')) { + code = element.textContent; + this.logDebug('从代码块魔改格式提取代码'); +} +``` + +### 技术细节 + +#### 选择器优先级 + +选择器按以下优先级匹配: + +1. `pre > code.language-mermaid` - 标准 Markdown 格式(最常见) +2. `pre > code.mermaid` - 简化格式 +3. `code.language-mermaid` - 无 pre 包裹 +4. `pre[data-lang="mermaid"]` - 自定义属性格式 + +#### 重复处理防护 + +使用 `data-mermaid-processed` 属性标记已处理的元素: + +```javascript +if (element.dataset.mermaidProcessed) { + return; // 跳过已处理的元素 +} +// ... 处理逻辑 +element.dataset.mermaidProcessed = 'true'; +``` + +这样可以: +- 避免 PJAX 切换时重复处理 +- 防止多次调用导致的错误 +- 提高性能 + +#### 代码提取 + +使用 `textContent` 而非 `innerHTML`: + +```javascript +let code = element.textContent.trim(); +``` + +**优势:** +- 获取纯文本,避免 HTML 实体 +- 防止 XSS 攻击 +- 保持原始内容不变 + +#### 容器创建 + +创建新的 div 容器: + +```javascript +const container = document.createElement('div'); +container.className = 'mermaid-from-codeblock'; +container.textContent = code; +container.dataset.processed = 'true'; +``` + +**属性说明:** +- `class="mermaid-from-codeblock"` - 标识来源于代码块 +- `data-processed="true"` - 标记已处理 +- `textContent` - 纯文本内容(不使用 `innerHTML`) + +#### 元素替换 + +优先替换整个 `
` 元素:
+
+```javascript
+const targetElement = element.closest('pre') || element;
+if (targetElement.parentNode) {
+	targetElement.parentNode.replaceChild(container, targetElement);
+}
+```
+
+**逻辑:**
+- 如果代码块在 `
` 中,替换整个 `
` 元素
+- 如果没有 `
` 包裹,替换 `` 元素
+- 保留原始位置和上下文
+
+### PJAX 兼容性
+
+代码块转换自动支持 PJAX,因为:
+
+1. `highlightJsRender()` 已在 PJAX 回调中调用
+2. `convertMermaidCodeblocks()` 在 `highlightJsRender()` 开始处执行
+3. 使用 `data-processed` 属性防止重复处理
+
+**PJAX 回调链:**
+```javascript
+$(document).on('pjax:complete', function() {
+	// ... 其他初始化
+	try { highlightJsRender(); } catch (err) { ... }  // 包含代码块转换
+	// ... 其他初始化
+});
+```
+
+### 性能优化
+
+#### 1. 使用原生 JavaScript
+
+```javascript
+document.querySelectorAll(selector)  // 而非 $(selector)
+```
+
+**理由:** 原生方法性能更好,减少 jQuery 开销
+
+#### 2. 提前返回
+
+```javascript
+if (element.dataset.mermaidProcessed) {
+	return;  // 提前返回,避免不必要的处理
+}
+```
+
+**理由:** 减少重复处理,提高效率
+
+#### 3. 批量处理
+
+```javascript
+selectors.forEach(selector => {
+	document.querySelectorAll(selector).forEach(element => {
+		// 处理逻辑
+	});
+});
+```
+
+**理由:** 一次性查找所有元素,减少 DOM 查询次数
+
+#### 4. 最小化 DOM 操作
+
+```javascript
+const container = document.createElement('div');
+container.className = 'mermaid-from-codeblock';
+container.textContent = code;
+container.dataset.processed = 'true';
+targetElement.parentNode.replaceChild(container, targetElement);
+```
+
+**理由:** 一次性创建和替换,减少重排和重绘
+
+### 安全性
+
+#### XSS 防护
+
+使用 `textContent` 而非 `innerHTML`:
+
+```javascript
+container.textContent = code;  // 安全
+// container.innerHTML = code;  // 不安全
+```
+
+**理由:** `textContent` 会自动转义 HTML,防止 XSS 攻击
+
+#### 代码来源验证
+
+```javascript
+let code = element.textContent.trim();
+if (!code) {
+	return;  // 拒绝空代码
+}
+```
+
+**理由:** 避免处理恶意或无效的代码块
+
+### 错误处理
+
+#### 空代码检查
+
+```javascript
+let code = element.textContent.trim();
+if (!code) {
+	return; // 跳过空代码块
+}
+```
+
+**理由:** 避免创建空容器,减少不必要的 DOM 操作
+
+#### Try-Catch 包裹
+
+```javascript
+try {
+	convertMermaidCodeblocks();
+} catch (err) {
+	console.error('Mermaid 代码块转换失败:', err);
+}
+```
+
+**理由:** 捕获异常,不中断其他代码块的处理
+
+#### 降级支持
+
+如果代码块转换失败,仍可通过降级选择器检测:
+
+```javascript
+'pre code.language-mermaid'  // 降级选择器
+```
+
+**理由:** 确保即使转换失败,仍能渲染
+
+### 扩展方式
+
+#### 添加新的选择器
+
+在 `selectors` 数组中添加新的选择器:
+
+```javascript
+const selectors = [
+	'pre > code.language-mermaid',
+	'pre > code.mermaid',
+	'code.language-mermaid',
+	'pre[data-lang="mermaid"]',
+	'your-custom-selector'  // 添加自定义选择器
+];
+```
+
+#### 自定义容器类名
+
+修改容器类名:
+
+```javascript
+container.className = 'your-custom-class';
+```
+
+然后在 `detectMermaidBlocks()` 中添加对应的选择器:
+
+```javascript
+const selectors = [
+	'div.mermaid-shortcode',
+	'div.your-custom-class',  // 添加自定义类名
+	'div.mermaid',
+	// ...
+];
+```
+
+### 调试技巧
+
+#### 1. 启用调试日志
+
+在 `convertMermaidCodeblocks()` 中添加日志:
+
+```javascript
+console.log('[Mermaid] 找到代码块:', element);
+console.log('[Mermaid] 提取的代码:', code);
+console.log('[Mermaid] 创建的容器:', container);
+```
+
+#### 2. 检查转换结果
+
+在浏览器控制台中检查:
+
+```javascript
+// 查看所有转换后的容器
+document.querySelectorAll('.mermaid-from-codeblock')
+
+// 查看容器内容
+document.querySelectorAll('.mermaid-from-codeblock').forEach(el => {
+	console.log(el.textContent);
+});
+```
+
+#### 3. 验证执行顺序
+
+在关键位置添加日志:
+
+```javascript
+function highlightJsRender(){
+	console.log('[1] highlightJsRender 开始');
+	convertMermaidCodeblocks();
+	console.log('[2] convertMermaidCodeblocks 完成');
+	// ... 代码高亮逻辑
+	console.log('[3] 代码高亮完成');
+}
+```
+
+### 测试用例
+
+参见 `tests/test-codeblock-magic.html` 文件,包含以下测试:
+
+1. 标准 Markdown 格式
+2. 多个代码块(批量处理)
+3. 特殊字符保留
+4. 空代码块(边界情况)
+5. 多行代码块(换行符保留)
+6. 简化格式
+7. 无 pre 包裹
+8. 自定义属性格式
+9. 复杂图表
+
+### 常见问题
+
+#### Q: 为什么要在代码高亮之前拦截?
+
+A: 因为代码高亮会:
+- 添加行号和控制按钮
+- 转换特殊字符(`-->` → `–>`)
+- 添加额外的 HTML 结构
+- 干扰 Mermaid 渲染
+
+#### Q: 为什么使用 `textContent` 而不是 `innerHTML`?
+
+A: 因为:
+- `textContent` 获取纯文本,避免 HTML 实体
+- 防止 XSS 攻击
+- 保持原始内容不变
+
+#### Q: 如何确保 PJAX 兼容性?
+
+A: 通过:
+- 在 `highlightJsRender()` 中调用(已在 PJAX 回调中)
+- 使用 `data-processed` 属性防止重复处理
+- 无需额外修改 PJAX 逻辑
+
+#### Q: 如何添加新的代码块格式?
+
+A: 在 `selectors` 数组中添加新的选择器,然后在 `detectMermaidBlocks()` 和 `extractMermaidCode()` 中添加对应的处理逻辑。
+
+---
diff --git a/docs/mermaid-faq.md b/docs/mermaid-faq.md
new file mode 100644
index 0000000..6e67c4e
--- /dev/null
+++ b/docs/mermaid-faq.md
@@ -0,0 +1,712 @@
+# Mermaid 图表常见问题解答 (FAQ)
+
+## 目录
+
+- [基础问题](#基础问题)
+- [配置问题](#配置问题)
+- [渲染问题](#渲染问题)
+- [兼容性问题](#兼容性问题)
+- [性能问题](#性能问题)
+- [高级问题](#高级问题)
+
+---
+
+## 基础问题
+
+### Q1: 什么是 Mermaid?
+
+**A:** Mermaid 是一个基于 JavaScript 的图表和图形工具,它使用类似 Markdown 的文本语法来创建和修改图表。您可以用简单的文本代码创建流程图、时序图、类图等多种专业图表。
+
+**优势:**
+- 📝 文本即代码,易于版本控制
+- 🎨 自动布局,无需手动调整
+- 🔄 易于修改和维护
+- 📱 响应式设计,自适应屏幕
+
+---
+
+### Q2: Argon 主题支持哪些 Mermaid 图表类型?
+
+**A:** Argon 主题支持 Mermaid 的所有主要图表类型:
+
+1. **流程图 (Flowchart)** - 展示流程和决策
+2. **时序图 (Sequence Diagram)** - 描述对象交互
+3. **类图 (Class Diagram)** - 展示类结构
+4. **状态图 (State Diagram)** - 表示状态转换
+5. **饼图 (Pie Chart)** - 显示数据占比
+6. **甘特图 (Gantt Chart)** - 项目进度管理
+7. **用户旅程图 (User Journey)** - 用户体验流程
+8. **Git 图 (Git Graph)** - 版本控制可视化
+
+详细示例请参考[用户指南](mermaid-user-guide.md#支持的图表类型)。
+
+---
+
+### Q3: 如何在文章中插入 Mermaid 图表?
+
+**A:** 有三种方式:
+
+**方式 1:标准 Markdown 代码块**(推荐)⭐
+````markdown
+三个反引号mermaid
+flowchart TD
+    A[开始] --> B[结束]
+三个反引号
+````
+
+**优点:**
+- ✅ 符合标准 Markdown 语法
+- ✅ 在所有 Markdown 编辑器中都能正确显示
+- ✅ 易于迁移到其他平台(GitHub、GitLab、Typora 等)
+- ✅ 主题自动拦截处理,避免代码高亮干扰
+
+**方式 2:Markdown 容器语法**(备选)
+````markdown
+::: mermaid
+flowchart TD
+    A[开始] --> B[结束]
+:::
+````
+
+**优点:**
+- ✅ 符合 Markdown 扩展规范(VuePress、Docusaurus 等)
+- ✅ 不会被 WP-Markdown 当作代码块处理
+
+**方式 3:Shortcode 格式**(兼容)
+```
+[mermaid]
+flowchart TD
+    A[开始] --> B[结束]
+[/mermaid]
+```
+
+**优点:**
+- ✅ WordPress 原生支持
+- ✅ 兼容性最好
+
+**缺点:**
+- ❌ 不符合 Markdown 标准
+- ❌ 在其他平台无法使用
+
+---
+
+### Q4: 为什么推荐使用标准 Markdown 代码块?
+
+**A:** 因为标准 Markdown 代码块 (` ```mermaid `) 是最通用的方式:
+
+- **GitHub** 使用这种语法
+- **GitLab** 使用这种语法
+- **Typora** 使用这种语法
+- **VS Code** 使用这种语法
+- **符合 CommonMark 规范**
+
+Argon 主题通过**代码块魔改**技术,在代码高亮之前拦截并转换 mermaid 代码块,因此:
+- ✅ 不会被代码高亮处理(无行号、无控制按钮)
+- ✅ 不会有字符转义问题(`-->` 保持不变)
+- ✅ 不会有嵌套结构问题
+- ✅ 完全符合标准 Markdown 语法
+- ✅ 易于迁移到其他平台
+```mermaid
+flowchart TD
+    A --> B
+```
+````
+
+**方式 2:HTML 标签**
+```html
+
+flowchart TD + A --> B +
+``` + +**注意:** 使用前需要在主题设置中启用 Mermaid 支持。 + +--- + +### Q4: 需要安装额外的插件吗? + +**A:** 不需要。Argon 主题内置了 Mermaid 支持,开箱即用。 + +**但是:** +- 如果您已经安装了 Mermaid 相关插件(如 WP Githuber MD),主题会自动检测并避免重复加载 +- 主题会智能判断是否需要加载 Mermaid 库 + +--- + +## 配置问题 + +### Q5: 如何启用 Mermaid 支持? + +**A:** 按照以下步骤操作: + +1. 登录 WordPress 后台 +2. 进入 **外观 → Argon 主题设置** +3. 找到 **Mermaid 图表** 分类 +4. 勾选 **"启用 Mermaid 支持"** +5. 点击 **"保存设置"** + +--- + +### Q6: 应该选择哪个 CDN 来源? + +**A:** 推荐选择: + +**首选:jsDelivr CDN** +- ✅ 全球 CDN,速度快 +- ✅ 稳定性高 +- ✅ 免费使用 + +**备选:unpkg CDN** +- 作为备用选项 + +**特殊情况:** +- **内网环境** → 使用本地文件 +- **特定版本需求** → 使用自定义 CDN +- **极致速度** → 下载本地文件 + +**主题优势:** 即使主 CDN 失败,主题会自动尝试备用 CDN,确保可用性。 + +--- + +### Q7: 如何使用自定义 CDN? + +**A:** 步骤如下: + +1. 在 **CDN 来源** 中选择 **"自定义 CDN 地址"** +2. 在 **自定义 CDN 地址** 输入框中填入完整的 URL +3. 保存设置 + +**URL 格式要求:** +- 必须是有效的 URL +- 必须以 `.js` 结尾 +- 必须使用 `http://` 或 `https://` 协议 + +**示例:** +``` +https://cdn.example.com/mermaid@10.0.0/mermaid.min.js +``` + +--- + +### Q8: 图表主题应该选择哪个? + +**A:** 推荐选择 **"自动切换"**。 + +**原因:** +- 自动跟随页面的日间/夜间模式 +- 日间模式使用浅色主题 +- 夜间模式使用深色主题 +- 用户体验最佳 + +**其他选项:** +- **默认主题** - 固定使用浅色 +- **深色主题** - 固定使用深色 +- **森林主题** - 绿色主题 +- **中性主题** - 灰色主题 + +--- + +### Q9: 什么时候需要启用调试模式? + +**A:** 在以下情况下启用: + +1. **图表不显示** - 查看是否有加载错误 +2. **渲染失败** - 查看详细的错误信息 +3. **主题切换异常** - 检查主题切换逻辑 +4. **CDN 加载问题** - 查看 CDN 加载状态 +5. **开发测试** - 开发新功能时调试 + +**如何使用:** +1. 启用调试模式 +2. 打开浏览器开发者工具(F12) +3. 切换到"控制台"标签 +4. 查看以 `[Argon Mermaid]` 开头的日志 + +**注意:** 生产环境建议关闭调试模式。 + +--- + +## 渲染问题 + +### Q10: 图表不显示,只显示代码怎么办? + +**A:** 按以下步骤排查: + +**步骤 1:检查是否启用** +- 确认主题设置中已启用 Mermaid 支持 + +**步骤 2:检查代码格式** +- 确认使用了正确的代码块格式 +- 检查是否有语法错误 + +**步骤 3:检查浏览器控制台** +- 按 F12 打开开发者工具 +- 查看是否有 JavaScript 错误 + +**步骤 4:启用调试模式** +- 在主题设置中启用调试模式 +- 查看详细的日志信息 + +**步骤 5:验证代码** +- 访问 [Mermaid Live Editor](https://mermaid.live/) +- 粘贴代码验证语法是否正确 + +--- + +### Q11: 图表显示"渲染失败"错误? + +**A:** 这通常是代码语法错误导致的。 + +**解决方法:** + +1. **查看错误详情** + - 点击错误提示中的"查看原始代码" + - 查看错误类型和错误信息 + +2. **常见语法错误:** + - 缺少必要的关键字 + - 箭头符号错误 + - 节点 ID 重复 + - 引号不匹配 + - 缩进不正确 + +3. **使用在线编辑器验证** + - 访问 [Mermaid Live Editor](https://mermaid.live/) + - 粘贴代码并查看错误提示 + - 根据提示修正语法 + +4. **参考官方文档** + - [Mermaid 语法参考](https://mermaid.js.org/intro/syntax-reference.html) + - 查看对应图表类型的语法规则 + +--- + +### Q12: 图表在夜间模式下看不清? + +**A:** 这是主题配置问题。 + +**解决方法:** + +1. 进入 **主题设置 → Mermaid 图表 → 外观设置** +2. 将 **图表主题** 设置为 **"自动切换"** +3. 保存设置 + +**原理:** +- 自动切换模式会检测页面主题 +- 日间模式使用浅色图表主题 +- 夜间模式使用深色图表主题 + +**如果仍有问题:** +- 清除浏览器缓存 +- 刷新页面 +- 检查是否有其他 CSS 冲突 + +--- + +### Q13: 图表太大,超出容器怎么办? + +**A:** Mermaid 图表会自动适应容器宽度,但如果图表过于复杂,可能会出现问题。 + +**解决方法:** + +**方法 1:简化图表** +- 减少节点数量 +- 拆分为多个小图表 +- 使用子图组织内容 + +**方法 2:自定义样式** +```css +.mermaid-container { + max-width: 100%; + overflow-x: auto; +} + +.mermaid-container svg { + max-width: 100%; + height: auto; +} +``` + +**方法 3:调整图表方向** +```mermaid +flowchart LR /* 横向布局 */ + A --> B +``` + +```mermaid +flowchart TD /* 纵向布局 */ + A --> B +``` + +--- + +### Q14: 如何在评论中使用 Mermaid? + +**A:** 评论中需要使用 HTML 格式。 + +**步骤:** + +1. **确保评论允许 HTML** + - 检查 WordPress 评论设置 + - 确认允许使用 HTML 标签 + +2. **使用 HTML 格式** +```html +
+flowchart LR + A --> B +
+``` + +3. **提交评论** + - 评论会在前台自动渲染为图表 + +**注意:** +- 不能使用 Markdown 代码块格式 +- 必须使用 `
` 包裹 +- 代码需要正确的换行格式 + +--- + +## 兼容性问题 + +### Q15: 与其他插件冲突怎么办? + +**A:** Argon 主题内置了智能兼容机制。 + +**自动检测的插件:** +- WP Githuber MD +- Markdown Block +- Code Syntax Block + +**兼容策略:** +1. 主题会自动检测已安装的 Mermaid 插件 +2. 如果检测到插件,主题只提供样式增强 +3. 避免重复加载 Mermaid 库 + +**查看兼容性状态:** +1. 进入 **主题设置 → Mermaid 图表 → 高级选项** +2. 查看 **插件兼容性检测** 部分 +3. 查看检测结果和建议 + +**如果仍有冲突:** +- 禁用主题的 Mermaid 支持,使用插件 +- 或禁用插件,使用主题的 Mermaid 支持 +- 不要同时启用多个 Mermaid 功能 + +--- + +### Q16: 检测到多个 Mermaid 插件怎么办? + +**A:** 这会导致重复加载和冲突。 + +**建议:** +1. **只保留一个** - 选择功能最完善的插件 +2. **或使用主题** - 禁用所有插件,使用主题的 Mermaid 支持 + +**如何选择:** +- **插件功能更多** → 禁用主题支持,使用插件 +- **主题集成更好** → 禁用插件,使用主题支持 +- **性能优先** → 使用主题支持(按需加载) + +--- + +### Q17: 在不同编辑器中如何使用? + +**A:** 不同编辑器使用方法略有不同。 + +**Gutenberg 编辑器:** +1. 添加"代码"块或"自定义 HTML"块 +2. 输入 Mermaid 代码 +3. 使用 `
` 包裹 + +**经典编辑器:** +1. 切换到"文本"模式 +2. 使用 HTML 格式 +3. 使用 `
` 包裹 + +**Markdown 编辑器(如 WP-Markdown):** +1. 使用代码块语法 +2. 指定语言为 `mermaid` +````markdown +```mermaid +flowchart TD + A --> B +``` +```` + +**WP Githuber MD:** +- 插件自带 Mermaid 支持 +- 主题会自动检测并避免冲突 +- 使用插件的 Mermaid 功能即可 + +--- + +## 性能问题 + +### Q18: Mermaid 会影响页面加载速度吗? + +**A:** 主题已做了充分的性能优化。 + +**优化措施:** + +1. **按需加载** + - 只在包含 Mermaid 代码的页面加载库 + - 没有 Mermaid 代码的页面不加载 + +2. **异步加载** + - Mermaid 库使用 async 属性异步加载 + - 不阻塞页面渲染 + +3. **CDN 加速** + - 使用全球 CDN 加速加载 + - 浏览器缓存减少重复加载 + +4. **智能检测** + - 检测插件是否已加载库 + - 避免重复加载 + +**实际影响:** +- Mermaid 库大小约 300KB(gzip 后约 100KB) +- 首次加载约 0.5-1 秒 +- 后续访问使用缓存,几乎无影响 + +--- + +### Q19: 一篇文章可以使用多少个图表? + +**A:** 技术上没有限制,但建议控制数量。 + +**建议:** +- **小型图表** - 不超过 10 个 +- **中型图表** - 不超过 5 个 +- **大型图表** - 不超过 3 个 + +**原因:** +- 过多图表会增加渲染时间 +- 影响页面性能 +- 用户体验下降 + +**优化建议:** +1. 合并相关图表 +2. 使用子图组织内容 +3. 复杂图表考虑使用图片替代 +4. 分页展示大量图表 + +--- + +### Q20: 如何优化 Mermaid 性能? + +**A:** 以下是一些优化建议: + +**1. 使用本地文件** +- 下载 Mermaid 库到主题目录 +- 启用"使用本地镜像" +- 减少网络请求 + +**2. 简化图表** +- 减少节点数量 +- 避免过于复杂的关系 +- 使用简洁的文本 + +**3. 启用浏览器缓存** +- CDN 文件会自动缓存 +- 减少重复加载 + +**4. 按需加载** +- 主题已自动实现 +- 只在需要时加载库 + +**5. 使用 CDN** +- 利用 CDN 的全球加速 +- 减少服务器负载 + +--- + +## 高级问题 + +### Q21: 如何自定义 Mermaid 样式? + +**A:** 可以通过 CSS 自定义样式。 + +**方法 1:使用主题自定义 CSS** +1. 进入 **外观 → 自定义 → 额外 CSS** +2. 添加自定义样式 + +**示例:** +```css +/* 自定义图表容器样式 */ +.mermaid-container { + background: #f5f5f5; + padding: 20px; + border-radius: 8px; + box-shadow: 0 2px 8px rgba(0,0,0,0.1); +} + +/* 自定义错误提示样式 */ +.mermaid-error-container { + background: #fff3cd; + border-left: 4px solid #ffc107; +} +``` + +**方法 2:修改主题文件** +- 编辑 `style.css` +- 在 Mermaid 相关部分添加样式 +- 不推荐(主题更新会覆盖) + +--- + +### Q22: 如何导出 Mermaid 图表为图片? + +**A:** 有多种方法可以导出图表。 + +**方法 1:使用 Mermaid Live Editor** +1. 访问 [Mermaid Live Editor](https://mermaid.live/) +2. 粘贴代码 +3. 点击"Export"按钮 +4. 选择 PNG 或 SVG 格式 + +**方法 2:浏览器截图** +1. 在浏览器中打开文章 +2. 使用截图工具截取图表 +3. Windows: Win + Shift + S +4. Mac: Cmd + Shift + 4 + +**方法 3:开发者工具** +1. 右键点击图表 → 检查元素 +2. 找到 SVG 元素 +3. 右键 → Copy → Copy outerHTML +4. 保存为 .svg 文件 +5. 使用工具转换为 PNG + +**方法 4:使用插件** +- 安装浏览器截图插件 +- 如 Awesome Screenshot +- 直接截取并保存 + +--- + +### Q23: 如何在 Mermaid 代码中使用中文? + +**A:** Mermaid 完全支持中文,直接使用即可。 + +**示例:** +```mermaid +flowchart TD + 开始([开始]) --> 处理[处理数据] + 处理 --> 判断{是否成功?} + 判断 -->|是| 成功([成功]) + 判断 -->|否| 失败([失败]) +``` + +**注意事项:** +1. **引号问题** + - 如果文本包含特殊字符,使用引号包裹 + - `A["包含特殊字符的文本"]` + +2. **编码问题** + - 确保文件编码为 UTF-8 + - WordPress 默认使用 UTF-8 + +3. **字体问题** + - 确保浏览器支持中文字体 + - 现代浏览器都支持 + +--- + +### Q24: 如何在 Mermaid 中添加链接? + +**A:** Mermaid 支持为节点添加链接。 + +**语法:** +```mermaid +flowchart TD + A[节点 A] + B[节点 B] + A --> B + click A "https://example.com" "点击访问" + click B "https://example.com" _blank +``` + +**参数说明:** +- 第一个参数:节点 ID +- 第二个参数:链接 URL +- 第三个参数:提示文本或打开方式 + - `"提示文本"` - 鼠标悬停提示 + - `_blank` - 新标签页打开 + - `_self` - 当前标签页打开 + +--- + +### Q25: 如何使用 Mermaid 的高级功能? + +**A:** Mermaid 支持许多高级功能。 + +**1. 子图 (Subgraph)** +```mermaid +flowchart TD + subgraph 输入阶段 + A[接收] --> B[验证] + end + subgraph 处理阶段 + B --> C[处理] + end +``` + +**2. 样式定义** +```mermaid +flowchart TD + A[节点 A] + B[节点 B] + A --> B + style A fill:#f9f,stroke:#333,stroke-width:4px + style B fill:#bbf,stroke:#333,stroke-width:2px +``` + +**3. 类样式** +```mermaid +flowchart TD + A[节点 A]:::someclass + B[节点 B]:::someclass + classDef someclass fill:#f96,stroke:#333 +``` + +**4. 注释** +```mermaid +%% 这是注释,不会显示 +flowchart TD + A --> B %% 行尾注释 +``` + +**更多功能:** +- 查看 [Mermaid 官方文档](https://mermaid.js.org/) +- 参考各图表类型的详细语法 + +--- + +## 获取更多帮助 + +### 官方资源 + +- 📚 [Mermaid 官方文档](https://mermaid.js.org/) +- 🎨 [Mermaid Live Editor](https://mermaid.live/) +- 💬 [Mermaid GitHub](https://github.com/mermaid-js/mermaid) + +### Argon 主题支持 + +- 🐛 [提交 Issue](https://github.com/solstice23/argon-theme/issues) +- 📖 [主题文档](https://github.com/solstice23/argon-theme) +- 💡 [用户指南](mermaid-user-guide.md) + +### 社区资源 + +- 🌐 WordPress 论坛 +- 💬 主题用户群 +- 📝 技术博客和教程 + +--- + +**最后更新:** 2024-01-22 +**文档版本:** 1.0.0 diff --git a/docs/mermaid-usage-guide.md b/docs/mermaid-usage-guide.md index 04f0468..8376994 100644 --- a/docs/mermaid-usage-guide.md +++ b/docs/mermaid-usage-guide.md @@ -2,7 +2,30 @@ ## 推荐的标记方式 -### Markdown 容器语法(推荐)⭐ +### 1. 标准 Markdown 代码块(推荐)⭐ + +```markdown +三个反引号mermaid +flowchart TD + A[开始] --> B[处理] + B --> C[结束] +三个反引号 +``` + +**优点**: +- ✅ 符合标准 Markdown 语法 +- ✅ 在所有 Markdown 编辑器中都能正确显示 +- ✅ 支持语法高亮(编辑器层面) +- ✅ 易于迁移到其他平台(GitHub、GitLab、Typora 等) +- ✅ 主题自动拦截处理,避免代码高亮干扰 +- ✅ 支持所有 Mermaid 图表类型 + +**工作原理**: +- 主题在代码高亮之前拦截 mermaid 代码块 +- 自动转换为 Mermaid 渲染容器 +- 完全绕过代码高亮和 WordPress 格式化 + +### 2. Markdown 容器语法(备选) ```markdown ::: mermaid @@ -20,19 +43,41 @@ flowchart TD - ✅ 在纯文本编辑器中也很清晰 - ✅ 易于迁移到其他平台 -### 为什么使用容器语法? +### 3. Shortcode 格式(兼容) -**Markdown 容器语法** (`::: mermaid ... :::`) 是现代 Markdown 扩展的标准方式: +``` +[mermaid] +flowchart TD + A[开始] --> B[处理] + B --> C[结束] +[/mermaid] +``` -- **VuePress** 使用这种语法 -- **Docusaurus** 使用这种语法 -- **MkDocs** 使用类似语法 -- **符合 CommonMark 扩展规范** +**优点**: +- ✅ WordPress 原生支持 +- ✅ 不会被任何插件干扰 +- ✅ 兼容性最好 -这种语法不会被 WP-Markdown 插件当作代码块处理,因此: -- 不会被套上代码高亮窗口 +**缺点**: +- ❌ 不符合 Markdown 标准 +- ❌ 在其他平台无法使用 +- ❌ 编辑器中不显示为代码块 + +### 为什么推荐标准 Markdown 代码块? + +**标准 Markdown 代码块** (` ```mermaid `) 是最通用的方式: + +- **GitHub** 使用这种语法 +- **GitLab** 使用这种语法 +- **Typora** 使用这种语法 +- **VS Code** 使用这种语法 +- **符合 CommonMark 规范** + +Argon 主题通过**代码块魔改**技术,在代码高亮之前拦截并转换 mermaid 代码块,因此: +- 不会被代码高亮处理(无行号、无控制按钮) +- 不会有字符转义问题(`-->` 保持不变) - 不会有嵌套结构问题 -- 不会有字符转义问题 +- 完全符合标准 Markdown 语法 --- @@ -40,6 +85,17 @@ flowchart TD ### 流程图 +**标准 Markdown 代码块:** +```markdown +三个反引号mermaid +flowchart LR + A[用户] --> B{登录?} + B -->|是| C[显示首页] + B -->|否| D[跳转登录页] +三个反引号 +``` + +**容器语法:** ```markdown ::: mermaid flowchart LR @@ -52,18 +108,18 @@ flowchart LR ### 时序图 ```markdown -::: mermaid +三个反引号mermaid sequenceDiagram Alice->>Bob: Hello Bob! Bob-->>Alice: Hi Alice! Alice->>Bob: How are you? -::: +三个反引号 ``` ### 类图 ```markdown -::: mermaid +三个反引号mermaid classDiagram class Animal { +String name @@ -75,13 +131,13 @@ classDiagram +bark() } Animal <|-- Dog -::: +三个反引号 ``` ### 甘特图 ```markdown -::: mermaid +三个反引号mermaid gantt title 项目进度 dateFormat YYYY-MM-DD @@ -91,31 +147,31 @@ gantt section 开发 前端开发 :b1, after a2, 10d 后端开发 :b2, after a2, 12d -::: +三个反引号 ``` ### 状态图 ```markdown -::: mermaid +三个反引号mermaid stateDiagram-v2 [*] --> 待审核 待审核 --> 已通过: 审核通过 待审核 --> 已拒绝: 审核拒绝 已通过 --> [*] 已拒绝 --> [*] -::: +三个反引号 ``` ### 饼图 ```markdown -::: mermaid +三个反引号mermaid pie title 宠物分布 "狗" : 386 "猫" : 85 "兔子" : 15 -::: +三个反引号 ``` --- @@ -195,22 +251,30 @@ pie title 宠物分布 ## 最佳实践 -### 1. 使用容器语法 +### 1. 使用标准 Markdown 代码块 **推荐:** ```markdown +三个反引号mermaid +flowchart TD + A --> B +三个反引号 +``` + +**也可以使用容器语法:** +```markdown ::: mermaid flowchart TD A --> B ::: ``` -**不推荐:** +**不推荐(Shortcode):** ``` -三个反引号mermaid +[mermaid] flowchart TD A --> B -三个反引号 +[/mermaid] ``` ### 2. 避免特殊字符 @@ -252,19 +316,48 @@ flowchart TD Argon 主题支持以下格式(按优先级排序): -1. `::: mermaid ... :::` - Markdown 容器语法 ⭐(推荐) -2. `
` - 标准格式(WPMD 生成) -3. `
` - Markdown 格式
-4. `
` - 自定义属性格式
-5. `` - 简化格式
+1. ` ```mermaid ... ``` ` - 标准 Markdown 代码块 ⭐(推荐)
+2. `::: mermaid ... :::` - Markdown 容器语法(备选)
+3. `[mermaid]...[/mermaid]` - Shortcode 格式(兼容)
+4. `
` - 标准格式(WPMD 生成) +5. `
` - Markdown 格式(降级)
+6. `
` - 自定义属性格式
+7. `` - 简化格式
+
+### 代码块魔改技术
+
+**工作原理**:
+
+1. **拦截阶段**(在代码高亮之前)
+   - 查找所有 `
` 元素
+   - 提取纯文本代码(使用 `textContent`)
+   - 创建 `
` 容器 + - 替换原始代码块元素 + +2. **代码高亮阶段** + - 处理其他代码块 + - 跳过 mermaid 相关的元素 + +3. **Mermaid 渲染阶段** + - 检测所有 Mermaid 容器(包括新的 `mermaid-from-codeblock`) + - 提取代码并渲染为 SVG 图表 + +**优势**: +- ✅ 完全绕过代码高亮干扰 +- ✅ 特殊字符不被转换(`-->` 保持不变) +- ✅ 换行符正确保留 +- ✅ 支持 PJAX 页面切换 +- ✅ 性能无明显影响 ### 代码提取逻辑 1. **检测代码块** - CSS 选择器查找标准格式 - TreeWalker 查找容器语法 + - 代码块魔改:在代码高亮前拦截 2. **提取代码** + - 代码块魔改格式:直接提取 `textContent` - 容器语法:移除 `::: mermaid` 和 `:::` - WPMD 格式:正则提取 `document.write()` 内容 - 标准格式:直接提取文本内容 @@ -329,11 +422,16 @@ Argon 主题支持以下格式(按优先级排序): ## 更新日志 ### 2026-01-24 +- ✅ **新增代码块魔改支持**:支持标准 Markdown 代码块 (` ```mermaid `) +- ✅ 在代码高亮之前拦截并转换 mermaid 代码块 +- ✅ 完全绕过代码高亮和 WordPress 格式化 +- ✅ 特殊字符不被转换(`-->` 保持不变) +- ✅ 换行符正确保留 +- ✅ 支持 PJAX 页面切换 - ✅ 添加 Markdown 容器语法支持(`::: mermaid ... :::`) - ✅ 修复 WP-Markdown 格式的代码提取问题 - ✅ 改进正则表达式,支持多行代码 - ✅ 添加降级方案和详细日志 -- ✅ 简化标记方式,只保留容器语法作为推荐方式 - ✅ 修复代码高亮干扰 mermaid 渲染的问题(排除 mermaid 代码块) - ✅ 修复容器语法中空行导致内容被截断的问题 - ✅ 修复 WP-Markdown 的 document.write 重复输出问题 diff --git a/docs/mermaid-user-guide.md b/docs/mermaid-user-guide.md new file mode 100644 index 0000000..3aa0aeb --- /dev/null +++ b/docs/mermaid-user-guide.md @@ -0,0 +1,719 @@ +# Argon 主题 Mermaid 图表使用指南 + +## 目录 + +1. [功能简介](#功能简介) +2. [快速开始](#快速开始) +3. [支持的图表类型](#支持的图表类型) +4. [使用方法](#使用方法) +5. [主题设置](#主题设置) +6. [常见问题](#常见问题) +7. [最佳实践](#最佳实践) +8. [故障排除](#故障排除) + +--- + +## 功能简介 + +Argon 主题内置了 Mermaid 图表支持,让您可以在文章中轻松创建各种专业的图表,包括: + +- 📊 **流程图** - 展示业务流程和逻辑关系 +- 📈 **时序图** - 描述系统交互和时间顺序 +- 🏗️ **类图** - 展示面向对象的类结构 +- 📉 **状态图** - 表示状态机和状态转换 +- 🥧 **饼图** - 显示数据占比 +- 📅 **甘特图** - 项目进度管理 +- 🗺️ **用户旅程图** - 用户体验流程 +- 🌳 **Git 图** - 版本控制分支可视化 + +### 主要特性 + +✅ **零配置使用** - 开箱即用,无需额外插件 +✅ **自动主题切换** - 跟随页面日间/夜间模式 +✅ **智能加载** - 只在需要时加载库文件 +✅ **插件兼容** - 自动检测并避免重复加载 +✅ **错误提示** - 友好的错误信息和调试支持 +✅ **CDN 降级** - 多个 CDN 自动切换,确保可用性 + +--- + +## 快速开始 + +### 1. 启用 Mermaid 支持 + +进入 **WordPress 后台 → 外观 → Argon 主题设置 → Mermaid 图表**,勾选"启用 Mermaid 支持"。 + +### 2. 在文章中使用 + +在文章编辑器中,使用以下格式插入 Mermaid 代码: + +````markdown +```mermaid +flowchart TD + Start([开始]) --> Process[处理数据] + Process --> End([结束]) +``` +```` + +或使用 HTML 格式: + +```html +
+flowchart TD + Start([开始]) --> Process[处理数据] + Process --> End([结束]) +
+``` + +### 3. 发布并查看 + +保存文章后,在前台页面即可看到渲染后的图表。 + +--- + +## 支持的图表类型 + +### 1. 流程图 (Flowchart) + +展示流程和决策逻辑。 + +````markdown +```mermaid +flowchart TD + A[开始] --> B{判断条件} + B -->|是| C[执行操作 A] + B -->|否| D[执行操作 B] + C --> E[结束] + D --> E +``` +```` + +**节点形状:** +- `[文本]` - 矩形 +- `([文本])` - 圆角矩形 +- `{文本}` - 菱形(判断) +- `((文本))` - 圆形 +- `[[文本]]` - 子程序 + +### 2. 时序图 (Sequence Diagram) + +描述对象之间的交互顺序。 + +````markdown +```mermaid +sequenceDiagram + participant 用户 + participant 服务器 + participant 数据库 + + 用户->>服务器: 发送请求 + 服务器->>数据库: 查询数据 + 数据库-->>服务器: 返回结果 + 服务器-->>用户: 响应数据 +``` +```` + +**箭头类型:** +- `->` - 实线箭头 +- `-->` - 虚线箭头 +- `->>` - 实线箭头(带箭头) +- `-->>` - 虚线箭头(带箭头) + +### 3. 类图 (Class Diagram) + +展示面向对象的类结构。 + +````markdown +```mermaid +classDiagram + class Animal { + +String name + +int age + +makeSound() + } + class Dog { + +String breed + +bark() + } + class Cat { + +meow() + } + Animal <|-- Dog + Animal <|-- Cat +``` +```` + +### 4. 状态图 (State Diagram) + +表示状态机和状态转换。 + +````markdown +```mermaid +stateDiagram-v2 + [*] --> 待处理 + 待处理 --> 处理中: 开始处理 + 处理中 --> 已完成: 处理成功 + 处理中 --> 失败: 处理失败 + 失败 --> 待处理: 重试 + 已完成 --> [*] +``` +```` + +### 5. 饼图 (Pie Chart) + +显示数据占比。 + +````markdown +```mermaid +pie title 浏览器市场份额 + "Chrome" : 65 + "Safari" : 15 + "Firefox" : 10 + "Edge" : 7 + "其他" : 3 +``` +```` + +### 6. 甘特图 (Gantt Chart) + +项目进度管理。 + +````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 + section 测试阶段 + 功能测试 :c1, after b1, 5d +``` +```` + +### 7. 用户旅程图 (User Journey) + +描述用户体验流程。 + +````markdown +```mermaid +journey + title 用户购物旅程 + section 浏览商品 + 访问网站: 5: 用户 + 搜索商品: 3: 用户 + 查看详情: 4: 用户 + section 下单 + 加入购物车: 4: 用户 + 填写信息: 2: 用户 + 支付: 3: 用户 + section 收货 + 等待发货: 2: 用户 + 收到商品: 5: 用户 +``` +```` + +### 8. Git 图 (Git Graph) + +版本控制分支可视化。 + +````markdown +```mermaid +gitGraph + commit + commit + branch develop + checkout develop + commit + commit + checkout main + merge develop + commit +``` +```` + +--- + +## 使用方法 + +### 在 Markdown 编辑器中使用 + +如果您使用 Markdown 编辑器(如 WP-Markdown),直接使用代码块语法: + +````markdown +```mermaid +flowchart LR + A --> B + B --> C +``` +```` + +### 在 Gutenberg 编辑器中使用 + +1. 添加"代码"块或"自定义 HTML"块 +2. 输入 Mermaid 代码 +3. 使用 `
` 包裹 + +```html +
+flowchart LR + A --> B + B --> C +
+``` + +### 在经典编辑器中使用 + +切换到"文本"模式,使用 HTML 格式: + +```html +
+flowchart LR + A --> B + B --> C +
+``` + +--- + +## 主题设置 + +### 基本设置 + +#### 启用 Mermaid 支持 + +**位置:** Argon 主题设置 → Mermaid 图表 → 基本设置 + +勾选此选项以启用 Mermaid 图表渲染功能。 + +#### CDN 来源 + +选择 Mermaid 库的加载来源: + +- **jsDelivr CDN** (推荐) - 全球 CDN,速度快,稳定性高 +- **unpkg CDN** - 备用 CDN +- **自定义 CDN 地址** - 使用自己的 CDN 或镜像 +- **本地文件** - 使用主题目录中的本地文件 + +**建议:** 使用 jsDelivr CDN,主题会自动在多个 CDN 之间切换以确保可用性。 + +#### 自定义 CDN 地址 + +当选择"自定义 CDN 地址"时,输入完整的 Mermaid 库 URL。 + +**格式要求:** +- 必须是有效的 URL +- 必须以 `.js` 结尾 +- 必须使用 `http://` 或 `https://` 协议 + +**示例:** +``` +https://cdn.example.com/mermaid@10.0.0/mermaid.min.js +``` + +### 外观设置 + +#### 图表主题 + +选择 Mermaid 图表的配色主题: + +- **自动切换** (推荐) - 跟随页面日间/夜间模式自动切换 +- **默认主题** - 浅色主题,适合日间模式 +- **深色主题** - 深色主题,适合夜间模式 +- **森林主题** - 绿色主题 +- **中性主题** - 灰色主题 + +**建议:** 使用"自动切换",让图表主题与页面主题保持一致。 + +### 高级选项 + +#### 使用本地镜像 + +启用后,如果检测到主题目录中存在 Mermaid 库文件,将优先使用本地文件而不是 CDN。 + +**本地文件路径:** +``` +wp-content/themes/argon/assets/vendor/mermaid/mermaid.min.js +``` + +**适用场景:** +- 内网环境无法访问外部 CDN +- 需要使用特定版本的 Mermaid +- 追求极致的加载速度 + +#### 调试模式 + +启用后,将在浏览器控制台输出详细的 Mermaid 渲染日志。 + +**日志内容包括:** +- 初始化状态 +- 检测到的代码块数量 +- 渲染成功/失败信息 +- 主题切换记录 +- CDN 加载状态 + +**使用方法:** +1. 启用调试模式 +2. 打开浏览器开发者工具(F12) +3. 切换到"控制台"标签 +4. 查看以 `[Argon Mermaid]` 开头的日志 + +#### 插件兼容性检测 + +主题会自动检测已安装的 Mermaid 插件,避免重复加载库文件。 + +**支持的插件:** +- WP Githuber MD +- Markdown Block +- Code Syntax Block + +**兼容策略:** +- 如果检测到插件,主题将只提供样式增强 +- 如果未检测到插件,主题将负责加载 Mermaid 库 +- 如果检测到多个插件,会显示警告信息 + +--- + +## 常见问题 + +### Q1: 图表不显示,只显示代码? + +**可能原因:** +1. 未启用 Mermaid 支持 +2. 代码格式不正确 +3. JavaScript 加载失败 + +**解决方法:** +1. 检查主题设置中是否启用了 Mermaid 支持 +2. 确认代码格式正确(参考本文档示例) +3. 打开浏览器控制台查看是否有错误信息 +4. 启用调试模式查看详细日志 + +### Q2: 图表显示"渲染失败"错误? + +**可能原因:** +1. Mermaid 代码语法错误 +2. 使用了不支持的图表类型 +3. 代码格式不符合规范 + +**解决方法:** +1. 检查代码语法是否正确 +2. 使用 [Mermaid Live Editor](https://mermaid.live/) 验证代码 +3. 查看错误提示中的详细信息 +4. 参考本文档中的示例代码 + +### Q3: 图表在夜间模式下看不清? + +**解决方法:** +1. 进入主题设置 → Mermaid 图表 → 外观设置 +2. 将"图表主题"设置为"自动切换" +3. 图表会自动跟随页面主题切换 + +### Q4: CDN 加载失败怎么办? + +**主题已内置降级机制:** +1. 主 CDN 失败时,自动尝试备用 CDN +2. 所有 CDN 都失败时,显示友好的错误提示 + +**手动解决:** +1. 切换到其他 CDN 来源 +2. 使用自定义 CDN 地址 +3. 下载本地文件并启用"使用本地镜像" + +### Q5: 与其他插件冲突? + +**主题已内置兼容机制:** +- 自动检测已安装的 Mermaid 插件 +- 避免重复加载库文件 +- 只提供样式增强功能 + +**如果仍有冲突:** +1. 查看插件兼容性检测结果 +2. 禁用主题的 Mermaid 支持,使用插件 +3. 或禁用插件,使用主题的 Mermaid 支持 + +### Q6: 如何在评论中使用 Mermaid? + +**方法:** +1. 评论中使用 HTML 格式 +2. 使用 `
` 包裹代码 + +**示例:** +```html +
+flowchart LR + A --> B +
+``` + +**注意:** 需要确保评论允许 HTML 标签。 + +### Q7: 图表太大,超出容器? + +**解决方法:** +1. Mermaid 图表会自动适应容器宽度 +2. 如果图表过于复杂,考虑简化或拆分 +3. 使用 CSS 自定义样式调整大小 + +**自定义样式示例:** +```css +.mermaid-container { + max-width: 100%; + overflow-x: auto; +} +``` + +### Q8: 如何导出图表为图片? + +**方法 1:使用浏览器截图** +1. 在浏览器中打开文章 +2. 使用截图工具截取图表部分 + +**方法 2:使用 Mermaid Live Editor** +1. 访问 [Mermaid Live Editor](https://mermaid.live/) +2. 粘贴代码 +3. 点击"Export"导出为 PNG/SVG + +**方法 3:使用浏览器开发者工具** +1. 右键点击图表 → 检查元素 +2. 找到 SVG 元素 +3. 复制 SVG 代码或导出为图片 + +--- + +## 最佳实践 + +### 1. 代码格式规范 + +**推荐:** +```mermaid +flowchart TD + A[开始] --> B[处理] + B --> C[结束] +``` + +**不推荐:** +```mermaid +flowchart TD +A[开始]-->B[处理] +B-->C[结束] +``` + +**建议:** +- 使用缩进保持代码可读性 +- 箭头两侧添加空格 +- 每行一个语句 + +### 2. 节点命名 + +**推荐:** +```mermaid +flowchart TD + start([开始]) + process[处理数据] + decision{是否成功?} +``` + +**不推荐:** +```mermaid +flowchart TD + a([开始]) + b[处理数据] + c{是否成功?} +``` + +**建议:** +- 使用有意义的节点 ID +- 节点文本简洁明了 +- 避免使用特殊字符 + +### 3. 图表复杂度 + +**建议:** +- 单个图表不超过 20 个节点 +- 复杂流程拆分为多个图表 +- 使用子图组织相关节点 + +**示例:** +```mermaid +flowchart TD + subgraph 输入阶段 + A[接收数据] --> B[验证数据] + end + subgraph 处理阶段 + B --> C[处理数据] + C --> D[保存结果] + end +``` + +### 4. 性能优化 + +**建议:** +- 避免在一篇文章中使用过多图表(建议不超过 10 个) +- 复杂图表考虑使用图片替代 +- 启用 CDN 加速加载 + +### 5. 可访问性 + +**建议:** +- 为图表添加文字说明 +- 使用清晰的节点文本 +- 避免仅依赖颜色传达信息 + +**示例:** +```html +
+

以下是用户注册流程图:

+
+ flowchart TD + Start([用户访问注册页]) --> Input[填写信息] + Input --> Validate{验证信息} + Validate -->|通过| Register[注册成功] + Validate -->|失败| Input +
+
+``` + +### 6. 版本控制 + +**建议:** +- 在文章中记录 Mermaid 代码版本 +- 复杂图表保存源代码备份 +- 使用注释说明图表用途 + +**示例:** +```mermaid +%% 用户注册流程图 +%% 版本: 1.0 +%% 更新日期: 2024-01-20 +flowchart TD + Start --> End +``` + +--- + +## 故障排除 + +### 调试步骤 + +1. **启用调试模式** + - 进入主题设置 → Mermaid 图表 → 高级选项 + - 勾选"启用调试模式" + +2. **打开浏览器控制台** + - 按 F12 打开开发者工具 + - 切换到"控制台"标签 + +3. **查看日志信息** + - 查找以 `[Argon Mermaid]` 开头的日志 + - 记录错误信息和警告 + +4. **验证代码语法** + - 访问 [Mermaid Live Editor](https://mermaid.live/) + - 粘贴代码并检查是否有语法错误 + +5. **检查网络请求** + - 在开发者工具中切换到"网络"标签 + - 查看 Mermaid 库是否成功加载 + - 检查是否有 404 或其他错误 + +### 常见错误代码 + +#### 错误 1: Parse error on line X + +**原因:** Mermaid 代码语法错误 + +**解决:** +1. 检查代码语法是否正确 +2. 使用 Mermaid Live Editor 验证 +3. 参考官方文档修正语法 + +#### 错误 2: Mermaid 库未加载 + +**原因:** CDN 加载失败或被阻止 + +**解决:** +1. 检查网络连接 +2. 切换到其他 CDN 来源 +3. 使用本地文件 + +#### 错误 3: 主题切换失败 + +**原因:** 配置错误或 JavaScript 冲突 + +**解决:** +1. 检查主题设置是否正确 +2. 禁用其他可能冲突的插件 +3. 清除浏览器缓存 + +### 获取帮助 + +如果以上方法都无法解决问题,请: + +1. **收集信息:** + - WordPress 版本 + - Argon 主题版本 + - 浏览器类型和版本 + - 错误信息和日志 + - 问题复现步骤 + +2. **提交问题:** + - 访问 [Argon 主题 GitHub](https://github.com/solstice23/argon-theme/issues) + - 创建新 Issue + - 提供详细的问题描述和信息 + +3. **社区支持:** + - 访问主题官方论坛 + - 搜索类似问题 + - 向社区求助 + +--- + +## 相关资源 + +### 官方文档 + +- [Mermaid 官方文档](https://mermaid.js.org/) +- [Mermaid 语法参考](https://mermaid.js.org/intro/syntax-reference.html) +- [Mermaid Live Editor](https://mermaid.live/) + +### 教程和示例 + +- [Mermaid 快速入门](https://mermaid.js.org/intro/getting-started.html) +- [流程图教程](https://mermaid.js.org/syntax/flowchart.html) +- [时序图教程](https://mermaid.js.org/syntax/sequenceDiagram.html) +- [类图教程](https://mermaid.js.org/syntax/classDiagram.html) + +### 工具和插件 + +- [Mermaid Chart](https://www.mermaidchart.com/) - 在线图表编辑器 +- [VS Code Mermaid 插件](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid) +- [Chrome Mermaid 扩展](https://chrome.google.com/webstore/search/mermaid) + +--- + +## 更新日志 + +### 版本 1.0.0 (2024-01-22) + +- ✨ 初始版本发布 +- ✅ 支持所有主要图表类型 +- ✅ 自动主题切换 +- ✅ 插件兼容性检测 +- ✅ CDN 降级机制 +- ✅ 错误提示和调试支持 + +--- + +## 反馈与建议 + +如果您在使用过程中有任何问题或建议,欢迎: + +- 📧 发送邮件至主题作者 +- 💬 在 GitHub 上提交 Issue +- 🌟 为项目点赞支持 + +感谢您使用 Argon 主题! diff --git a/settings.php b/settings.php index 5ee6233..8f98f6f 100644 --- a/settings.php +++ b/settings.php @@ -3217,6 +3217,239 @@ function themeoptions_page(){ +

+ + + + +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+

+ +

+
+
+ + +
+ +

+ +

+ + + + +

diff --git a/tests/test-ai-comment-flow.md b/tests/test-ai-comment-flow.md new file mode 100644 index 0000000..7a67669 --- /dev/null +++ b/tests/test-ai-comment-flow.md @@ -0,0 +1,187 @@ +# AI 评论审核流程说明 + +## 流程概述 + +本文档通过 Mermaid 流程图详细展示用户提交评论后,系统进行 AI 审核的全流程,涵盖预处理、规则判断、AI 检测、结果处理、数据学习等核心环节。 + +## 流程图 + +::: mermaid +flowchart TD +Start([用户提交评论]) --> PreProcess[预处理评论
钩子:preprocess_comment/post_comment_preprocessing] +PreProcess --> CheckEnabled{启用 AI 检测?} +CheckEnabled -->|否| SaveComment[保存评论] +CheckEnabled -->|是| CheckMode{检测模式?} +CheckMode -->|manual(关闭实时检测)| SaveComment +CheckMode -->|keyword/sample/all| CheckLoggedIn{已登录用户?} +CheckLoggedIn -->|是且跳过登录用户| SaveComment +CheckLoggedIn -->|否或不跳过| CheckWhitelist{在白名单?} +CheckWhitelist -->|是| SaveComment +CheckWhitelist -->|否| CheckKeyword[检查关键字触发] +CheckKeyword --> DecideCheck{决定是否检测} +DecideCheck -->|keyword模式且触发关键字| NeedCheck[需要检测] +DecideCheck -->|sample模式且触发关键字| NeedCheck +DecideCheck -->|sample模式且随机抽中| NeedCheck +DecideCheck -->|all模式| NeedCheck +DecideCheck -->|其他情况| SaveComment +NeedCheck --> SetPending[强制设置 comment_approved=0
待审核状态] +SetPending --> SetFlag[设置 _argon_needs_spam_check=true] +SetFlag --> SaveKeywords[保存触发的关键字] +SaveKeywords --> SaveComment +SaveComment --> CommentPost[评论入库后处理
钩子:comment_post/post_comment_updatemetas] +CommentPost --> SaveMeta[保存评论元数据] +SaveMeta --> CheckNeedFlag{有 _argon_needs_spam_check 标记?} +CheckNeedFlag -->|否| ShowPending[显示审核中状态] +CheckNeedFlag -->|是| SaveCheckMeta[保存检测标记到数据库] +SaveCheckMeta --> AutoDetect[触发自动检测
钩子:comment_post/argon_auto_detect_spam_on_comment] +AutoDetect --> CheckSaved{有检测标记?} +CheckSaved -->|否| End1([结束]) +CheckSaved -->|是| CheckDetected{已检测过?} +CheckDetected -->|是| End2([结束]) +CheckDetected -->|否| CheckReason{检测原因?} +CheckReason -->|关键字触发| SyncDetect[立即同步检测] +CheckReason -->|其他| AsyncDetect[异步检测(延迟1秒)] +SyncDetect --> DetectHandler[检测处理函数
argon_async_spam_detection_handler] +AsyncDetect --> DetectHandler +DetectHandler --> CallAI[调用 AI API
argon_detect_spam_comment] +CallAI --> GetPrompt[根据 Prompt 模式获取提示词] +CallAI --> BuildContext[构建评论上下文(用户名+内容)] +BuildContext --> SendAPI[发送到 AI API] +SendAPI --> ParseResult[解析 AI 返回结果] +ParseResult --> SaveTime[记录检测时间] +SaveTime --> GenCode[生成识别码] +GenCode --> UpdateStats[更新用户统计] +UpdateStats --> CheckResult{检测结果?} +CheckResult -->|内容违规(高置信度)| CheckAction1{自动处理方式?} +CheckResult -->|内容违规(低置信度)| MarkLowConf[标记为疑似垃圾
等待人工审核] +CheckResult -->|内容正常/用户名违规/无邮箱| TrashNoEmail[移入回收站] +CheckResult -->|内容正常/用户名违规/有邮箱| ChangeUsername[修改用户名] +CheckResult -->|都正常| MarkNormal[标记为正常评论] +CheckAction1 -->|trash| TrashComment[移入回收站] +CheckAction1 -->|hold| HoldComment[标记为待审核] +CheckAction1 -->|mark| MarkOnly[仅标记不处理] +TrashComment --> SendSpamEmail[发送垃圾评论通知] +HoldComment --> SendSpamEmail +MarkOnly --> SaveResult1[保存检测结果] +SendSpamEmail --> SaveResult1 +MarkLowConf --> SaveResult2[保存检测结果] +TrashNoEmail --> SaveResult3[保存检测结果] +ChangeUsername --> GenNewName[生成新用户名] +GenNewName --> UpdateDB[更新数据库] +UpdateDB --> SendChangeEmail[发送用户名变更通知] +SendChangeEmail --> SaveResult4[保存检测结果] +MarkNormal --> SaveResult5[保存检测结果] +SaveResult1 --> AILearn{启用 AI 学习?} +SaveResult2 --> AILearn +SaveResult3 --> AILearn +SaveResult4 --> AILearn +SaveResult5 --> AILearn +AILearn -->|是| ExtractKeywords[提取关键词] +AILearn -->|否| DetectEnd([检测完成]) +ExtractKeywords --> UpdateKeywords[更新学习关键词库] +UpdateKeywords --> DetectEnd +ShowPending --> UserView([用户看到:审核中状态]) +DetectEnd --> AdminReview([管理员审核]) + +style Start fill:#e1f5e1,stroke:#2e7d32,stroke-width:2px +style End1 fill:#ffe1e1,stroke:#c62828,stroke-width:2px +style End2 fill:#ffe1e1,stroke:#c62828,stroke-width:2px +style DetectEnd fill:#e1f5e1,stroke:#2e7d32,stroke-width:2px +style UserView fill:#fff4e1,stroke:#ff8f00,stroke-width:2px +style AdminReview fill:#e1e8ff,stroke:#1565c0,stroke-width:2px +style NeedCheck fill:#ffcccc,stroke:#c62828,stroke-width:1px +style SetPending fill:#ffcccc,stroke:#c62828,stroke-width:1px +style TrashComment fill:#ff6b6b,stroke:#c62828,stroke-width:1px +style TrashNoEmail fill:#ff6b6b,stroke:#c62828,stroke-width:1px +style HoldComment fill:#ffa500,stroke:#ff8f00,stroke-width:1px +style MarkLowConf fill:#ffa500,stroke:#ff8f00,stroke-width:1px +style ChangeUsername fill:#4ecdc4,stroke:#00897b,stroke-width:1px +style MarkNormal fill:#95e1d3,stroke:#2e7d32,stroke-width:1px +::: + +## 流程关键节点说明 + +### 1. 预处理阶段 + +- 触发 `preprocess_comment`/`post_comment_preprocessing` 钩子,完成评论基础清洗。 +- 优先判断是否启用 AI 检测,未启用则直接保存评论。 + +### 2. 检测规则判断 + +- 检测模式分 4 类:manual(关闭)、keyword(关键字)、sample(抽样)、all(全量)。 +- 白名单用户、已登录且配置跳过的用户,直接跳过检测。 +- keyword/sample 模式下,仅关键字触发/随机抽中时才启动检测。 + +### 3. AI 检测执行 + +- 关键字触发:立即同步检测;其他情况:延迟 1 秒异步检测。 +- 调用 `argon_detect_spam_comment` 接口,拼接用户名+评论内容作为上下文发送 AI。 + +### 4. 结果处理逻辑 + +| 检测结果 | 处理方式 | +|-------------------------|-----------------------------------| +| 内容违规(高置信度)| 按配置自动处理(移入回收站/待审核/仅标记) | +| 内容违规(低置信度)| 标记疑似垃圾,等待人工审核 | +| 用户名违规(无邮箱)| 直接移入回收站 | +| 用户名违规(有邮箱)| 自动生成新用户名并通知用户 | +| 内容+用户名均正常 | 标记为正常评论 | + +### 5. 后续环节 + +- 所有检测结果均保存至数据库,支持 AI 学习功能(提取关键词更新词库)。 +- 用户侧仅展示"审核中"状态,最终结果需管理员复核。 + +## 技术说明 + +### 使用的钩子 + +- `preprocess_comment` - 评论预处理 +- `post_comment_preprocessing` - 评论预处理(备用) +- `comment_post` - 评论入库后 +- `post_comment_updatemetas` - 更新评论元数据 +- `argon_auto_detect_spam_on_comment` - 自动检测触发 + +### 关键函数 + +- `argon_detect_spam_comment()` - AI 检测主函数 +- `argon_async_spam_detection_handler()` - 异步检测处理 +- `argon_get_spam_detection_prompt()` - 获取检测 Prompt +- `argon_build_comment_context()` - 构建评论上下文 + +### 数据库字段 + +- `comment_approved` - 评论审核状态(0=待审核,1=已通过) +- `_argon_needs_spam_check` - 是否需要 AI 检测标记 +- `_argon_spam_detection_result` - AI 检测结果 +- `_argon_spam_detection_time` - 检测时间戳 +- `_argon_spam_keywords` - 触发的关键字 + +## 配置建议 + +### 小型博客(评论量 < 100/天) + +- 检测模式:keyword(关键字触发) +- Prompt 模式:标准模式 +- 自动处理阈值:置信度 > 0.9 + +### 中型博客(评论量 100-500/天) + +- 检测模式:sample(智能抽样) +- Prompt 模式:标准模式 +- 自动处理阈值:置信度 > 0.85 + +### 大型博客(评论量 > 500/天) + +- 检测模式:sample(智能抽样 30-40%) +- Prompt 模式:极简模式 +- 自动处理阈值:置信度 > 0.8 +- 定期批量扫描待审核评论 + +## 注意事项 + +1. **API 成本控制**:合理设置检测模式和抽样比例 +2. **误判处理**:始终保留人工审核入口 +3. **隐私保护**:不要将敏感信息发送给 AI +4. **性能优化**:关键字触发使用同步检测,其他使用异步 +5. **定期优化**:根据误判率调整 Prompt 和阈值 diff --git a/tests/test-codeblock-magic.html b/tests/test-codeblock-magic.html new file mode 100644 index 0000000..aeb7cdf --- /dev/null +++ b/tests/test-codeblock-magic.html @@ -0,0 +1,295 @@ + + + + + + Mermaid 代码块魔改测试 + + + + + +

Mermaid 代码块魔改测试

+

本页面用于测试标准 Markdown 代码块 (```mermaid) 的 Mermaid 图表渲染功能。

+ + +
+

测试用例 1:标准 Markdown 格式

+
+ 格式:<pre><code class="language-mermaid"> +
+

+flowchart TD
+    A[开始] --> B{判断}
+    B -->|是| C[执行操作]
+    B -->|否| D[跳过]
+    C --> E[结束]
+    D --> E
+		
+
+ + +
+

测试用例 2:多个代码块(批量处理)

+
+ 测试同一页面中多个 Mermaid 代码块的处理 +
+

+graph LR
+    A[客户端] --> B[服务器]
+    B --> C[数据库]
+    C --> B
+    B --> A
+		
+
+

+sequenceDiagram
+    participant 用户
+    participant 系统
+    用户->>系统: 发送请求
+    系统->>用户: 返回响应
+		
+
+ + +
+

测试用例 3:特殊字符保留

+
+ 测试箭头符号 -->、双横线 --、等号 == 等特殊字符是否正确保留 +
+

+flowchart TD
+    A --> B
+    B -- 文本 --> C
+    C ==> D
+    D -.-> E
+    E ~~~ F
+		
+
+ + +
+

测试用例 4:空代码块(边界情况)

+
+ 测试空代码块是否会导致错误 +
+
+

空代码块应该被跳过,不会创建容器

+
+ + +
+

测试用例 5:多行代码块(换行符保留)

+
+ 测试多行代码块中的换行符是否正确保留 +
+

+graph TB
+    subgraph 子图1
+        A1[节点A1]
+        A2[节点A2]
+    end
+    subgraph 子图2
+        B1[节点B1]
+        B2[节点B2]
+    end
+    A1 --> B1
+    A2 --> B2
+		
+
+ + +
+

测试用例 6:简化格式

+
+ 格式:<pre><code class="mermaid"> +
+

+pie title 数据分布
+    "类别A" : 45
+    "类别B" : 30
+    "类别C" : 25
+		
+
+ + +
+

测试用例 7:无 pre 包裹

+
+ 格式:<code class="language-mermaid">(无 pre 标签) +
+ +flowchart LR + Start --> Stop + +
+ + +
+

测试用例 8:自定义属性格式

+
+ 格式:<pre data-lang="mermaid"> +
+
+stateDiagram-v2
+    [*] --> 状态1
+    状态1 --> 状态2
+    状态2 --> [*]
+		
+
+ + +
+

测试用例 9:复杂图表

+
+ 测试复杂的 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()
+    }
+		
+
+ + + + diff --git a/tests/test-wp-markdown-format.html b/tests/test-wp-markdown-format.html index d794d73..5e8fc8b 100644 --- a/tests/test-wp-markdown-format.html +++ b/tests/test-wp-markdown-format.html @@ -120,7 +120,7 @@ flowchart TD return blocks; } - // 提取代码块内容 + // 提取代码块内容(使用改进后的正则) function extractMermaidCode(element) { let code = ''; @@ -128,25 +128,31 @@ flowchart TD const scriptTag = element.querySelector('script'); if (scriptTag) { const scriptContent = scriptTag.textContent || scriptTag.innerText; - console.log('[测试] 原始 script 内容:', scriptContent); + console.log('[测试] 原始 script 内容:', scriptContent.substring(0, 100)); - // 匹配 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); - } + // 使用改进后的正则:[\s\S]*? 匹配包括换行在内的所有字符 + let match = scriptContent.match(/document\.write\s*\(\s*["']([\s\S]*?)["']\s*\)/); if (match && match[1]) { code = match[1]; - console.log('[测试] 提取到的代码(转义前):', code); + console.log('[测试] 从 document.write() 提取到代码,长度:', code.length); } else { - const clonedElement = element.cloneNode(true); - const scripts = clonedElement.querySelectorAll('script'); - scripts.forEach(script => script.remove()); - code = clonedElement.textContent; + // 降级方案:直接提取引号内容 + match = scriptContent.match(/["']([\s\S]*?)["']/); + if (match && match[1]) { + code = match[1]; + console.log('[测试] 从引号内提取到代码,长度:', code.length); + } else { + const clonedElement = element.cloneNode(true); + const scripts = clonedElement.querySelectorAll('script'); + scripts.forEach(script => script.remove()); + code = clonedElement.textContent; + console.log('[测试] 使用降级方案提取代码'); + } } } else { code = element.textContent; + console.log('[测试] 从纯文本提取代码'); } } else if (element.tagName === 'CODE') { code = element.textContent; @@ -172,7 +178,7 @@ flowchart TD .replace(/\\'/g, "'") .replace(/\\\\/g, '\\'); - console.log('[测试] 最终提取的代码:', code); + console.log('[测试] 最终提取的代码:', code.substring(0, 100) + (code.length > 100 ? '...' : '')); return code.trim(); }