架构
Docmod 分成 CLI、核心库、HTML 模型、Reader/Writer、Patch engine 和模板包几层。
src/├── Docmod.Core/│ ├── Api/│ ├── Html/│ ├── Reader/│ ├── Writer/│ ├── Patch/│ ├── Models/│ └── Commands/├── Docmod/└── Docmod.Native/docx -> DocxReader -> DocmodDocument -> HtmlEmitter -> document.htmldocument.html -> HtmlParser -> DocmodDocument -> DocxWriter -> docxDocmodDocument 是中间表示:一组扁平元素,加上样式表、计数器、批注、修订和诊断信息。
Patch engine
Section titled “Patch engine”全量 docx -> HTML -> docx 会丢失不支持对象。Patch engine 的职责是让未修改内容不经过重建。
BodyElementMap建立data-id -> body child index。PatchDiff比较 baseline 和 modified HTML,分类为 keep、replace、delete、insert。PatchEngine直接操作document.xml的XDocument。- styles、media、headers、footers 等未命中的 part 不动。
ChangeMerger
Section titled “ChangeMerger”Agent 输出的是 fragment,不是完整 HTML。ChangeMerger 把 fragment 合并进 baseline:
- 按
data-id替换或删除元素。 - 按
data-after/data-before插入新元素。 - 合并批注、脚注、尾注等元数据块。
- 自动清理孤立批注。
- 对定位失败或只读命中产生 diagnostics。
对 .docmod 执行 edit 时,Docmod 只更新包内 document.html,不立即改 source.docx。这样连续多轮 Agent 编辑只需要合并 HTML。
export 或 compact 才运行真正 patch,把最终 HTML 一次性应用到原始 docx。
段落 ID 优先使用可信 w14:paraId。没有可信 paraId 时,读取阶段生成 8 位大写 hex,并标记 data-stable="false"。compact / export 会把首次读取到的 ID 盖进 docx,后续就成为稳定锚点。
同路径外部编辑后,DataIdReconciler 会按 w14:paraId 或归一化可见文本对齐旧 ID,并重锚批注。
可编辑性门控
Section titled “可编辑性门控”Docmod 默认拒绝不可确认安全的改动。read 会给可编辑节点标 data-editable="true";没有这个属性的节点视为只读。
只读来源包括:
- 锁定内容控件。
- 强制只读文档保护范围外的内容。
- TOC 结果行。
- PAGE 域 run。
- opaque 区域,例如嵌套表格、文本框、SmartArt、图表和 OLE。
命中只读区域会产生 PATCH009 或 PATCH010。