imprint-pdf 0.11.0__tar.gz

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.
Files changed (56) hide show
  1. imprint_pdf-0.11.0/LICENSE +21 -0
  2. imprint_pdf-0.11.0/PKG-INFO +230 -0
  3. imprint_pdf-0.11.0/README.md +204 -0
  4. imprint_pdf-0.11.0/imprint/__init__.py +3 -0
  5. imprint_pdf-0.11.0/imprint/__main__.py +4 -0
  6. imprint_pdf-0.11.0/imprint/cli.py +138 -0
  7. imprint_pdf-0.11.0/imprint/converter.py +504 -0
  8. imprint_pdf-0.11.0/imprint/fonts.py +55 -0
  9. imprint_pdf-0.11.0/imprint/mcp_server.py +108 -0
  10. imprint_pdf-0.11.0/imprint/recommend.py +130 -0
  11. imprint_pdf-0.11.0/imprint/render.py +93 -0
  12. imprint_pdf-0.11.0/imprint/templates/book.md +22 -0
  13. imprint_pdf-0.11.0/imprint/templates/gongwen.md +38 -0
  14. imprint_pdf-0.11.0/imprint/templates/ieee.md +66 -0
  15. imprint_pdf-0.11.0/imprint/templates/letter.md +27 -0
  16. imprint_pdf-0.11.0/imprint/templates/paper.md +77 -0
  17. imprint_pdf-0.11.0/imprint/templates/report.md +39 -0
  18. imprint_pdf-0.11.0/imprint/templates/resume.md +30 -0
  19. imprint_pdf-0.11.0/imprint/templates/techdoc.md +46 -0
  20. imprint_pdf-0.11.0/imprint/theme.py +527 -0
  21. imprint_pdf-0.11.0/imprint/themes/__init__.py +42 -0
  22. imprint_pdf-0.11.0/imprint/themes/academic.json +40 -0
  23. imprint_pdf-0.11.0/imprint/themes/amber.json +39 -0
  24. imprint_pdf-0.11.0/imprint/themes/catppuccin.json +39 -0
  25. imprint_pdf-0.11.0/imprint/themes/coffee.json +39 -0
  26. imprint_pdf-0.11.0/imprint/themes/coral.json +39 -0
  27. imprint_pdf-0.11.0/imprint/themes/gongwen.json +40 -0
  28. imprint_pdf-0.11.0/imprint/themes/graphite.json +39 -0
  29. imprint_pdf-0.11.0/imprint/themes/ieee.json +40 -0
  30. imprint_pdf-0.11.0/imprint/themes/ink.json +39 -0
  31. imprint_pdf-0.11.0/imprint/themes/jade.json +39 -0
  32. imprint_pdf-0.11.0/imprint/themes/lavender.json +39 -0
  33. imprint_pdf-0.11.0/imprint/themes/midnight.json +39 -0
  34. imprint_pdf-0.11.0/imprint/themes/minimal.json +39 -0
  35. imprint_pdf-0.11.0/imprint/themes/mint.json +39 -0
  36. imprint_pdf-0.11.0/imprint/themes/modern.json +39 -0
  37. imprint_pdf-0.11.0/imprint/themes/mono.json +39 -0
  38. imprint_pdf-0.11.0/imprint/themes/newspaper.json +39 -0
  39. imprint_pdf-0.11.0/imprint/themes/nord.json +39 -0
  40. imprint_pdf-0.11.0/imprint/themes/ocean.json +39 -0
  41. imprint_pdf-0.11.0/imprint/themes/pine.json +39 -0
  42. imprint_pdf-0.11.0/imprint/themes/rose.json +39 -0
  43. imprint_pdf-0.11.0/imprint/themes/sand.json +39 -0
  44. imprint_pdf-0.11.0/imprint/themes/sepia.json +39 -0
  45. imprint_pdf-0.11.0/imprint/themes/wine.json +39 -0
  46. imprint_pdf-0.11.0/imprint/validator.py +518 -0
  47. imprint_pdf-0.11.0/imprint_pdf.egg-info/PKG-INFO +230 -0
  48. imprint_pdf-0.11.0/imprint_pdf.egg-info/SOURCES.txt +54 -0
  49. imprint_pdf-0.11.0/imprint_pdf.egg-info/dependency_links.txt +1 -0
  50. imprint_pdf-0.11.0/imprint_pdf.egg-info/entry_points.txt +3 -0
  51. imprint_pdf-0.11.0/imprint_pdf.egg-info/requires.txt +13 -0
  52. imprint_pdf-0.11.0/imprint_pdf.egg-info/top_level.txt +1 -0
  53. imprint_pdf-0.11.0/pyproject.toml +41 -0
  54. imprint_pdf-0.11.0/setup.cfg +4 -0
  55. imprint_pdf-0.11.0/tests/test_mcp.py +63 -0
  56. imprint_pdf-0.11.0/tests/test_smoke.py +211 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Imprint contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,230 @@
