md2word

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Markdown转Word文档Skill

Markdown to Word Document Skill

概述

Overview

将 Markdown 文档转换为符合中文排版标准的 Word 文档。支持完整的 Markdown 语法,自动应用专业格式设置。
Convert Markdown documents to Word documents that comply with Chinese typesetting standards. Supports full Markdown syntax and automatically applies professional formatting settings.

依赖要求

Dependency Requirements

Python 依赖

Python Dependencies

bash
pip install python-docx Pillow beautifulsoup4 PyYAML
bash
pip install python-docx Pillow beautifulsoup4 PyYAML

可选依赖

Optional Dependencies

bash
npm install -g @mermaid-js/mermaid-cli   # Mermaid 图表渲染
brew install librsvg                       # SVG→PNG(推荐,rsvg-convert)
bash
npm install -g @mermaid-js/mermaid-cli   # Mermaid diagram rendering
brew install librsvg                       # SVG→PNG (recommended, rsvg-convert)

或 pip install cairosvg # SVG→PNG 备选

or pip install cairosvg # SVG→PNG alternative

或 npm install puppeteer # SVG→PNG 备选(scripts/svg2png.js)

or npm install puppeteer # SVG→PNG alternative (scripts/svg2png.js)


> 正文内联 `<svg>...</svg>` 块会自动渲染为 PNG 嵌入,渲染优先级 rsvg-convert → cairosvg → svg2png.js(puppeteer),三者任一即可;全部不可用时降级为代码框显示 SVG 源码。

> Inline `<svg>...</svg>` blocks in the content will be automatically rendered as PNG and embedded. The rendering priority is rsvg-convert → cairosvg → svg2png.js(puppeteer); any one of the three is sufficient. If none are available, it will fall back to displaying the SVG source code in a code block.

快速开始

Quick Start

主转换脚本:
scripts/md2word.py
bash
undefined
Main conversion script:
scripts/md2word.py
bash
undefined

基本转换

Basic conversion

python scripts/md2word.py input.md output.docx
python scripts/md2word.py input.md output.docx

使用预设格式

Use preset format

python scripts/md2word.py input.md --preset=academic
python scripts/md2word.py input.md --preset=academic

使用自定义配置

Use custom configuration

python scripts/md2word.py input.md --config=my-config.yaml
python scripts/md2word.py input.md --config=my-config.yaml

脚注/尾注模式(默认 footnote 页面脚注;endnote=文档末注释+上标编号)

Footnote/endnote mode (default footnote is page footnote; endnote=end-of-document notes + superscript numbering)

python scripts/md2word.py input.md --notes=endnote
python scripts/md2word.py input.md --notes=endnote

全书合并:多章 md → 单 docx(目录+按输入文件分章+页眉,配合 -o 指定输出)

Book merging: multiple chapter md files → single docx (table of contents + chapter division by input files + header, specify output with -o)

python scripts/md2word.py --book ch01.md ch02.md ch03.md -o book.docx --preset=book-publish

> `--book` 只把相邻输入文件的边界转换为新 section。章节正文里的 Markdown 水平线 `---`、`***`、`___` 在单章和全书模式下都会保留为水平线,不承担分页或分章语义。

> `--book` 会在合并前按每个章节 Markdown 自己所在的目录解析本地相对图片路径,再写入临时合并稿。Markdown 图片与 HTML `<img src>` 均支持;HTTP/HTTPS、data URI、锚点和绝对路径保持原样。单章转换的图片解析流程不变。

> `book-publish` 默认让标题文字精确等于“本章小结”或“动手练习”的 Markdown 标题从新页开始;转换器在标题段自身写入 Word 原生 `pageBreakBefore`,不插入空段、分页 run 或新 section。该规则同样适用于单章转换,其他预设默认关闭;可通过 `pagination.page_break_before_headings` 覆盖。

> 同一 `[^label]` 在正文重复出现时,原生 `footnote` 模式会为每次出现生成独立的 Word 脚注,并重复相同定义文本,确保每个引用位置都能看到脚注;`endnote` 模式仍复用同一编号与一条尾注定义。

> 原生 `footnote` 模式下,两个脚注标记在源码中直接相邻时,输出会在两个上标之间加入一个同为 9pt 上标的 NBSP;源码已有空格或标点时不额外添加。页面脚注段落固定为段前段后 0、单倍自动行距;`endnote` 不应用这两项规则。

> 页面脚注在普通正文与 Markdown 引用块(`>`)中都可使用;引用块内的 `[^label]` 会生成原生 Word 脚注引用,不会作为字面标记留在正文,同时保留引用段落和加粗等行内格式。

