跳转到内容

架构

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.html
document.html -> HtmlParser -> DocmodDocument -> DocxWriter -> docx

DocmodDocument 是中间表示:一组扁平元素,加上样式表、计数器、批注、修订和诊断信息。

全量 docx -> HTML -> docx 会丢失不支持对象。Patch engine 的职责是让未修改内容不经过重建。

  1. BodyElementMap 建立 data-id -> body child index
  2. PatchDiff 比较 baseline 和 modified HTML,分类为 keep、replace、delete、insert。
  3. PatchEngine 直接操作 document.xmlXDocument
  4. styles、media、headers、footers 等未命中的 part 不动。

Agent 输出的是 fragment,不是完整 HTML。ChangeMerger 把 fragment 合并进 baseline:

  • data-id 替换或删除元素。
  • data-after / data-before 插入新元素。
  • 合并批注、脚注、尾注等元数据块。
  • 自动清理孤立批注。
  • 对定位失败或只读命中产生 diagnostics。

.docmod 执行 edit 时,Docmod 只更新包内 document.html,不立即改 source.docx。这样连续多轮 Agent 编辑只需要合并 HTML。

exportcompact 才运行真正 patch,把最终 HTML 一次性应用到原始 docx。

段落 ID 优先使用可信 w14:paraId。没有可信 paraId 时,读取阶段生成 8 位大写 hex,并标记 data-stable="false"compact / export 会把首次读取到的 ID 盖进 docx,后续就成为稳定锚点。

同路径外部编辑后,DataIdReconciler 会按 w14:paraId 或归一化可见文本对齐旧 ID,并重锚批注。

Docmod 默认拒绝不可确认安全的改动。read 会给可编辑节点标 data-editable="true";没有这个属性的节点视为只读。

只读来源包括:

  • 锁定内容控件。
  • 强制只读文档保护范围外的内容。
  • TOC 结果行。
  • PAGE 域 run。
  • opaque 区域,例如嵌套表格、文本框、SmartArt、图表和 OLE。

命中只读区域会产生 PATCH009PATCH010