1
+ Metadata-Version: 2.4
2
+ Name: imprint-pdf
3
+ Version: 0.11.0
4
+ Summary: AI-native, print-grade Chinese PDF generator: Markdown in, publisher-quality PDF out, with a 0-100 print-quality report.
5
+ Author: Imprint
6
+ License: MIT
7
+ Keywords: pdf,markdown,chinese,typography,weasyprint,print
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Topic :: Documentation
10
+ Classifier: Topic :: Printing
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: markdown-it-py>=3.0
15
+ Requires-Dist: mdit-py-plugins>=0.4
16
+ Requires-Dist: WeasyPrint>=61
17
+ Requires-Dist: PyYAML>=6.0
18
+ Requires-Dist: Pygments>=2.15
19
+ Requires-Dist: pdfplumber>=0.11
20
+ Requires-Dist: PyMuPDF>=1.24
21
+ Provides-Extra: charts
22
+ Requires-Dist: mermaidx>=0.1; extra == "charts"
23
+ Provides-Extra: mcp
24
+ Requires-Dist: mcp<2.0,>=1.2; extra == "mcp"
25
+ Dynamic: license-file
26
+
27
+ # Imprint · 印记
28
+
29
+ > **Markdown 进,出版社级 PDF 出,自带 0–100 印刷级质检报告。**
30
+
31
+ [English](README.en.md) · [简体中文](README.md)
32
+
33
+ Imprint 是一个 AI 原生的中文印刷级 PDF 生成器。它把 Markdown 当成草稿,把 PDF 当成成品——按出版物的标准排版:宋体正文、黑体标题、首行缩进、标点避头尾、目录页码精确、表格跨页重复表头、代码不截断。生成之后,机器自动给这份 PDF 打分:**0–100 印刷级评分,逐项给出证据**。
34
+
35
+ <p align="center">
36
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/imprint-pdf.svg">
37
+ <img alt="npm" src="https://img.shields.io/npm/v/imprint-pdf.svg">
38
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/imprint-pdf.svg">
39
+ <img alt="License" src="https://img.shields.io/pypi/l/imprint-pdf.svg">
40
+ <img alt="Downloads" src="https://img.shields.io/pypi/dm/imprint-pdf.svg">
41
+ <img alt="CI" src="https://github.com/263311487-ux/imprint-pdf/actions/workflows/ci.yml/badge.svg">
42
+ <img alt="Stars" src="https://img.shields.io/github/stars/263311487-ux/imprint-pdf">
43
+ </p>
44
+
45
+ ## 快速开始(零配置)
46
+
47
+ ```bash
48
+ # 方式一:一行命令(自动安装引擎,跨平台)
49
+ npx imprint-pdf 论文.md
50
+
51
+ # 方式二:pip 安装
52
+ pip install imprint-pdf
53
+ imprint 论文.md
54
+
55
+ # 常用命令
56
+ npx imprint-pdf --new report # 从模板起稿
57
+ npx imprint-pdf --list-themes # 22 套主题
58
+ npx imprint-pdf 论文.md --theme academic --out 论文.pdf
59
+ ```
60
+
61
+ ![封面](examples/qa/sample-01.png)
62
+
63
+ ![目录](examples/qa/sample-02.png)
64
+
65
+ ![正文](examples/qa/sample-04.png)
66
+
67
+ ![提示框](examples/qa/alerts-03.png)
68
+
69
+ ![mermaid 流程图](examples/qa/charts-03.png)
70
+
71
+ ## 主题画廊(22 套 · 全部通过印刷级质检)
72
+
73
+ <p align="center">
74
+ <img src="examples/qa/modern-01.png" width="150" alt="modern"/>
75
+ <img src="examples/qa/academic-01.png" width="150" alt="academic"/>
76
+ <img src="examples/qa/nord-01.png" width="150" alt="nord"/>
77
+ <img src="examples/qa/sepia-01.png" width="150" alt="sepia"/>
78
+ <img src="examples/qa/newspaper-01.png" width="150" alt="newspaper"/>
79
+ </p>
80
+ <p align="center">
81
+ <img src="examples/qa/catppuccin-01.png" width="150" alt="catppuccin"/>
82
+ <img src="examples/qa/mono-01.png" width="150" alt="mono"/>
83
+ <img src="examples/qa/jade-01.png" width="150" alt="jade"/>
84
+ <img src="examples/qa/coffee-01.png" width="150" alt="coffee"/>
85
+ <img src="examples/qa/ocean-01.png" width="150" alt="ocean"/>
86
+ </p>
87
+ <p align="center">
88
+ <img src="examples/qa/lavender-01.png" width="150" alt="lavender"/>
89
+ <img src="examples/qa/rose-01.png" width="150" alt="rose"/>
90
+ <img src="examples/qa/pine-01.png" width="150" alt="pine"/>
91
+ <img src="examples/qa/wine-01.png" width="150" alt="wine"/>
92
+ <img src="examples/qa/graphite-01.png" width="150" alt="graphite"/>
93
+ </p>
94
+ <p align="center">
95
+ <img src="examples/qa/midnight-01.png" width="150" alt="midnight"/>
96
+ <img src="examples/qa/coral-01.png" width="150" alt="coral"/>
97
+ <img src="examples/qa/amber-01.png" width="150" alt="amber"/>
98
+ <img src="examples/qa/mint-01.png" width="150" alt="mint"/>
99
+ <img src="examples/qa/sand-01.png" width="150" alt="sand"/>
100
+ </p>
101
+ <p align="center">
102
+ <img src="examples/qa/minimal-01.png" width="150" alt="minimal"/>
103
+ <img src="examples/qa/ink-01.png" width="150" alt="ink"/>
104
+ <img src="examples/qa/gongwen-01.png" width="150" alt="gongwen 公文"/>
105
+ </p>
106
+
107
+ ## 双栏学术论文模板
108
+
109
+ `imprint --new paper` 一键生成双栏学术论文:摘要/关键词通栏,正文双栏排版,标题不落页尾、表格不跨栏截断、行内公式不断行。
110
+
111
+ <p align="center">
112
+ <img src="examples/qa/paper-03.png" width="260" alt="paper 双栏正文"/>
113
+ <img src="examples/qa/paper-04.png" width="260" alt="paper 双栏图表"/>
114
+ </p>
115
+
116
+ 英文论文用 `imprint --new ieee`:IEEE 风格(Times 10pt 紧凑双栏 + IEEE 蓝),
117
+ `lang: en` 自动切换文档语言标签,Abstract / Index Terms 通栏。
118
+
119
+ <p align="center">
120
+ <img src="examples/qa/ieee-03.png" width="300" alt="ieee 双栏英文论文"/>
121
+ </p>
122
+
123
+ ## 党政机关公文(GB/T 9704 红头文件)
124
+
125
+ `imprint --new gongwen` 一键生成符合《党政机关公文格式》的红头文件:
126
+ 红色发文机关标志、发文字号、红色分隔线(★)、黑体标题、仿宋三号正文、
127
+ 右对齐落款与成文日期。
128
+
129
+ <p align="center">
130
+ <img src="examples/qa/gongwen-01.png" width="300" alt="gongwen 红头文件"/>
131
+ </p>
132
+
133
+ 换肤 = 一行命令:`imprint paper.md --theme wine`;**不指定也会智能换肤**——自动分析内容气质选主题并说明理由(如周报自动用 `graphite`,论文自动用 `academic`)。
134
+
135
+ ## 为什么是 Imprint
136
+
137
+ 大多数 Markdown→PDF 工具(pandoc 默认、md2pdf 系、Chrome 打印)只是"把文字倒进页面"。Imprint 的三个差异点:
138
+
139
+ - **中文印刷级**——严格按《中文排版需求》:避头尾禁则、首行缩进 2 字符、中英文混排字距、孤行寡行控制
140
+ - **设计系统即主题**——每套主题是一组 DTCG 设计令牌(色板/字体配对/间距/装饰),换肤 = 换一行
141
+ - **印刷级质检报告**——每个 PDF 生成后自动评分 0–100,检查文本可选、字体子集嵌入、标点违规、目录页码、PDF/UA 无障碍标签,证据可查
142
+
143
+ ## 快速开始
144
+
145
+ ```bash
146
+ pip install imprint-pdf
147
+ # 图表支持(可选)
148
+ pip install imprint-pdf[charts]
149
+ # MCP server(可选,Agent 一句话出报告)
150
+ pip install imprint-pdf[mcp]
151
+
152
+ imprint paper.md -o paper.pdf
153
+ imprint paper.md --theme sepia --compress
154
+ # 从模板起稿(报告/书籍/简历/技术文档/信函)
155
+ imprint --new report -o my_report.md
156
+ # 启动 MCP server(stdio),供 Claude Code / Cursor / DeepSeek Harness 等接入
157
+ imprint-mcp
158
+ ```
159
+
160
+ 输出结尾是一张质检报告:
161
+
162
+ ```
163
+ 印刷级质检报告
164
+ ==============================================
165
+ ✓ 文本可选 15.0/15.0 平均每页 722 字符
166
+ ✓ 字体子集嵌入 15.0/15.0 5/5 字体已嵌入
167
+ ✓ 元数据完整 3.0/3.0 标题「印记」
168
+ ✓ 标点避头尾 15.0/15.0 0 违规
169
+ ✓ 孤行寡行 9.0/9.0 0 处
170
+ ✓ 目录页码 15.0/15.0 核对 15 条
171
+ ✓ 页码存在 2.0/2.0 8/9 页含页码
172
+ ✓ PDF/UA 标签 3.0/3.0 Tagged PDF
173
+ ✓ 主题字体生效 3.0/3.0 命中 songti
174
+ ✓ 主题对比度 5.0/5.0 正文 17.0:1 …
175
+ ✓ 缺字检测 5.0/5.0 无缺字回退
176
+ ✓ 内容溢出 5.0/5.0 无内容越界
177
+ ✓ 图片清晰度 5.0/5.0 全部达标
178
+ ----------------------------------------------
179
+ 总分 100.0/100 · 等级 A+ · 9 页
180
+ ```
181
+
182
+ ## 特性
183
+
184
+ - **封面 + 目录**:frontmatter 里的 `title / author / date` 自动生成封面,标题自动生成可点击目录(页码精确)
185
+ - **智能换肤**:不指定主题时,按标题/关键词/正文信号自动推荐(含理由);显式指定优先
186
+ - **主题系统**:22 套主题(见下方画廊)——现代杂志 / 学术书卷 / 北欧极简 / 护眼纸色 / 报纸头版 / 柔和粉彩 / 纯黑白 / 玉石绿 / 咖啡暖棕 / 海洋蓝 / 薰衣草紫 / 樱粉 / 松林绿 / 勃艮第酒红 / 石墨灰 / 深夜蓝纸(暗色)/ 珊瑚橙 / 琥珀金 / 薄荷青 / 沙漠沙色 / **极简(minimal)** / **线装书(ink,宣纸+印章红)**,自定义主题 = 一个 JSON 文件
187
+ - **GitHub 风格提示框**:`> [!NOTE]` / `[!TIP]` / `[!WARNING]` / `[!IMPORTANT]` / `[!CAUTION]` 自动渲染为印刷级彩色提示卡,见 `examples/alerts.md`
188
+ - **Mermaid 图表**:` ```mermaid ` 代码块自动渲染为矢量图(中文正常、无限缩放),未装引擎时优雅回退代码块,见 `examples/charts.md`
189
+ - **数学公式**:`$行内公式$` / `$$块级公式$$` 渲染为矢量 SVG(matplotlib mathtext,无数学字体依赖),见 `examples/math.md`
190
+ - **模板系统**:`imprint --new report|book|resume|techdoc|letter|paper|gongwen|ieee` 一键起稿,模板自带对应排版气质(石墨灰报告 / 米黄书稿 / 等宽简历 / 海洋蓝技术文档 / 薰衣草信函 / 双栏学术论文 / 红头公文 / IEEE 英文论文)
191
+ - **图片压缩**:`--compress` 自动降采样超大图并重编码(实测 11.7MB → 1.4MB)
192
+ - **字体体检**:生成前自动检查主题字体本机是否可用,缺失时明确警告
193
+ - **中文规范**:避头尾禁则、首行缩进、中英文混排、英文段落自动连字
194
+ - **表格跨页**:表头自动重复、行不截断
195
+ - **代码高亮**:Pygments 着色、整体换页不截断
196
+ - **缺字检测**:渲染后扫描 LastResort/notdef 回退(豆腐块),脚注、箭头等符号缺字自动暴露
197
+ - **PDF/UA**:默认输出无障碍标签版
198
+ - **AI 原生**:CLI 一行命令;内置 MCP server(`imprint-mcp`),Agent 一句话出报告(tools: render_markdown / list_themes / validate_pdf / new_document)
199
+ - **对比度合规**:每套主题自动通过 WCAG 印刷检查(正文 ≥7:1、小字 ≥4.5:1、装饰 ≥3:1)
200
+
201
+ ## 对比
202
+
203
+ | | pandoc 默认 | Chrome 打印 | Imprint |
204
+ |---|---|---|---|
205
+ | 中文印刷级 | 弱 | 弱 | **按规范** |
206
+ | 设计系统主题 | 无 | 无 | **DTCG tokens** |
207
+ | 质检报告 0–100 | 无 | 无 | **自带** |
208
+ | 数学公式 | 插件级 | 无 | **矢量内嵌** |
209
+ | 模板起稿 | 无 | 无 | **8 套内置** |
210
+ | 双栏学术排版 | 无 | 无 | **内置** |
211
+ | 公文格式(红头文件) | 无 | 无 | **内置** |
212
+ | WCAG 对比度检查 | 无 | 无 | **内置** |
213
+ | PDF/UA 无障碍 | 手动 | 无 | **默认** |
214
+
215
+ ## 文档
216
+
217
+ - [完美 PDF 标准](docs/完美PDF标准.md)——"完美"的定义与验收门槛
218
+ - [极致借鉴清单](docs/极致借鉴清单_技术选型_20260819.md)——每个环节的社区选型与实测结论
219
+
220
+ ## 路线图
221
+
222
+ - 更多主题(minimal / ink 已上线,22 套)
223
+ - npm 分发 `npx imprint`(已上线)
224
+ - 双栏 / 学术模板(已上线)
225
+ - PyPI 发布
226
+ - 更多双栏模板(IEEE / 公文 / 病历等)
227
+
228
+ ## License
229
+
230
+ MIT
@@ -0,0 +1,204 @@
1
+ # Imprint · 印记
2
+
3
+ > **Markdown 进,出版社级 PDF 出,自带 0–100 印刷级质检报告。**
4
+
5
+ [English](README.en.md) · [简体中文](README.md)
6
+
7
+ Imprint 是一个 AI 原生的中文印刷级 PDF 生成器。它把 Markdown 当成草稿,把 PDF 当成成品——按出版物的标准排版:宋体正文、黑体标题、首行缩进、标点避头尾、目录页码精确、表格跨页重复表头、代码不截断。生成之后,机器自动给这份 PDF 打分:**0–100 印刷级评分,逐项给出证据**。
8
+
9
+ <p align="center">
10
+ <img alt="PyPI" src="https://img.shields.io/pypi/v/imprint-pdf.svg">
11
+ <img alt="npm" src="https://img.shields.io/npm/v/imprint-pdf.svg">
12
+ <img alt="Python" src="https://img.shields.io/pypi/pyversions/imprint-pdf.svg">
13
+ <img alt="License" src="https://img.shields.io/pypi/l/imprint-pdf.svg">
14
+ <img alt="Downloads" src="https://img.shields.io/pypi/dm/imprint-pdf.svg">
15
+ <img alt="CI" src="https://github.com/263311487-ux/imprint-pdf/actions/workflows/ci.yml/badge.svg">
16
+ <img alt="Stars" src="https://img.shields.io/github/stars/263311487-ux/imprint-pdf">
17
+ </p>
18
+
19
+ ## 快速开始(零配置)
20
+
21
+ ```bash
22
+ # 方式一:一行命令(自动安装引擎,跨平台)
23
+ npx imprint-pdf 论文.md
24
+
25
+ # 方式二:pip 安装
26
+ pip install imprint-pdf
27
+ imprint 论文.md
28
+
29
+ # 常用命令
30
+ npx imprint-pdf --new report # 从模板起稿
31
+ npx imprint-pdf --list-themes # 22 套主题
32
+ npx imprint-pdf 论文.md --theme academic --out 论文.pdf
33
+ ```
34
+
35
+ ![封面](examples/qa/sample-01.png)
36
+
37
+ ![目录](examples/qa/sample-02.png)
38
+
39
+ ![正文](examples/qa/sample-04.png)
40
+
41
+ ![提示框](examples/qa/alerts-03.png)
42
+
43
+ ![mermaid 流程图](examples/qa/charts-03.png)
44
+
45
+ ## 主题画廊(22 套 · 全部通过印刷级质检)
46
+
47
+ <p align="center">
48
+ <img src="examples/qa/modern-01.png" width="150" alt="modern"/>
49
+ <img src="examples/qa/academic-01.png" width="150" alt="academic"/>
50
+ <img src="examples/qa/nord-01.png" width="150" alt="nord"/>
51
+ <img src="examples/qa/sepia-01.png" width="150" alt="sepia"/>
52
+ <img src="examples/qa/newspaper-01.png" width="150" alt="newspaper"/>
53
+ </p>
54
+ <p align="center">
55
+ <img src="examples/qa/catppuccin-01.png" width="150" alt="catppuccin"/>
56
+ <img src="examples/qa/mono-01.png" width="150" alt="mono"/>
57
+ <img src="examples/qa/jade-01.png" width="150" alt="jade"/>
58
+ <img src="examples/qa/coffee-01.png" width="150" alt="coffee"/>
59
+ <img src="examples/qa/ocean-01.png" width="150" alt="ocean"/>
60
+ </p>
61
+ <p align="center">
62
+ <img src="examples/qa/lavender-01.png" width="150" alt="lavender"/>
63
+ <img src="examples/qa/rose-01.png" width="150" alt="rose"/>
64
+ <img src="examples/qa/pine-01.png" width="150" alt="pine"/>
65
+ <img src="examples/qa/wine-01.png" width="150" alt="wine"/>
66
+ <img src="examples/qa/graphite-01.png" width="150" alt="graphite"/>
67
+ </p>
68
+ <p align="center">
69
+ <img src="examples/qa/midnight-01.png" width="150" alt="midnight"/>
70
+ <img src="examples/qa/coral-01.png" width="150" alt="coral"/>
71
+ <img src="examples/qa/amber-01.png" width="150" alt="amber"/>
72
+ <img src="examples/qa/mint-01.png" width="150" alt="mint"/>
73
+ <img src="examples/qa/sand-01.png" width="150" alt="sand"/>
74
+ </p>
75
+ <p align="center">
76
+ <img src="examples/qa/minimal-01.png" width="150" alt="minimal"/>
77
+ <img src="examples/qa/ink-01.png" width="150" alt="ink"/>
78
+ <img src="examples/qa/gongwen-01.png" width="150" alt="gongwen 公文"/>
79
+ </p>
80
+
81
+ ## 双栏学术论文模板
82
+
83
+ `imprint --new paper` 一键生成双栏学术论文:摘要/关键词通栏,正文双栏排版,标题不落页尾、表格不跨栏截断、行内公式不断行。
84
+
85
+ <p align="center">
86
+ <img src="examples/qa/paper-03.png" width="260" alt="paper 双栏正文"/>
87
+ <img src="examples/qa/paper-04.png" width="260" alt="paper 双栏图表"/>
88
+ </p>
89
+
90
+ 英文论文用 `imprint --new ieee`:IEEE 风格(Times 10pt 紧凑双栏 + IEEE 蓝),
91
+ `lang: en` 自动切换文档语言标签,Abstract / Index Terms 通栏。
92
+
93
+ <p align="center">
94
+ <img src="examples/qa/ieee-03.png" width="300" alt="ieee 双栏英文论文"/>
95
+ </p>
96
+
97
+ ## 党政机关公文(GB/T 9704 红头文件)
98
+
99
+ `imprint --new gongwen` 一键生成符合《党政机关公文格式》的红头文件:
100
+ 红色发文机关标志、发文字号、红色分隔线(★)、黑体标题、仿宋三号正文、
101
+ 右对齐落款与成文日期。
102
+
103
+ <p align="center">
104
+ <img src="examples/qa/gongwen-01.png" width="300" alt="gongwen 红头文件"/>
105
+ </p>
106
+
107
+ 换肤 = 一行命令:`imprint paper.md --theme wine`;**不指定也会智能换肤**——自动分析内容气质选主题并说明理由(如周报自动用 `graphite`,论文自动用 `academic`)。
108
+
109
+ ## 为什么是 Imprint
110
+
111
+ 大多数 Markdown→PDF 工具(pandoc 默认、md2pdf 系、Chrome 打印)只是"把文字倒进页面"。Imprint 的三个差异点:
112
+
113
+ - **中文印刷级**——严格按《中文排版需求》:避头尾禁则、首行缩进 2 字符、中英文混排字距、孤行寡行控制
114
+ - **设计系统即主题**——每套主题是一组 DTCG 设计令牌(色板/字体配对/间距/装饰),换肤 = 换一行
115
+ - **印刷级质检报告**——每个 PDF 生成后自动评分 0–100,检查文本可选、字体子集嵌入、标点违规、目录页码、PDF/UA 无障碍标签,证据可查
116
+
117
+ ## 快速开始
118
+
119
+ ```bash
120
+ pip install imprint-pdf
121
+ # 图表支持(可选)
122
+ pip install imprint-pdf[charts]
123
+ # MCP server(可选,Agent 一句话出报告)
124
+ pip install imprint-pdf[mcp]
125
+
126
+ imprint paper.md -o paper.pdf
127
+ imprint paper.md --theme sepia --compress
128
+ # 从模板起稿(报告/书籍/简历/技术文档/信函)
129
+ imprint --new report -o my_report.md
130
+ # 启动 MCP server(stdio),供 Claude Code / Cursor / DeepSeek Harness 等接入
131
+ imprint-mcp
132
+ ```
133
+
134
+ 输出结尾是一张质检报告:
135
+
136
+ ```
137
+ 印刷级质检报告
138
+ ==============================================
139
+ ✓ 文本可选 15.0/15.0 平均每页 722 字符
140
+ ✓ 字体子集嵌入 15.0/15.0 5/5 字体已嵌入
141
+ ✓ 元数据完整 3.0/3.0 标题「印记」
142
+ ✓ 标点避头尾 15.0/15.0 0 违规
143
+ ✓ 孤行寡行 9.0/9.0 0 处
144
+ ✓ 目录页码 15.0/15.0 核对 15 条
145
+ ✓ 页码存在 2.0/2.0 8/9 页含页码
146
+ ✓ PDF/UA 标签 3.0/3.0 Tagged PDF
147
+ ✓ 主题字体生效 3.0/3.0 命中 songti
148
+ ✓ 主题对比度 5.0/5.0 正文 17.0:1 …
149
+ ✓ 缺字检测 5.0/5.0 无缺字回退
150
+ ✓ 内容溢出 5.0/5.0 无内容越界
151
+ ✓ 图片清晰度 5.0/5.0 全部达标
152
+ ----------------------------------------------
153
+ 总分 100.0/100 · 等级 A+ · 9 页
154
+ ```
155
+
156
+ ## 特性
157
+
158
+ - **封面 + 目录**:frontmatter 里的 `title / author / date` 自动生成封面,标题自动生成可点击目录(页码精确)
159
+ - **智能换肤**:不指定主题时,按标题/关键词/正文信号自动推荐(含理由);显式指定优先
160
+ - **主题系统**:22 套主题(见下方画廊)——现代杂志 / 学术书卷 / 北欧极简 / 护眼纸色 / 报纸头版 / 柔和粉彩 / 纯黑白 / 玉石绿 / 咖啡暖棕 / 海洋蓝 / 薰衣草紫 / 樱粉 / 松林绿 / 勃艮第酒红 / 石墨灰 / 深夜蓝纸(暗色)/ 珊瑚橙 / 琥珀金 / 薄荷青 / 沙漠沙色 / **极简(minimal)** / **线装书(ink,宣纸+印章红)**,自定义主题 = 一个 JSON 文件
161
+ - **GitHub 风格提示框**:`> [!NOTE]` / `[!TIP]` / `[!WARNING]` / `[!IMPORTANT]` / `[!CAUTION]` 自动渲染为印刷级彩色提示卡,见 `examples/alerts.md`
162
+ - **Mermaid 图表**:` ```mermaid ` 代码块自动渲染为矢量图(中文正常、无限缩放),未装引擎时优雅回退代码块,见 `examples/charts.md`
163
+ - **数学公式**:`$行内公式$` / `$$块级公式$$` 渲染为矢量 SVG(matplotlib mathtext,无数学字体依赖),见 `examples/math.md`
164
+ - **模板系统**:`imprint --new report|book|resume|techdoc|letter|paper|gongwen|ieee` 一键起稿,模板自带对应排版气质(石墨灰报告 / 米黄书稿 / 等宽简历 / 海洋蓝技术文档 / 薰衣草信函 / 双栏学术论文 / 红头公文 / IEEE 英文论文)
165
+ - **图片压缩**:`--compress` 自动降采样超大图并重编码(实测 11.7MB → 1.4MB)
166
+ - **字体体检**:生成前自动检查主题字体本机是否可用,缺失时明确警告
167
+ - **中文规范**:避头尾禁则、首行缩进、中英文混排、英文段落自动连字
168
+ - **表格跨页**:表头自动重复、行不截断
169
+ - **代码高亮**:Pygments 着色、整体换页不截断
170
+ - **缺字检测**:渲染后扫描 LastResort/notdef 回退(豆腐块),脚注、箭头等符号缺字自动暴露
171
+ - **PDF/UA**:默认输出无障碍标签版
172
+ - **AI 原生**:CLI 一行命令;内置 MCP server(`imprint-mcp`),Agent 一句话出报告(tools: render_markdown / list_themes / validate_pdf / new_document)
173
+ - **对比度合规**:每套主题自动通过 WCAG 印刷检查(正文 ≥7:1、小字 ≥4.5:1、装饰 ≥3:1)
174
+
175
+ ## 对比
176
+
177
+ | | pandoc 默认 | Chrome 打印 | Imprint |
178
+ |---|---|---|---|
179
+ | 中文印刷级 | 弱 | 弱 | **按规范** |
180
+ | 设计系统主题 | 无 | 无 | **DTCG tokens** |
181
+ | 质检报告 0–100 | 无 | 无 | **自带** |
182
+ | 数学公式 | 插件级 | 无 | **矢量内嵌** |
183
+ | 模板起稿 | 无 | 无 | **8 套内置** |
184
+ | 双栏学术排版 | 无 | 无 | **内置** |
185
+ | 公文格式(红头文件) | 无 | 无 | **内置** |
186
+ | WCAG 对比度检查 | 无 | 无 | **内置** |
187
+ | PDF/UA 无障碍 | 手动 | 无 | **默认** |
188
+
189
+ ## 文档
190
+
191
+ - [完美 PDF 标准](docs/完美PDF标准.md)——"完美"的定义与验收门槛
192
+ - [极致借鉴清单](docs/极致借鉴清单_技术选型_20260819.md)——每个环节的社区选型与实测结论
193
+
194
+ ## 路线图
195
+
196
+ - 更多主题(minimal / ink 已上线,22 套)
197
+ - npm 分发 `npx imprint`(已上线)
198
+ - 双栏 / 学术模板(已上线)
199
+ - PyPI 发布
200
+ - 更多双栏模板(IEEE / 公文 / 病历等)
201
+
202
+ ## License
203
+
204
+ MIT
@@ -0,0 +1,3 @@
1
+ """Imprint: AI-native, print-grade Chinese PDF generator."""
2
+
3
+ __version__ = "0.11.0"
@@ -0,0 +1,4 @@
1
+ from imprint.cli import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
@@ -0,0 +1,138 @@
1
+ """Imprint command-line interface."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import json
7
+ import sys
8
+ from pathlib import Path
9
+
10
+ from . import __version__
11
+ from .converter import build_document, md_to_html
12
+ from .fonts import missing_font_slots
13
+ from .recommend import recommend_theme
14
+ from .render import compress_pdf, render_pdf
15
+ from .theme import theme_css
16
+ from .themes import list_themes
17
+ from .validator import validate_pdf
18
+
19
+
20
+ def _enable_utf8_io() -> None:
21
+ """Windows consoles default to a legacy codepage; force UTF-8 output so
22
+ Chinese report text never crashes print()."""
23
+ for stream in (sys.stdout, sys.stderr):
24
+ try:
25
+ stream.reconfigure(encoding="utf-8", errors="replace")
26
+ except (AttributeError, ValueError):
27
+ pass
28
+
29
+
30
+ def build_parser() -> argparse.ArgumentParser:
31
+ p = argparse.ArgumentParser(
32
+ prog="imprint",
33
+ description="AI 原生 · 印刷级中文 PDF 生成器:Markdown 进,出版社级 PDF 出,自带 0-100 印刷级质检报告。",
34
+ )
35
+ p.add_argument("input", nargs="?", default=None, help="输入 Markdown 文件(支持 frontmatter: title/author/date/subtitle/keywords/theme)")
36
+ p.add_argument("-o", "--output", default=None, help="输出 PDF 路径(默认 input.pdf)")
37
+ p.add_argument("--theme", default=None, help="主题名(默认读 frontmatter 或 modern)")
38
+ p.add_argument("--themes-dir", default=None, help="额外主题目录(*.json)")
39
+ p.add_argument("--no-validate", action="store_true", help="跳过印刷级质检")
40
+ p.add_argument("--report", default=None, help="把质检报告另存为 JSON")
41
+ p.add_argument("--compress", action="store_true", help="生成后激进压缩(清除冗余对象)")
42
+ p.add_argument("--no-pdf-ua", action="store_true", help="不输出 PDF/UA 标签版")
43
+ p.add_argument("--new", metavar="TEMPLATE", default=None, help="从模板生成新文档: report/book/resume/techdoc/letter")
44
+ p.add_argument("--list-templates", action="store_true", help="列出可用模板")
45
+ p.add_argument("--list-themes", action="store_true", help="列出可用主题")
46
+ p.add_argument("--version", action="version", version=f"imprint {__version__}")
47
+ return p
48
+
49
+
50
+ def _new_document(template: str, out: Path | None) -> int:
51
+ from importlib.resources import files
52
+
53
+ tpl = template.removesuffix(".md")
54
+ path = Path(str(files("imprint.templates").joinpath(f"{tpl}.md")))
55
+ if not path.exists():
56
+ print(f"错误: 模板 {template} 不存在(可用: {list_templates()})", file=sys.stderr)
57
+ return 1
58
+ target = out or Path(f"{tpl}.md")
59
+ target.write_text(path.read_text(encoding="utf-8"), encoding="utf-8")
60
+ print(f"已生成 {target},渲染: imprint {target}")
61
+ return 0
62
+
63
+
64
+ def list_templates() -> str:
65
+ from importlib.resources import files
66
+
67
+ tpl_dir = files("imprint.templates")
68
+ names = sorted(
69
+ p.name.removesuffix(".md")
70
+ for p in tpl_dir.iterdir()
71
+ if p.name.endswith(".md")
72
+ )
73
+ return " / ".join(names)
74
+
75
+
76
+ def main(argv: list[str] | None = None) -> int:
77
+ _enable_utf8_io()
78
+ args = build_parser().parse_args(argv)
79
+ if args.list_templates:
80
+ print(list_templates())
81
+ return 0
82
+ if args.new:
83
+ return _new_document(args.new, Path(args.output) if args.output else None)
84
+ if args.list_themes:
85
+ for name in list_themes(args.themes_dir):
86
+ print(name)
87
+ return 0
88
+
89
+ if not args.input:
90
+ build_parser().print_help()
91
+ return 1
92
+ src = Path(args.input)
93
+ if not src.exists():
94
+ print(f"错误: 找不到输入文件 {src}", file=sys.stderr)
95
+ return 1
96
+
97
+ conv = md_to_html(src.read_text(encoding="utf-8"))
98
+ meta = conv.meta
99
+ theme_name = args.theme or (meta.get("theme") or "").strip().lower()
100
+ theme_note = None
101
+ if not theme_name:
102
+ theme_name, theme_note = recommend_theme(meta, conv.text)
103
+ css, theme = theme_css(theme_name, args.themes_dir)
104
+ if theme_note:
105
+ print(f"主题:{theme_name}({theme_note})")
106
+ html = build_document(conv)
107
+
108
+ for slot in missing_font_slots(theme):
109
+ print(f"警告: 主题 {theme_name} 的{slot}字体在本机不可用,已回退系统字体", file=sys.stderr)
110
+
111
+ out = Path(args.output) if args.output else src.with_suffix(".pdf")
112
+ out.parent.mkdir(parents=True, exist_ok=True)
113
+ pages = render_pdf(html, css, out, pdf_ua=not args.no_pdf_ua, base_url=src.parent)
114
+ if args.compress:
115
+ saved = compress_pdf(out)
116
+ print(f"已压缩,节省 {saved/1024:.0f} KB" if saved else "无图片可压缩,文件保持原样")
117
+
118
+ if args.no_validate:
119
+ print(f"已生成 {out}({pages} 页,主题 {theme_name})")
120
+ return 0
121
+
122
+ report = validate_pdf(
123
+ out,
124
+ toc_entries=[] if str(meta.get("layout") or "").strip().lower() == "gongwen" else [(i.text, i.href) for i in conv.toc],
125
+ serif_hint=meta.get("theme-font-hint") or "Songti",
126
+ theme_colors=theme["tokens"].get("color"),
127
+ )
128
+ print(report.print_table())
129
+ if args.report:
130
+ Path(args.report).write_text(
131
+ json.dumps(report.to_dict(), ensure_ascii=False, indent=2),
132
+ encoding="utf-8",
133
+ )
134
+ return 0 if report.score >= 80 else 1
135
+
136
+
137
+ if __name__ == "__main__":
138
+ raise SystemExit(main())