fix(acceptance-r2): 二轮验收 4 项回修(docs/15)

C5 粘贴:handleDOMEvents.paste 前置拦截无 HTML/无文件的多行纯文本按段落
插入(真机菜单粘贴走 execCommand 兜底、与 Ctrl+V 同中 clipboard 插件的
Markdown 解析);插入改开放 Slice,消除段中空段。
E3 相对导出:先选保存位置,再按导出目录重写图片相对路径。
E4 复制为 HTML:剪贴板变体公式只留 MathML、Mermaid 栅格化 PNG。
E6 HTML 导入:DOM 预处理剥 head/脚本/SVG、自家 KaTeX 还原 $ 源码、
GFM 插件加载失败降级。vitest 79 通过 + 2 跳过。
This commit is contained in:
Muse
2026-11-14 11:17:12 +08:00
parent 9bd3f3de97
commit b2d36b7397
8 changed files with 348 additions and 34 deletions

View File

@@ -0,0 +1,58 @@
# new-markdown 二轮验收回修报告(2026-11-14)
对应大王二轮回填的 4 项:C5 粘贴、E3 相对导出、E4 复制到 Word、E6 HTML 导入。本地验证:tsc 0 错误、vitest **79 通过 + 2 跳过**(新增回归 5 例)、`npm run build` 通过。
---
## C5 多行纯文本粘贴仍是一行(Ctrl+V 与菜单粘贴都中)
**根因有两层,这次都修了:**
1. **菜单粘贴在真机上根本没走 insertPlainText**:WebView2 里 `navigator.clipboard.readText()` 通常被拒,菜单粘贴实际掉进 `execCommand('paste')` 兜底 → 走 Milkdown 自带 clipboard 插件,它把纯文本当 Markdown 解析,三行 = 一个段落的软换行。
2. **Ctrl+V 同理**:自带 clipboard 插件直接处理了。
**修法**(`src/editor/plugins.ts` + `paste.ts` + `editor.ts`):
- 新增纯文本粘贴插件,走 PM 的 `handleDOMEvents.paste`——实测发现 `handlePaste` 在插件序里轮不到后注册者(clipboard 插件先处理并返回 true),而 handleDOMEvents 在 PM 事件分发里先于内置粘贴管线。条件:剪贴板**无 HTML、无文件**且纯文本含换行时,按段落插入;富文本/图片粘贴仍走默认管线。
- 插入算法换成**开放 Slice**(openStart/openEnd=1):上一版 replaceSelectionWith + insert 在段落中间粘贴会留一个序列化为 `<br />` 的空段,现在首尾行与光标前后原文自然衔接,不产生空段。
- 菜单粘贴的 execCommand 兜底触发的是同一个 paste 事件,一并受益。
**回归测试**:合成 paste 事件粘三行 → 三段;段中粘贴两行 → 无 `<br />`、前后文衔接正确。
## E3 导出 HTML(相对路径模式)图片不显示
**根因**:相对模式原样保留了文档里的相对路径(如 `doc.assets/x.png`),它只相对于 **.md 文件**成立;HTML 被另存到别的目录时,浏览器按 HTML 自己的位置找图,自然找不到。
**修法**(`exportHtml.ts` + `App.tsx`):
- 导出改为**先选保存位置、再生成 HTML**,生成时按「导出文件所在目录 → 图片实际位置(源文档目录解析)」重写 src,例如文档在 `C:\ws\docs`、HTML 存 `C:\out` 时写成 `../ws/docs/doc.assets/x.png`;HTML 与文档同目录时保持原样。路径段做 URL 编码,跨盘符退回 `file:///` 绝对地址。
**回归测试**:跨目录重写与同目录不变两例。
## E4 复制为 HTML 粘到 Word,公式和 Mermaid 都是代码
**根因**:剪贴板片段**不带 CSS**。KaTeX 的视觉层是一堆 span,没样式时在 Word 里塌成源代码式的碎字符;Mermaid 是 SVG,Word 不认剪贴板 HTML 里的 SVG。(图片内嵌本身没问题,原先就是 embed 模式。)
**修法**(剪贴板专用变体,文件导出不变):
- 公式:只保留 **MathML 本体**、剥掉 KaTeX 视觉层——Word 会把 MathML 转成原生公式,浏览器也能原生渲染 MathML。
- Mermaid:渲染出的 SVG **栅格化为 PNG 图片**(2 倍图、白底)再放进剪贴板;栅格化失败才退回 SVG。
**回归测试**:剪贴板版输出含 `<math>` 且不含 `katex-html`。
**说明**:Word 对 MathML 的转换是其标准行为,但不同 Word 版本表现可能有别,请复验时留意;若你的 Word 仍显示源码,下一步方案是公式也栅格化成图片(清晰度换兼容性)。
## E6 导入 HTML 全是 HTML 代码
**根因**:整页 HTML 直接喂给 turndown,它把 head 里的 `<style>`/`<title>` 文本、`<script>`、SVG 都翻成了正文文本,看起来「全是代码」;从记事本/浏览器另存的整页文件都会中。若导入的是**本应用自己导出的 HTML**,KaTeX 的 span 与 Mermaid 的 SVG 同样会被翻成残片。
**修法**(`exportHtml.ts`):
- 导入前用 DOM 预处理:删 script/style/svg/iframe/head 杂项;本应用导出的公式按 annotation 还原回 `$...$`(块公式 `$$...$$`);Mermaid 图换成一句「导入时无法还原源码」的说明(SVG 里没有源码,不可逆)。
- GFM 插件加载失败时降级为基础转换,不再让整个导入失败。
**回归测试**:整页 HTML(含 head/style/script/svg)导入后只剩正文结构。
---
## 复验建议(Windows)
- **C5**:记事本三行,Ctrl+V 一次、菜单粘贴一次,都应是三段;在一段文字中间粘两行,前后应衔接、无空行。
- **E3**:相对模式导出到**与文档不同的目录**(如桌面),浏览器打开图片应显示;同目录再导一份对照。
- **E4**:复制为 HTML → 粘 Word:公式应是可编辑的原生公式、Mermaid 应是图片;再粘公众号编辑器看一眼。
- **E6**:导入一个浏览器另存的整页 HTML(或上一轮导出的那份),应只有正文;表格仍在。