1实现原理 · 为什么它能做到
把 .docx 当『ZIP 容器 + OOXML』处理,按任务类型分三条技术路线:创建走 npm docx-js 编程生成;编辑既有文件走 unzip→改 XML→zip 的外科手术;读取走 pandoc。
A `.docx` is a ZIP archive of XML files. Choose your approach by task:
创建侧内置一整套『反 footgun』gotcha 知识(A4 默认页、表格双宽度、ShadingType.CLEAR、列表 numbering、ImageRun type、PageBreak 位置、PositionalTab 点线等),把 Word/Google Docs 渲染差异写死成规则。
**Table shading:** use `ShadingType.CLEAR`, never `SOLID` (renders black).
编辑侧先做 runs 归一化再改文本:Word 会把一句话拆成大量 `<w:r>` runs,merge_runs.py 把相邻同格式 runs 合并,使 find-and-replace 在 XML 上可靠。
Word splits text across many `<w:r>` runs (revision ids, spell-check markers), so a phrase you can see in the document often doesn't exist as a contiguous string in the XML. `merge_runs.py` merges adjacent identically-formatted runs in `word/document.xml` without changing content or rendering
验证闭环=『渲染成图再看 + XSD 校验』双轨:soffice 转 PDF→pdftoppm 出图→模型 Read 图片做视觉 QA;validate.py 做 schema/关系/修订一致性检查。
python scripts/office/validate.py out.docx --original doc.docx # XSD checks; --auto-repair fixes common issues
修订(redline)有专门验收工具:validate.py 的 --author 模式检查所有改动是否被 `<w:ins>`/`<w:del>` 包住,防止『改了却不可见』的意外。
it reports any text you changed without a `<w:ins>`/`<w:del>` around it, which is easy to do by accident and invisible in the accepted view
批注是『六文件联动』装配:comment.py 自动写 4 个 comments XML + relationships + content-type overrides,再打印要插入 document.xml 的锚点片段。
The script writes `comments.xml`, `commentsExtended.xml`, `commentsIds.xml`, `commentsExtensible.xml`, the relationships, and the content-type overrides.
对『来自外部的不可信 .docx』有明确防御动作:解包后删除符号链接条目(zip-slip 类攻击面)。
find unpacked -type l -delete # strip symlink entries — docx from external parties is untrusted
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| package | docx(npm,docx-js) |
| cli | pandoc(读取 .docx → markdown) |
| cli | LibreOffice soffice(渲染 QA/接受修订/.doc 转换;经 soffice.py 包装) |
| cli | pdftoppm(Poppler,PDF 渲染成图) |
| cli | unzip / zip(解包与回封 OOXML 容器) |
4风险提醒 风险提醒:蓝色 · 知晓即可
- 外部 .docx 为不可信输入 — zip-symlink/畸形 XML 等攻击面靠提示级指引缓解(无脚本强制);恶意文档的解析暴露面最终在宿主工具与解析器。
- XML 直改易损坏文档 — 直接编辑 word/document.xml 要求精确的 XML 语义(转义、命名空间、元素顺序),模型出错会产出坏文件;validate.py 能拦一部分但不是全部。
- 运行时 gcc 编译 shim — soffice.py 在受限环境会调用本机 gcc 编译 C shim 并 LD_PRELOAD——代码自包含无害,但『skill 触发本机编译』值得知晓。
- 强环境依赖 — docx-js/pandoc/soffice/pdftoppm 需预装;缺失时条件安装会引入网络与版本不确定性。
- 专有许可 — LICENSE.txt 为 Anthropic 服务条款式专有许可(含 ADDITIONAL RESTRICTIONS),非开源——商用/再分发需审阅条款。
5第二遍独立确认
- [ok] 『创建走 docx-js』路线与依赖声明 — approach 表与 Dependencies 节一致;npm 包不在仓库内(外部依赖,条件安装)。
- [ok] merge_runs 机制(runs 拆分问题) — SKILL.md 描述与 merge_runs.py docstring 相互印证,均原文在。
- [ok] redline --author 验收与 accept_changes — 两工具及用法命令行均存在于 SKILL.md,accept_changes.py 存在且 docstring 相符。
- [ok] 批注六文件机制与 templates — comment.py 写 4 个 comments xml + rels + content-type(代码 rels/ct 常量可查);templates/ 5 个 xml 模板(含 people.xml)与脚本引用一致。
- [ok] soffice.py 沙箱 shim 无外联 — C shim 仅拦 AF_UNIX socket/listen/accept 做 socketpair 回退;编译产物在 tempdir;无任何网络地址。
- [ok] 网络/凭证零命中 — 脚本层无网络调用无 env/token 读取(get_soffice_env 仅拷贝环境变量+设 SAL_USE_VCLPLUGIN/LD_PRELOAD)。
- [ok] 功能声明 vs 实现(夸大检查) — description 声称的能力均有对应命令/脚本;'Do NOT use for PDFs, spreadsheets…' 负面边界清晰。唯一无法源码证实的是环境预装假设。
- [ok] 元数据 — 本地 HEAD==pin 41bbe19;LICENSE.txt 为 Anthropic 专有条款(© 2025 Anthropic, PBC.),与 SKILL.md frontmatter 'Proprietary' 一致。
6结论
054b66c290295197…41bbe19d1a