> 所有 Markdown 引用块统一读取一套 `quote` 配置,不按“本章导读”“案例”等文字标签分流。内置预设的引用框与 fenced code block 共用中性浅灰视觉 token `#F5F5F5`,样式为正文全宽、无可见边框的段落底纹;不使用表格容器,因此 Word 的“查看网格线”不会出现虚线外框。文字通过 `padding` 保留左右和首尾内边距;内部空引用行会生成同底色的 `paragraph_spacing` exact 空段,使多段 callout 保持一整块连续灰底。连续多个内部空引用行确定性折叠为一个,首尾空引用行忽略。

> 行内代码优先保护反引号范围:其中的 `_`、`*` 等 Markdown 标记按字面量保留,不会与相邻代码段拼成斜体或粗体;例如 `` `law_keyword` `` 会完整输出为一个代码 run。

> 普通技术标识内部的下划线按字面量保留:正文与 Markdown 表格中的 `payment_instance_id`、`API_SERVER_KEY` 等名称不会被解释为斜体或粗体。下划线强调须位于单词边界,明确的 `_斜体_`、`__粗体__` 与 `___粗斜体___` 仍按原语义渲染。

> 所有 fenced code block(包括 `text`、`markdown` 与无语言围栏)均沿用既有等宽、紧凑的代码内容样式;可通过 `code_block.content.space_before` 与 `space_after` 仅调整整个框与前后正文的垂直间距。

> Markdown 表格固定在页面正文可用宽度内;多列长表头会自动换行,转换器会统一表格总宽、网格列宽和单元格宽度,避免表格越过左右页边距。

> Markdown 与 HTML 数据表都由表格组件自身追加 `table.space_after` 固定高度留白(默认 6pt exact);后续正文保持普通正文的 1.5 倍行距与 0 段前距。图片和图注不使用这项表格留白。

> 普通 Markdown 表题(如 `**表 10-5:标题**`)会自动水平居中并取消首行缩进;显式 `<div align="center">...</div>` 仍可继续使用。表题原有字号和粗体不受自动对齐影响。
python scripts/md2word.py --book ch01.md ch02.md ch03.md -o book.docx --preset=book-publish

> `--book` only converts the boundaries between adjacent input files into new sections. Markdown horizontal lines `---`, `***`, `___` in chapter content will be retained as horizontal lines in both single-chapter and book modes, and do not bear pagination or chapter division semantics.

> `--book` will resolve local relative image paths according to the directory where each chapter's Markdown is located before merging, then write to a temporary merged draft. Both Markdown images and HTML `<img src>` are supported; HTTP/HTTPS, data URI, anchors and absolute paths remain unchanged. The image resolution process for single-chapter conversion remains the same.

> The `book-publish` preset by default starts a new page for Markdown titles whose text is exactly "Chapter Summary" or "Hands-on Practice"; the converter writes Word native `pageBreakBefore` in the title paragraph itself, without inserting empty paragraphs, pagination runs or new sections. This rule also applies to single-chapter conversion, and is disabled by default in other presets; it can be overridden via `pagination.page_break_before_headings`.

> When the same `[^label]` appears repeatedly in the content, the native `footnote` mode will generate independent Word footnotes for each occurrence and repeat the same definition text, ensuring that the footnote can be seen at each reference position; the `endnote` mode still reuses the same number and one endnote definition.

> In native `footnote` mode, when two footnote markers are directly adjacent in the source code, the output will add a 9pt superscript NBSP between the two superscripts; no additional space is added if there is already a space or punctuation in the source code. Page footnote paragraphs are fixed to 0 before/after spacing and single auto line spacing; these two rules do not apply to `endnote`.

> Page footnotes can be used in both regular content and Markdown blockquotes (`>`); `[^label]` in blockquotes will generate native Word footnote references, not remain as literal markers in the content, while retaining the blockquote paragraph and inline formats like bold.

> All Markdown blockquotes read a set of `quote` configuration uniformly, and are not diverted by text labels such as "Chapter Guide" or "Case". The built-in preset's quote box and fenced code block share the neutral light gray visual token `#F5F5F5`, with the style of full-width content paragraph shading without visible borders; no table container is used, so Word's "View Gridlines" will not show dashed outer borders. Text retains left/right and top/bottom padding via `padding`; empty quote lines inside generate `paragraph_spacing` exact empty paragraphs with the same background color, so multi-paragraph callouts maintain a single continuous gray background. Consecutive empty quote lines inside are deterministically collapsed into one, and leading/trailing empty quote lines are ignored.

> Inline code prioritizes protecting backtick ranges: Markdown markers like `_` and `*` within are retained as literals, and will not be combined with adjacent code segments to form italics or bold; for example, `` `law_keyword` `` will be fully output as a single code run.

