@deepwhale-cn/dsh-cn-doc-formatter
安装
dsh plugin --profile web add @deepwhale-cn/dsh-cn-doc-formatter
中文公文排版 —— 给 DeepSeek Harness 用的 skill 插件。
按 GB/T 9704-2012《党政机关公文格式》 生成 .docx / .pdf / .txt,
并自带输出自检——生成完逐项核对页边距、字号、行距、字体、页面尺寸,
不符合规范就报错,而不是让你交付一份看起来差不多、实际不合规的文件。
⚠️ 本插件不含字体,字体需你自备
这是刻意的设计,不是缺失。
公文规范要求的仿宋(方正仿宋等)是商业字体。其授权允许你在文档中使用,
但不允许再分发字体文件本身。所以本插件只做「排版引擎」,字体由你提供:
# 方式一:直接指定字体文件(推荐,最明确)
export DSH_CN_FANGSONG=/path/to/仿宋.ttf
export DSH_CN_FANGSONG_BOLD=/path/to/仿宋加粗.ttf # 可选
# 方式二:指定一个目录,脚本在其中按文件名查找
export DSH_CN_FONT_DIR=~/my-fonts
也可以直接装进系统字体目录(一次装好处处可用):
| 系统 | 目录 |
|---|
| macOS | ~/Library/Fonts/ |
| Windows | C:\Windows\Fonts\ |
| Linux | ~/.fonts/ 或 ~/.local/share/fonts/ |
装 WPS Office 也行 —— 它自带方正仿宋。
找不到字体时不会静默失败:PDF 退回系统宋体,并在 stderr 打印上面这张获取指引。
docx 只在文件里声明字体族名(由你机器上的 Word 渲染),不依赖字体文件。
一个细节:如果你只有常规仿宋、没有加粗体,标题会继续使用仿宋(只是不加粗),
而不是换成宋体。因为「全文统一仿宋」是硬规范,宁可字重不够也不换字体族。
reportlab 不做合成粗体,这是引擎限制。
它管什么
| 项目 | 规范值 |
|---|
| 标题 | 仿宋,二号(22pt)加粗,居中,行距 33–36 磅 |
| 一/二/三/四级标题 | 仿宋,三号(16pt)加粗,左空二字 |
| 正文 | 仿宋,四号(14pt),固定行距 28 磅,首行缩进严格 2 字 |
| 版头(可选) | 份号 / 密级 / 紧急程度 / 发文字号,仿宋三号 |
| 署名与日期 | 距正文下空 3 行,日期阿拉伯数字右空 4 字 |
| 页码 | 「- 1 -」,单页居右空一字、双页居左空一字 |
| 页边距 | 上 3.7 / 下 3.5 / 左 2.8 / 右 2.6 cm |
| 文档网格 | 每面 22 行、每行 28 字 |
不出现任何 AI 痕迹:无水印、无生成标记、无作者信息、无版本说明、无注释。
安装
dsh plugin --profile <profile> add @deepwhale-cn/dsh-cn-doc-formatter
然后重启 dsh。技能会在 agent 需要时自动可用。
Python 依赖
排版脚本是 Python,需要这些库:
pip install python-docx reportlab fontTools pypdf
| 库 | 用途 |
|---|
python-docx | 生成 Word 文档 |
reportlab | 生成 PDF |
fontTools | 探测本机已装字体(读字体 name 表) |
pypdf | 自检时校验 PDF 是否真的嵌入了目标字体 |
它比「套个模板」多做了什么
1. 输出自检(verify_output.py)
生成完不是结束。自检会真的打开产出文件,逐项核对:
── 公文.docx
✅ 上边距 3.70cm ✓ ✅ 标题 22pt 加粗 ✓
✅ 正文 14.0pt / 行距 28pt ✓
✅ 全文统一字体:FangS-SC ✓
── 公文.pdf
✅ 嵌入字体:/AAAAAA+FangS-SC, /AAAAAA+FangS-SC-Bold
✅ 页面 A4 21.0×29.7cm ✓
退出码 0 = 通过,1 = 有不符合项 —— 可以直接用在 CI 或交付卡口上。
2. Markdown 输入适配(md_adapter.py)
内容常以 Markdown 写就,直接喂给脚本会丢失层级(整篇被当正文):
| Markdown | 转成 | 公文层级 |
|---|
## 一、小节 | 一、小节 | 一级标题 |
### 1.1 小节 | (一)小节 | 二级标题 |
#### 更深 | 1. 小节 | 三级标题 |
- 列表项 | 正文 | 正文 |
| 表格 | | 表头:值;表头:值。 | 正文 |
它还会把同一段内的软换行合并成一行 —— 源文档常手动折行,
逐行当独立段落会在断句处留下孤立标点(如单独一行的「、」)。
3. 跨平台字体探测
早期实现用 fc-list 探测字体,而 macOS 不预装 fontconfig,
异常被吞掉后恒返回「字体不存在」,于是即使装了仿宋也检测不到,会始终走回退分支。
本版改为直接读字体文件的 name 表,macOS / Windows / Linux 通用。
用法
技能正文里有完整命令。核心三条:
# 生成 Word / PDF
python "<插件目录>/scripts/docx_formatter.py" --output <目录> \
--title "标题" --body "正文..." --sender "发文机关" --date "2026年9月25日"
python "<插件目录>/scripts/pdf_formatter.py" --output <目录> \
--title "标题" --body "正文..." --sender "发文机关" --date "2026年9月25日"
# 输出自检(不要跳过)
python "<插件目录>/scripts/verify_output.py" --dir <输出目录>
⚠️ 早期文档里的 --type notice 参数并不存在,加上会直接报
unrecognized arguments。文种由内容决定,脚本不做区分。本版已修正文档。
设计取舍
不分发字体。 见上文——这不是省事,是避免把商业字体的再分发风险
转嫁给每一个使用者。
不联网。 排版、字体探测、自检全部在本地完成,不把文档内容发往任何第三方服务。
文种不参与排版。 通知 / 报告 / 函 / 决定的排版规范是一致的,
差别只在正文怎么写。脚本不为文种分叉,避免维护一堆看似不同实则相同的模板。
与其它插件的关系
按 DSH 插件生态倡议书
的三条原则开发:组合优先、声明清晰、兼容优先。不假设、不覆盖其它插件的内部实现。
许可
MIT。本软件不包含任何字体文件;使用者在文档中选用何种字体,由使用者自行负责
取得该字体的合法授权。