@v1hz/md2docx 1.6.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  <h1 align="center">md2docx</h1>
6
6
 
7
7
  <p align="center">
8
- 基于 pandoc 的 Markdown 转 Word 工具,自动格式化 Markdown,支持自定义样式,AI 友好,用户友好。
8
+ 基于 Pandoc 的 Markdown 转 Word 工具。在转换前规范文档结构、补充编号、渲染 Mermaid,并通过可定制的 Word 样式生成 DOCX。
9
9
  </p>
10
10
 
11
11
  <p align="center">
@@ -17,160 +17,339 @@
17
17
 
18
18
  ## 功能
19
19
 
20
- Markdown 转换为格式精美的 Word 文档,自动处理:
20
+ | 功能 | 说明 |
21
+ | ----------------- | ------------------------------------------------------------------ |
22
+ | 文档标题 | 从 YAML frontmatter、H1 或文件名提取标题 |
23
+ | 标题层级归一化 | 将最浅标题归一化为 H1,并修复标题层级跳跃 |
24
+ | 标题编号 | 生成 `1`、`1.1`、`1.1.1` 等编号,并可剥离常见的已有中英文编号 |
25
+ | 表格与图片编号 | 自动生成“表 1”“图 1:标题”等题注 |
26
+ | Mermaid 图表 | 使用 beautiful-mermaid 和 resvg-wasm 将 Mermaid 渲染为高 DPI PNG |
27
+ | Word 样式 | 根据 JSON 样式生成 Pandoc reference DOCX,也可从现有 DOCX 提取样式 |
28
+ | Markdown 格式化 | 可只运行预处理流水线,输出格式化后的 Markdown |
29
+ | 集中缓存 | 中间文件统一存储到 `~/.md2docx/`,不会在当前目录创建 `tmp/` |
30
+ | Node 与可执行版本 | 支持 npm CLI,也支持构建不依赖 Node.js/Bun 的平台可执行文件 |
21
31
 
22
- | 功能 | 说明 |
23
- | ------------------ | ----------------------------------------------------------- |
24
- | **文档标题** | 从 frontmatter、H1 或文件名自动提取 |
25
- | **标题层级归一化** | 修正标题层级跳跃,确保从 H1 开始连续递增 |
26
- | **标题编号** | 为标题添加多级编号(1、1.1、1.1.1 …),支持剥离已有编号 |
27
- | **表格编号** | 自动为表格添加编号(表 1、表 2 …) |
28
- | **图片编号** | 为独立图片添加编号(图 1、图 2 …) |
29
- | **Mermaid 图表** | 将 Mermaid 代码块渲染为 PNG 图片 |
30
- | **Word 导出** | 集成 pandoc,传入自定义样式模板,一键生成 .docx |
31
- | **样式定制** | 通过 `config/style.json` 定义文档样式,支持从模板 docx 提取 |
32
- | **web 配置编辑器** | 浏览器中可视化编辑配置 |
32
+ ## 安装方式
33
33
 
34
- ## 安装
34
+ ### npm CLI
35
35
 