> Underscores in regular technical identifiers are retained as literals: names like `payment_instance_id` and `API_SERVER_KEY` in content and Markdown tables will not be interpreted as italics or bold. Underscore emphasis must be at word boundaries; explicit `_italic_`, `__bold__` and `___bold-italic___` are still rendered according to their original semantics.

> All fenced code blocks (including `text`, `markdown` and language-less fences) follow the existing monospaced, compact code content style; you can adjust only the vertical spacing between the entire block and the preceding/following content via `code_block.content.space_before` and `space_after`.

> Markdown tables are fixed within the available width of the page content; multi-column long headers will automatically wrap, and the converter will unify the total table width, grid column width and cell width to prevent the table from crossing the left/right margins.

> Both Markdown and HTML data tables append a fixed-height blank space (default 6pt exact) via `table.space_after` by the table component itself; subsequent content maintains the regular content's 1.5x line spacing and 0 before-paragraph spacing. Images and captions do not use this table blank space.

> Regular Markdown table captions (such as `**Table 10-5: Title**`) will be automatically centered horizontally and have first-line indentation removed; explicit `<div align="center">...</div>` can still be used. The original font size and boldness of the caption are not affected by automatic alignment.

配置系统

Configuration System

内置预设

Built-in Presets

预设信息从 YAML 文件动态读取,运行以下命令查看完整列表:
bash
python scripts/config.py --list
常用预设:
  • legal — 法律文书格式(默认)
  • service-plan — 法律服务方案(含分层配色)
  • minimal — 极简格式
  • academic — 学术论文格式
  • report — 工作报告格式
  • book-publish — 中文书籍出版格式(正文宋体、标题黑体、TOC/页眉书名,配合
    --book
    全书合并导出)
