md-to-word(Markdown 转 Word)
目标
将一个或多个 Markdown 文档转换为格式优美的 Word(.docx),基于 Pandoc + 内置 reference.docx 模板(可选自定义模板),并确保不修改任何原始 Markdown 文件。内置模板已修复命名空间兼容性问题,支持 RGBA 图片自动转换。
流程
输入
输入为一个或多个 Markdown 文件;可选输入包括内置或自定义 reference.docx、输出目录、Pandoc 参数和图片处理选项。转换不得修改原始 Markdown,输出路径须在用户授权范围内。
执行步骤
你要解决的问题
用户给你一个或多个标准 Markdown 文档,希望把它们转换成排版美观、可审查、可交付的 Word(.docx),并且能在不同项目里复用同一套转换流程与样式模板。
常见问题解决方案:
- RGBA PNG 导致 Word 警告:使用
--fix-images自动转换为 RGB 模式 - 图片路径问题:脚本自动处理相对路径资源引用
- 中文排版问题:使用
--template cn-modern获得更好的中文样式
内置模板(Pandoc reference.docx)
内置模板文件位于 assets/:
default:assets/reference-default.docxcn-modern:assets/reference-cn-modern.docx(中文更友好字体/样式)compact:assets/reference-compact.docx(更紧凑段落间距)
推荐执行方式
优先运行确定性脚本 scripts/md_to_word.py,避免 AI 手写 Pandoc 命令导致参数缺失或误覆盖。
示例:
python3 md-to-word/scripts/md_to_word.py \
--template cn-modern \
--output-dir /path/to/out \
/path/to/a.md /path/to/b.md
如用户需要自定义样式,允许:
- 使用
--reference-doc /path/to/reference.docx覆盖内置模板(用户自带)。 - 需要用同一份 Markdown 生成多套风格时,使用
--output-suffix避免覆盖(默认不覆盖)。 - 用户不确定模板可选项时,先运行
python3 md-to-word/scripts/md_to_word.py --list-templates。
核心工作流
步骤 0:预检查(不写任何输出前)
- 校验
md_files均存在且为文件。- 默认仅接受
.md/.markdown;如用户确实给了其他扩展名,必须显式使用--allow-any-extension。
- 默认仅接受
- 确认 Pandoc 可用(默认执行
pandoc --version);不可用时给出明确安装提示,并停止。 - 选择模板:
- 优先
--reference-doc(用户显式指定); - 否则使用
--template(默认default)。
- 优先
- 计算输出路径:
- 默认:
{input_dir}/{basename}.docx - 单输入且用户想指定输出文件名:使用
--output /path/to/out.docx - 指定
--output-dir:{output_dir}/{basename}.docx - 若输出已存在:默认报错并停止(除非用户明确要求
--overwrite)。
- 默认:
步骤 1:逐文件转换(必须覆盖全部输入)
对每个 Markdown 文件:
- 图片处理(可选,
--fix-images):- 在 MD 所在目录创建
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/隐藏工作目录 - 创建
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/output/images-rgb/存放转换后的图片 - 创建 MD 副本,更新所有图片链接指向 RGB 版本
- 仅转换非 RGB 模式的图片(RGBA/P/L 等),RGB 图片直接复制
- 在 MD 所在目录创建
- 以非 shell方式调用 Pandoc(防止命令注入)。
- 自动设置
--resource-path,包含.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/目录。 - 生成
.docx到目标输出路径。 - 可选:使用
--clean转换后清理.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/工作目录(默认保留便于增量转换)
步骤 2:轻量自检(输出后必须做)
- 输入 Markdown 文件的内容未被修改(可选:对关键输入做 hash 前后对比)
- 输出
.docx均成功生成且路径符合预期 - 未发生意外覆盖(除非用户明确要求)
- 如存在图片/链接,Word 中渲染正常(无法验证时说明原因与建议)
输出
输入输出
输入
md_files:一个或多个 Markdown 文件路径(建议.md/.markdown)- 可选:
template(内置模板名)或reference_doc(自定义 reference.docx 路径) - 可选:
output_dir(输出目录)
输出
- 对每个输入 Markdown,生成一个同名
.docx(默认输出到输入文件同目录;也可输出到output_dir)
输出管理
BenszAPI 任务工作区
校验
转换前检查输入扩展名、文件存在性、Pandoc/Pillow 可用性和模板;转换后核对每个 .docx 存在、可打开、图片/链接渲染正常(无法验证时明确说明),且源 Markdown 未被覆盖。
失败与恢复
Word 兼容性问题与解决方案
问题 1:Word 打开时提示"发现无法读取的内容"(模板命名空间问题)
原因:自定义 Word 模板使用了非标准的 XML 命名空间前缀(ns0:),与 Pandoc 的 --reference-doc 参数结合时可能导致 Word 兼容性问题。
解决方案:
- 内置模板已修复:所有内置模板(
cn-modern、compact、default)已更新为使用标准命名空间 - 自动兼容性参数:脚本自动添加
--markdown-headings=atx参数提高兼容性 - 自定义模板修复:使用
scripts/fix_template_namespace.py修复自定义模板
# 修复自定义模板
python3 md-to-word/scripts/fix_template_namespace.py \
--input /path/to/custom-template.docx \
--output /path/to/custom-template-fixed.docx \
--verify
问题 2:RGBA PNG 图片导致 Word 警告
原因:Markdown 中引用的 PNG 图片使用 RGBA 模式(带透明通道),这种格式在嵌入 Word 文档时可能导致兼容性问题。
解决方案:使用 --fix-images 参数自动转换
python3 md-to-word/scripts/md_to_word.py \
--fix-images \
--template cn-modern \
your-document.md
工作原理:
- 在 MD 所在目录创建
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/隐藏工作目录 - 创建
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/output/images-rgb/存放转换后的图片 - 扫描 Markdown 中引用的所有图片(支持 PNG/JPG/GIF/BMP/WebP)
- 检测图片模式,仅转换非 RGB 模式的图片
- RGBA → RGB(白色背景)
- P/PA/LA 等 → RGB
- RGB/L → 直接复制
- 创建 MD 副本,更新图片链接指向
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/output/images-rgb/ - 使用 MD 副本执行 Pandoc 转换
- 默认保留
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/便于增量转换,使用--clean清理
工作目录结构:
your-doc.md
your-doc.docx
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/ # 隐藏工作目录(默认保留)
├── your-doc.md # MD 副本(图片链接已更新)
└── output/
└── images-rgb/ # RGB 模式图片
├── figure1.png # 转换后(RGBA→RGB)
└── photo.jpg # 直接复制(已是 RGB)
依赖:
- 需要 Pillow 库:
pip install Pillow - 如未安装,脚本会跳过图片修复并给出提示
清理选项:
- 默认保留
.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word/{yyyy-mm-dd-hh-mm}/工作目录,便于后续增量转换 - 使用
--clean转换后自动清理工作目录 - 手动清理:
rm -rf /path/to/md/.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/md-to-word
约束
公共硬约束
本块由 docs/templates/skill-common-constraints.md 统一维护;每个 SKILL.md 的 ## 约束 必须逐字同步本块,不得在副本中改写公共规则。
- 任务需要落盘时,使用唯一的
./.bensz-api/task-{yyyymmdd-hhmm}-{简短描述}/根目录;共享材料放入shared/,Skill 专属材料放入该 Skill 的input/、output/、log/。 - 正式交付物、源代码和正式计划按项目约定保存,不写入任务工作区;未经授权不覆盖、删除、迁移或远程写入。
- 项目维护变更检查 BAC 可用性并记录需求、AI 产出、工具结果、文件改动和验证摘要;BAC 只做过程审计,不替代署名、责任或合规判断。
- 不记录 API Key、访问令牌、密码、Cookie、环境/凭据文件、私有 Prompt、身份信息、本地用户名、主机名或不必要的大体积原始数据。
- 文件路径必须规范化并限制在授权项目范围内;外部 URL、子进程和网络访问遵循最小权限,防止路径遍历、SSRF 和命令注入。
- Skill 版本唯一记录在自身
config.yaml:skill_info.version;公开 API、协议、目录或配置变更同步文档与CHANGELOG.md。 bensz-collect-bugs是一个 Agent Skill;仅将 Bensz Agent Skill 或 Bensz 基础设施本身的设计缺陷交给它。先脱敏写入~/.bensz-skills/bugs/,当前任务不中断,只有用户明确要求才公开上报,禁止直接修改用户已安装的 Skill 源码。
Skill 专属约束
安全约束
- 你只能读取用户提供的 Markdown 文件及其引用资源(如图片)。
- 你绝不能修改/覆盖/重命名/删除任何输入 Markdown 文件或其同目录已有文件。
- 默认不覆盖任何已存在的输出
.docx;除非用户明确要求覆盖,才可使用--overwrite。 - 输出文件只能是新生成的
.docx(以及测试目录中的中间产物)。