36
- **前置依赖**:[Bun](https://bun.sh) | [Pandoc](https://pandoc.org)
36
+ 前置依赖:
37
+
38
+ - [Node.js 22.12+](https://nodejs.org/)
39
+ - [Pandoc](https://pandoc.org/installing.html),并确保 `pandoc` 可通过 `PATH` 调用
37
40
 
38
41
  ```bash
39
42
  npm install -g @v1hz/md2docx
40
- md2docx docs/example.md
43
+ md2docx --version
44
+ md2docx report.md
41
45
  ```
42
46
 
43
- 也可通过 `npx @v1hz/md2docx` 直接运行。
47
+ 也可以不全局安装:
48
+
49
+ ```bash
50
+ npx @v1hz/md2docx report.md
51
+ ```
44
52
 
45
53
  ## 快速开始
46
54
 
47
55
  ```bash
48
- # 处理 Markdown 并生成 Word 文档
49
- md2docx docs/example.md
56
+ # 只有输入路径时,可以省略 --file
57
+ md2docx report.md
58
+
59
+ # 使用任何转换选项时,输入必须通过 --file 指定
60
+ md2docx --file report.md --output output/report.docx --force
50
61
 
51
- # 只预处理,不调用 pandoc
52
- md2docx docs/example.md --pandoc.enabled false
62
+ # 使用自定义配置和样式
63
+ md2docx -f report.md -c config.json -s style.json
53
64
 
54
- # 指定输出路径
55
- md2docx docs/example.md -o output/example.docx
65
+ # 只执行 Markdown 预处理
66
+ md2docx format -f report.md
56
67
 
57
- # 打开 web 网页自定义配置
58
- md2docx --web
68
+ # 导出内置默认配置和样式
69
+ md2docx export config
70
+ md2docx export style
59
71
 
60
- # 使用自定义配置文件
61
- md2docx docs/example.md --config ./my-config.json
72
+ # 从现有 DOCX 提取样式
73
+ md2docx export style -f template.docx
62
74
 
63
- # 清除缓存(预处理中间产物、样式模板等)
75
+ # 删除 ~/.md2docx 中的中间文件和缓存
64
76
  md2docx clean
65
77
  ```
66
78
 
67
- ## 配置
79
+ 所有写文件命令默认拒绝覆盖已有文件。确认覆盖时显式传入 `--force`。
80
+
81
+ ## CLI 参考
82
+
83
+ ```shell
84
+ md2docx <markdown>
85
+ md2docx -f <markdown> [转换选项]
86
+ md2docx format -f <markdown> [选项]
87
+ md2docx export config [选项]
88
+ md2docx export style [选项]
89
+ md2docx clean
90
+ ```
91
+
92
+ ### 转换
68
93
 
69
- 配置文件位于 `config/config.json`,通过 JSON Schema 提供 IDE 校验。
94
+ | 参数 | 说明 |
95
+ | --------------------- | ---------------------------------------- |
96
+ | `<markdown>` | 位置参数;仅在没有其他转换选项时允许使用 |
97
+ | `-f, --file <path>` | Markdown 输入文件 |
98
+ | `-c, --config <path>` | 自定义配置 JSON |
99
+ | `-s, --style <path>` | 自定义样式 JSON |
100
+ | `-o, --output <path>` | DOCX 输出路径 |
101
+ | `--force` | 覆盖已有输出 |
102
+ | `-h, --help` | 显示帮助 |
103
+ | `-v, --version` | 显示版本号 |
70
104
 
71
- 所有配置项均可通过命令行覆盖:
105
+ 位置参数不能和 `--file`、`--config`、`--style`、`--output` 或 `--force` 混用。例如:
72
106
 
73
107
  ```bash
74
- md2docx docs/example.md --figureCaption.enabled false
75
- ```
76
-
77
- | 配置项 | 说明 | 默认值 |
78
- | -------------------------------- | ------------------------------------------------------------ | --------------------- |
79
- | `detectTitle.enabled` | 自动设置文档标题 | `true` |
80
- | `detectTitle.strategy` | 标题来源策略:`first-h1` / `single-h1` / `filename` / `none` | `"first-h1"` |
81
- | `normalizeHeadings.enabled` | 自动修正标题层级 | `true` |
82
- | `numberHeadings.enabled` | 自动为标题编号(开启时自动启用 normalizeHeadings) | `true` |
83
- | `numberHeadings.detectExisting` | 重新编号前移除已有编号 | `true` |
84
- | `numberHeadings.useBuiltinRules` | 识别常见的中文和数字编号 | `true` |
85
- | `figureCaption.enabled` | 自动为图片编号(格式:`图 {n}`) | `true` |
86
- | `figureCaption.format` | 图片编号格式 | `"图 {n}"` |
87
- | `figureCaption.separator` | 编号与标题之间的分隔符 | `":"` |
88
- | `tableCaption.enabled` | 自动为表格编号(格式:`表 {n}`) | `true` |
89
- | `tableCaption.format` | 表格编号格式 | `"表 {n}"` |
90
- | `tableCaption.separator` | 编号与标题之间的分隔符 | `" "` |
91
- | `renderMermaid.enabled` | 渲染 Mermaid 图表为 PNG | `true` |
92
- | `renderMermaid.theme` | 图表主题 | `"tokyo-night-light"` |
93
- | `renderMermaid.density` | 图片清晰度(DPI,最小 72) | `200` |
94
- | `pandoc.enabled` | 生成 Word 文档 | `true` |
95
- | `pandoc.outputName` | 输出文件名,`{file_name}` 代表源文件名 | `"{file_name}.docx"` |
108
+ md2docx report.md # 正确
109
+ md2docx report.md --force # 错误
110
+ md2docx -f report.md --force # 正确
111
+ ```
96
112
 
97
- ## 样式定制
113
+ ### format
98
114
 
99
- `config/style.json` 定义了 docx 输出的全部样式,包括字体、字号、颜色、缩进、间距等。
115
+ `format` 运行完整 Markdown 预处理,但不生成 DOCX,也不调用 Pandoc。
100
116
 
101
- ### 从模板 docx 提取样式
117
+ | 参数 | 说明 |
118
+ | --------------------- | ------------------------------------------- |
119
+ | `-f, --file <path>` | 必填,Markdown 输入文件 |
120
+ | `-c, --config <path>` | 自定义配置 JSON |
121
+ | `-o, --output <path>` | 输出 Markdown,默认 `<文件名>_formatted.md` |
122
+ | `--force` | 覆盖已有输出 |
102
123
 
103
- 如果你有一个排版精美的 docx 模板,可以提取其样式:
124
+ ### export
104
125
 
105
126
  ```bash
106
- bun run src/style/extract.ts
127
+ md2docx export config [-o config.json] [--force]
128
+ md2docx export style [-f template.docx] [-o style.json] [--force]
107
129
  ```
108
130
 
109
- 提取后修改 `config/style.json`,转换时会自动使用这些样式生成输出文档。
131
+ `export config` 导出内置默认配置。`export style` 不带 `--file` 时导出内置默认样式;指定 DOCX 时从该文档提取样式。
110
132
 
111
- ### 手动维护样式
133
+ ### clean
112
134
 
113
- 可直接编辑 `config/style.json`。支持以下样式配置:
135
+ ```bash
136
+ md2docx clean
137
+ ```
114
138
 
115
- - **文档默认样式**(`default.document`):全局字体、字号、段落间距
116
- - **内置样式覆盖**(`default.heading1` … `default.heading6`、`default.title` 等)
117
- - **自定义段落样式**(`paragraphStyles`)
118
- - **自定义字符样式**(`characterStyles`)
139
+ `clean` 只允许删除当前用户主目录下严格匹配的 `~/.md2docx/`。如果目标是符号链接,只删除链接本身。命令可重复执行;目录不存在时正常退出。
119
140
 
120
- 详细的样式字段定义参考 [docx 包文档](https://docx.js.org)。
141
+ npm 卸载不会可靠地清理用户数据。卸载前如需清理,请显式运行:
121
142
 
122
- ## 处理流水线
143
+ ```bash
144
+ md2docx clean
145
+ npm uninstall -g @v1hz/md2docx
146
+ ```
123
147
 
124
- 项目遵循单向处理流水线,每个步骤职责单一。
148
+ ## 默认输出
125
149
 
150
+ ```text
151
+ md2docx report.md → ./report.docx
152
+ md2docx -f report.md → ./report.docx
153
+ md2docx format -f report.md → ./report_formatted.md
154
+ md2docx export config → ./config.json
155
+ md2docx export style → ./style.json
156
+ md2docx export style -f template.docx → ./template_style.json
126
157
  ```
158
+
159
+ ## 中间文件与缓存
160
+
161
+ 所有运行时资源统一位于:
162
+
163
+ ```text
164
+ ~/.md2docx/
165
+ ├── preprocess/
166
+ │ └── <输入文件名>-<绝对路径哈希>/
167
+ │ ├── <输入文件名>_formatted.md
168
+ │ └── mermaid_*.png
169
+ ├── resources/
170
+ │ ├── config.json
171
+ │ ├── style.json
172
+ │ └── add-inline-code.lua
173
+ └── style/
174
+ └── <样式内容哈希>.docx
175
+ ```
176
+
177
+ 输入文件的绝对路径参与目录哈希,因此不同目录下的同名 Markdown 不会复用中间文件。内置资源会在需要时写入 `resources/`;样式模板按样式内容哈希缓存。
178
+
179
+ 输出 DOCX 和显式导出的配置、样式仍写到用户指定位置或当前工作目录,不会写入缓存目录。
180
+
181
+ ## 配置
182
+
183
+ 内置配置来自 `config/config.json`,并由 `config/config.schema.json` 提供 JSON Schema。推荐先导出再编辑:
184
+
185
+ ```bash
186
+ md2docx export config
187
+ md2docx -f report.md -c config.json
188
+ ```
189
+
190
+ CLI 不支持覆盖单个配置项,所有配置都通过 JSON 文件管理。
191
+
192
+ | 配置项 | 说明 | 默认值 |
193
+ | -------------------------------- | ---------------------------------------------- | --------------------- |
194
+ | `detectTitle.enabled` | 自动设置文档标题 | `true` |
195
+ | `detectTitle.strategy` | `first-h1` / `single-h1` / `filename` / `none` | `"first-h1"` |
196
+ | `normalizeHeadings.enabled` | 修正标题起始层级与层级跳跃 | `true` |
197
+ | `numberHeadings.enabled` | 为标题添加多级编号 | `true` |
198
+ | `numberHeadings.detectExisting` | 重新编号前移除已识别的编号 | `true` |
199
+ | `numberHeadings.useBuiltinRules` | 使用内置中文和数字编号识别规则 | `true` |
200
+ | `figureCaption.enabled` | 为独立图片添加题注 | `true` |
201
+ | `figureCaption.format` | 图片编号格式 | `"图 {n}"` |
202
+ | `figureCaption.separator` | 图片编号与标题之间的分隔符 | `":"` |
203
+ | `tableCaption.enabled` | 为表格添加题注 | `true` |
204
+ | `tableCaption.format` | 表格编号格式 | `"表 {n}"` |
205
+ | `tableCaption.separator` | 表格编号与标题之间的分隔符 | `" "` |
206
+ | `renderMermaid.enabled` | 将 Mermaid 渲染为 PNG | `true` |
207
+ | `renderMermaid.theme` | beautiful-mermaid 主题 | `"tokyo-night-light"` |
208
+ | `renderMermaid.density` | PNG 输出 DPI,最小值 72 | `200` |
209
+
210
+ ## 样式定制
211
+
212
+ `config/style.json` 定义 DOCX 的默认样式、标题样式、段落样式和字符样式。转换时,项目用 `docx` 生成 reference DOCX,再通过 Pandoc 的 `--reference-doc` 应用样式。
213
+
214
+ ### 从现有 DOCX 提取
215
+
216
+ ```bash
217
+ md2docx export style -f template.docx
218
+ md2docx -f report.md -s template_style.json
219
+ ```
220
+
221
+ ### 手动维护
222
+
223
+ 主要区域包括:
224
+
225
+ - `default.document`:全局字体、字号与段落设置
226
+ - `default.heading1` 至 `default.heading6`:标题样式
227
+ - `default.title`:文档标题样式
228
+ - `paragraphStyles`:自定义段落样式
229
+ - `characterStyles`:自定义字符样式
230
+ - `tableStylesXml`:从 DOCX 提取并重新注入的表格样式 XML
231
+
232
+ 基于 `a0`(Body Text)的样式会继承首行缩进。如果子样式不需要缩进,应在 `indent` 中显式清零。
233
+
234
+ ## Mermaid 渲染
235
+
236
+ 渲染流程如下:
237
+
238
+ ```text
239
+ Mermaid
240
+ → beautiful-mermaid
241
+ → SVG
242
+ → 内联 CSS var() / color-mix()
243
+ → @resvg/resvg-wasm
244
+ → 写入正确的 PNG DPI 元数据
245
+ → PNG
246
+ ```
247
+
248
+ resvg 不直接支持 beautiful-mermaid 输出中的所有 CSS 自定义属性,因此转换前会解析:
249
+
250
+ - `var(--name)`
251
+ - `var(--name, fallback)`
252
+ - 嵌套 fallback
253
+ - `color-mix(in srgb, ...)`
254
+ - 三位和六位十六进制颜色
255
+
256
+ Windows 会显式加载微软雅黑、Arial 和 Consolas;macOS 与 Linux 使用各自的候选系统字体。PNG 像素尺寸和 `pHYs` DPI 元数据都与 `renderMermaid.density` 保持一致。
257
+
258
+ 运行时不依赖 Sharp。Sharp 只作为开发依赖,用于测试中比较 resvg 与旧渲染结果,不会打入 npm 运行时包或平台 EXE。
259
+
260
+ ## 处理流水线
261
+
262
+ ```text
127
263
  Markdown
128
264
 
129
265
  解析 AST
130
266
 
131
- addTitle() ← 提取文档标题
267
+ addTitle()
132
268
 
133
- normalizeHeadings() ← 修正标题层级(最小深度 → H1,消除跳跃)
269
+ normalizeHeadings()
134
270
 
135
- numberHeadings() ← 添加标题编号(1 / 1.1 / 1.1.1 …)
271
+ numberHeadings()
136
272
 
137
- numberTables() ← 添加表格编号(表 1、表 2 …)
273
+ numberTables()
138
274
 
139
- renderMermaid() ← Mermaid 代码块 → PNG 图片
275
+ renderMermaid()
140
276
 
141
- numberPictures() ← 添加图片编号(图 1、图 2 …)
277
+ numberPictures()
142
278
 
143
279
  序列化 Markdown
144
280
 
145
- 生成样式模板 docx ← 根据 config/style.json 生成 pandoc reference-doc
281
+ 生成或复用 reference DOCX
282
+
283
+ Pandoc + Lua filter
146
284
 
147
- pandoc → DOCX ← 以 --reference-doc 传入样式模板
285
+ DOCX
148
286
  ```
149
287
 
150
- ## 开发
288
+ `numberTables()` 必须先于 Mermaid 渲染;`numberPictures()` 必须后于 Mermaid 渲染,这样 Mermaid 生成的图片也能获得图题。
151
289
 
152
- ### 从源码运行
290
+ ## 构建
291
+
292
+ 从源码开发需要 [Bun](https://bun.sh/)。
153
293
 
154
294
  ```bash
155
295
  git clone https://github.com/WXY-V1hZ/md2docx.git
156
296
  cd md2docx
157
297
  bun install
158
- bun run src/index.ts docs/example.md
298
+
299
+ # 从源码运行
300
+ bun run src/index.ts report.md
301
+
302
+ # 测试和静态检查
303
+ bun test
304
+ bun check
159
305
  ```
160
306
 
161
- ### 命令
307
+ ### npm 构建
162
308
 
163
309
  ```bash
164
- # 测试
165
- bun test
310
+ bun run build
311
+ ```
166
312
 
167
- # 类型检查 + 代码检查 + 格式检查
168
- bun check
313
+ 输出:
314
+
315
+ ```text
316
+ dist/
317
+ ├── index.js
318
+ └── index_bg.wasm
319
+ ```
320
+
321
+ 依赖会打包进 `index.js`,resvg WASM 作为相邻资源输出。`prepack` 会自动执行此构建。
322
+
323
+ ### 平台可执行文件
324
+
325
+ ```bash
326
+ bun run build:exe
327
+ ```
328
+
329
+ Windows 输出为 `dist/md2docx.exe`。该程序只适用于构建目标对应的操作系统和 CPU 架构。
330
+
331
+ `build` 和 `build:exe` 都会先删除整个 `dist/`,因此两种产物不会同时保留。尤其不要依赖手工生成的 EXE 参与 `npm publish`:发布时 `prepack` 会重新生成 npm 所需的 `index.js` 和 WASM。
169
332
 
170
- # 清除缓存
171
- bun run src/index.ts clean
333
+ ## 常见问题
334
+
335
+ ### 找不到 Pandoc
336
+
337
+ 先检查:
338
+
339
+ ```bash
340
+ pandoc --version
341
+ ```
342
+
343
+ 如果命令不存在,请从 [Pandoc 官方安装页](https://pandoc.org/installing.html) 安装,并重新打开终端使 `PATH` 生效。
344
+
345
+ ### 输出文件已存在
346
+
347
+ 默认不会覆盖文件。确认目标可以覆盖后使用:
348
+
349
+ ```bash
350
+ md2docx -f report.md --force
172
351
  ```
173
352
 
174
353
  ## 许可
175
354
 
176
- 本项目基于 GNU General Public License v3.0 开源 — 详见 [LICENSE](LICENSE)
355
+ md2docx 以 [GNU GPL v3.0](LICENSE) 发布。
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "./config.schema.json",
2
+ "$schema": "https://raw.githubusercontent.com/WXY-V1hZ/md2docx/main/config/config.schema.json",
3
3
  "figureCaption": {
4
4
  "enabled": true,
5
5
  "format": "图 {n}",
@@ -26,9 +26,5 @@
26
26
  "detectTitle": {
27
27
  "enabled": true,
28
28
  "strategy": "first-h1"
29
- },
30
- "pandoc": {
31
- "enabled": true,
32
- "outputName": "{file_name}.docx"
33
29
  }
34
30
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://raw.githubusercontent.com/WXY-V1hZ/md2docx/main/config.schema.json",
3
+ "$id": "https://raw.githubusercontent.com/WXY-V1hZ/md2docx/main/config/config.schema.json",
4
4
  "title": "md2docx 配置",
5
5
  "description": "md2docx 默认设置",
6
6
  "type": "object",
@@ -117,24 +117,6 @@
117
117
  },
118
118
  "required": ["enabled", "theme", "density"]
119
119
  },
120
- "pandoc": {
121
- "description": "Word 导出",
122
- "type": "object",
123
- "additionalProperties": false,
124
- "properties": {
125
- "enabled": {
126
- "description": "生成 Word 文档",
127
- "type": "boolean",
128
- "default": true
129
- },
130
- "outputName": {
131
- "description": "输出文件名,{file_name} 代表源文件名",
132
- "type": "string",
133
- "default": "{file_name}.docx"
134
- }
135
- },
136
- "required": ["enabled", "outputName"]
137
- },
138
120
  "detectTitle": {
139
121
  "description": "文档标题",
140
122
  "type": "object",
@@ -167,7 +149,6 @@
167
149
  "normalizeHeadings",
168
150
  "numberHeadings",
169
151
  "renderMermaid",
170
- "detectTitle",
171
- "pandoc"
152
+ "detectTitle"
172
153
  ]
173
154
  }
@@ -0,0 +1,6 @@
1
+ -- Author: Achuan-2
2
+ function Code(el)
3
+ -- 为行内代码添加一个自定义的 Word 样式名称
4
+ return pandoc.Span(el.text, {["custom-style"] = "Inline Code"})
5
+ end
6
+ return { Code = Code }