完整配置见
assets/presets/*.yaml
,设计说明见
assets/theme-notes/
Preset information is dynamically read from YAML files. Run the following command to view the complete list:
bash
python scripts/config.py --list
Common presets:
  • legal — Legal document format (default)
  • service-plan — Legal service plan (with hierarchical color scheme)
  • minimal — Minimalist format
  • academic — Academic paper format
  • report — Work report format
  • book-publish — Chinese book publishing format (content in Songti, titles in Heiti, TOC/header with book title, used with
    --book
    for book merging export)
Complete configurations are in
assets/presets/*.yaml
, and design instructions are in
assets/theme-notes/

自定义配置

Custom Configuration

复制配置模板并修改:
bash
cp assets/config-template.yaml my-config.yaml
Copy the configuration template and modify it:
bash
cp assets/config-template.yaml my-config.yaml

Word 模板文件

Word Template Files

.docx
模板放入
assets/templates/
目录,或使用
--template
指定。
Word 模板 vs 配置文件
  • Word 模板:控制视觉元素(页眉、页脚、Logo)
  • 配置文件:控制格式参数(字号、行距、页边距)
Place
.docx
templates in the
assets/templates/
directory, or specify using
--template
.
Word Template vs Configuration File:
  • Word Template: Controls visual elements (header, footer, Logo)
  • Configuration File: Controls format parameters (font size, line spacing, margins)

参考文档

Reference Documents

  • 配置参考: references/config-reference.md
  • 样式映射: references/style-mappings.md
  • 使用示例: references/examples.md
  • Configuration Reference: references/config-reference.md
  • Style Mappings: references/style-mappings.md
  • Usage Examples: references/examples.md

所需权限与安全说明

Required Permissions and Security Notes

本技能会调用本地脚本执行文档转换,涉及以下能力边界,请在使用前知悉:
This skill calls local scripts to perform document conversion, involving the following capability boundaries. Please be aware before use:

本地代码执行

Local Code Execution

  • scripts/md2word.py
    通过
    subprocess.run
    调用外部渲染工具渲染图表与 SVG:
    • Mermaid 图表:调用
      mmdc
      (MMDCCMD 环境变量 → 脚本同目录
      node_modules/.bin/mmdc
      → 系统 PATH),仅渲染用户输入的 mermaid 代码,命令以参数数组拼接,不经过 shell 字符串拼接。
    • SVG 渲染:按优先级调用
      rsvg-convert
      cairosvg
      node scripts/svg2png.js
      (Puppeteer)。内联 SVG 为不可信输入时,可能触发渲染器解析问题或资源消耗,请只转换可信来源的文档。
  • scripts/md2word.py
    calls external rendering tools via
    subprocess.run
    to render diagrams and SVG:
    • Mermaid Diagrams: Calls
      mmdc
      (MMDCCMD environment variable →
      node_modules/.bin/mmdc
      in the same directory as the script → system PATH), only renders user-input mermaid code, and commands are spliced as parameter arrays without shell string splicing.
    • SVG Rendering: Calls
      rsvg-convert
      cairosvg
      node scripts/svg2png.js
      (Puppeteer) according to priority. When inline SVG is untrusted input, it may trigger renderer parsing issues or resource consumption. Please only convert documents from trusted sources.

网络访问(默认启用)

Network Access (Enabled by Default)

  • 转换含外部 URL 图片的 Markdown 时会自动向任意 HTTP/HTTPS 地址发起请求
    urllib.request
    ,超时 20s),用于下载图片嵌入 Word。
  • 这是默认行为:外链图片会正常下载并嵌入文档;下载失败时降级为文字占位符。
  • 请知悉风险:处理不可信 Markdown 可能触发 SSRF(访问内网地址)、向第三方泄露转换方 IP/时间等元数据、引入恶意或超大图片负载。请仅转换可信来源的文档。
  • 上述下载请求不会上传文档内容,只按 Markdown 中的图片 URL 拉取图片。
  • When converting Markdown containing external URL images, it will automatically initiate requests to any HTTP/HTTPS address (via
    urllib.request
    , timeout 20s) to download images for embedding into Word.
  • This is the default behavior: external images will be downloaded and embedded normally; if download fails, it falls back to a text placeholder.
  • Please be aware of the risks: processing untrusted Markdown may trigger SSRF (accessing internal network addresses), leak metadata such as the converter's IP/time to third parties, or introduce malicious or oversized image loads. Please only convert documents from trusted sources.
  • The above download requests do not upload document content, only pull images according to the image URLs in the Markdown.

环境变量读取

Environment Variable Reading

  • chart_handler.py
    读取
    MMDCCMD
    环境变量以定位 mermaid-cli 可执行文件(可选,未设置时回退到脚本同目录 node_modules 与系统 PATH)。
  • chart_handler.py
    reads the
    MMDCCMD
    environment variable to locate the mermaid-cli executable (optional; if not set, it falls back to the script's same-directory node_modules and system PATH).

文件访问

File Access

  • 读取用户指定的 Markdown 输入文件、
    assets/templates/
    下的 Word 模板与
    assets/presets/
    下的 YAML 配置。
  • 在输出目录生成 Word 文档(
    --book
    模式会生成临时合并 Markdown,转换结束后自动删除;章节本地相对图片会先按各自源文件目录重定位)。
  • Reads user-specified Markdown input files, Word templates in
    assets/templates/
    and YAML configurations in
    assets/presets/
    .
  • Generates Word documents in the output directory (the
    --book
    mode generates a temporary merged Markdown file, which is automatically deleted after conversion; local relative images in chapters are first relocated according to their respective source file directories).

错误处理

Error Handling

  • 文件编码:自动检测 UTF-8 和 GBK
  • 模板找不到:使用默认格式创建新文档
  • Mermaid 失败:降级为文本描述
  • 图片过大:自动压缩和调整尺寸
  • File Encoding: Automatically detects UTF-8 and GBK
  • Template Not Found: Creates a new document using default format
  • Mermaid Failure: Falls back to text description
  • Overly Large Images: Automatically compresses and adjusts size

目录结构

Directory Structure

md2word/
├── SKILL.md               # 本文档
├── CHANGELOG.md           # 版本记录
├── references/            # 参考文档
│   ├── config-reference.md
│   ├── style-mappings.md
│   └── examples.md
├── scripts/               # 转换脚本
│   ├── md2word.py         # 主脚本
│   ├── config.py          # 配置模块(含 --list 查看预设)
│   ├── extract_template_config.py  # 从 Word 模板提取配置
│   ├── formatter.py       # 文本格式化模块
│   ├── table_handler.py   # 表格处理模块
│   └── chart_handler.py   # 图表渲染模块
└── assets/                # 资源文件
    ├── presets/           # YAML 预设配置
    ├── theme-notes/       # 预设设计说明文档
    ├── templates/         # Word 模板文件
    └── config-template.yaml
md2word/
├── SKILL.md               # This document
├── CHANGELOG.md           # Version history
├── references/            # Reference documents
│   ├── config-reference.md
│   ├── style-mappings.md
│   └── examples.md
├── scripts/               # Conversion scripts
│   ├── md2word.py         # Main script
│   ├── config.py          # Configuration module (includes --list to view presets)
│   ├── extract_template_config.py  # Extract configuration from Word template
│   ├── formatter.py       # Text formatting module
│   ├── table_handler.py   # Table processing module
│   └── chart_handler.py   # Diagram rendering module
└── assets/                # Resource files
    ├── presets/           # YAML preset configurations
    ├── theme-notes/       # Preset design documentation
    ├── templates/         # Word template files
    └── config-template.yaml