agent-markdown-pdf 0.1.2__tar.gz → 0.2.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 (93) hide show
  1. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/PKG-INFO +70 -7
  2. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/README.md +69 -6
  3. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/PKG-INFO +70 -7
  4. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/SOURCES.txt +1 -0
  5. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/api.py +4 -0
  6. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/doctor.py +47 -2
  7. agent_markdown_pdf-0.2.0/mdtopdf/core/fonts.py +436 -0
  8. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/html.py +4 -0
  9. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/markdown.py +81 -3
  10. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/mermaid.py +1 -1
  11. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/pdf.py +4 -0
  12. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/mdtopdf_cli.py +10 -0
  13. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/skills/SKILL.md +26 -2
  14. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/themes/default.css +31 -7
  15. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/pyproject.toml +1 -1
  16. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/tests/test_core.py +157 -0
  17. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/LICENSE +0 -0
  18. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/dependency_links.txt +0 -0
  19. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/entry_points.txt +0 -0
  20. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/requires.txt +0 -0
  21. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/agent_markdown_pdf.egg-info/top_level.txt +0 -0
  22. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/__init__.py +0 -0
  23. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/__main__.py +0 -0
  24. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/__init__.py +0 -0
  25. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/inline.py +0 -0
  26. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/katex.py +0 -0
  27. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/core/obsidian.py +0 -0
  28. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/LICENSE +0 -0
  29. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/contrib/mhchem.min.js +0 -0
  30. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_AMS-Regular.ttf +0 -0
  31. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_AMS-Regular.woff +0 -0
  32. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_AMS-Regular.woff2 +0 -0
  33. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
  34. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
  35. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
  36. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
  37. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
  38. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
  39. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
  40. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Bold.woff +0 -0
  41. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
  42. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
  43. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Regular.woff +0 -0
  44. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
  45. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Bold.ttf +0 -0
  46. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Bold.woff +0 -0
  47. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Bold.woff2 +0 -0
  48. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
  49. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-BoldItalic.woff +0 -0
  50. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
  51. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Italic.ttf +0 -0
  52. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Italic.woff +0 -0
  53. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Italic.woff2 +0 -0
  54. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Regular.ttf +0 -0
  55. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Regular.woff +0 -0
  56. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Main-Regular.woff2 +0 -0
  57. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
  58. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-BoldItalic.woff +0 -0
  59. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
  60. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-Italic.ttf +0 -0
  61. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-Italic.woff +0 -0
  62. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Math-Italic.woff2 +0 -0
  63. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
  64. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Bold.woff +0 -0
  65. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
  66. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
  67. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Italic.woff +0 -0
  68. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
  69. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
  70. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Regular.woff +0 -0
  71. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
  72. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Script-Regular.ttf +0 -0
  73. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Script-Regular.woff +0 -0
  74. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Script-Regular.woff2 +0 -0
  75. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size1-Regular.ttf +0 -0
  76. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size1-Regular.woff +0 -0
  77. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size1-Regular.woff2 +0 -0
  78. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size2-Regular.ttf +0 -0
  79. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size2-Regular.woff +0 -0
  80. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size2-Regular.woff2 +0 -0
  81. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size3-Regular.ttf +0 -0
  82. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size3-Regular.woff +0 -0
  83. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size3-Regular.woff2 +0 -0
  84. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size4-Regular.ttf +0 -0
  85. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size4-Regular.woff +0 -0
  86. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Size4-Regular.woff2 +0 -0
  87. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
  88. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Typewriter-Regular.woff +0 -0
  89. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
  90. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/katex.min.css +0 -0
  91. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/mdtopdf/vendor/katex/dist/katex.min.js +0 -0
  92. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/setup.cfg +0 -0
  93. {agent_markdown_pdf-0.1.2 → agent_markdown_pdf-0.2.0}/tests/test_full_e2e.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-markdown-pdf
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Agent-friendly Markdown-to-PDF CLI with HTML preview and JSON diagnostics
5
5
  Author: rainp
6
6
  License-Expression: MIT
@@ -140,10 +140,10 @@ mdtopdf html report.md -o report.html --overwrite --json
140
140
  mdtopdf convert report.md -o report.pdf --overwrite --json
141
141
  ```
142
142
 
143
- `convert --json` returns the input path, output path, file size, theme, and
144
- render method. If conversion fails in JSON mode, the error is structured enough
145
- for an agent to show the command, explain the likely cause, and retry after a
146
- fix.
143
+ `convert --json` returns the input path, output path, file size, theme, font
144
+ check summary, warnings, and render method. If conversion fails in JSON mode,
145
+ the error is structured enough for an agent to show the command, explain the
146
+ likely cause, and retry after a fix.
147
147
 
148
148
  ## Visual output
149
149
 
@@ -175,7 +175,7 @@ remain visible as highlighted code.
175
175
  | Feature | Notes |
176
176
  | --- | --- |
177
177
  | JSON output | `--json` is available for conversion, HTML preview, doctor, and theme listing. |
178
- | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, and Mermaid availability. |
178
+ | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, Mermaid availability, and recommended fonts. |
179
179
  | Local rendering | Markdown, CSS, math, Mermaid SVG generation, and PDF export stay on the machine. |
180
180
  | HTML preview | Generate standalone HTML before PDF export for fast visual inspection. |
181
181
  | Obsidian compatibility | Wikilinks, aliases, frontmatter hiding, comments, highlights, and typed callouts. |
@@ -215,6 +215,38 @@ mdtopdf convert report.md -o report.pdf --base-url assets
215
215
  mdtopdf convert report.md -o report.pdf --resource-dir attachments
216
216
  ```
217
217
 
218
+ Custom CSS is the style extension point. Put document-specific rules in a CSS
219
+ file; fonts, spacing, colors, page rules, and code block styling all live there.
220
+ Use a system-installed font directly, or define `@font-face` for a local font
221
+ file. Relative URLs in CSS are resolved from the Markdown file's base URL, so
222
+ use `--base-url` when those assets live next to your document:
223
+
224
+ ```css
225
+ @font-face {
226
+ font-family: "Report Sans";
227
+ src: url("fonts/NotoSansSC-Regular.otf");
228
+ }
229
+
230
+ :root {
231
+ font-family: "Report Sans", "Noto Sans SC", "Source Han Sans SC", sans-serif;
232
+ }
233
+
234
+ code,
235
+ pre {
236
+ font-family: "Cascadia Code", "Liberation Mono", monospace;
237
+ }
238
+ ```
239
+
240
+ Then pass the CSS file:
241
+
242
+ ```shell
243
+ mdtopdf convert report.md -o report.pdf --css print.css --base-url .
244
+ ```
245
+
246
+ During export, `mdtopdf` checks the final CSS font stacks. Missing fonts do not
247
+ stop PDF generation, but they are reported in CLI warnings and in the JSON
248
+ `warnings` field.
249
+
218
250
  Return JSON:
219
251
 
220
252
  ```shell
@@ -291,6 +323,31 @@ rendering is available.
291
323
  WeasyPrint also needs native libraries such as Pango, GLib, and Cairo. Linux
292
324
  and macOS package managers usually provide them through system packages.
293
325
 
326
+ The default theme names `Microsoft YaHei` first in its CSS on every platform,
327
+ including Linux. If that font is installed in the environment, WeasyPrint will
328
+ use it. If it is missing, the theme falls back to `PingFang SC`,
329
+ `Noto Sans SC`, `Noto Sans CJK SC`, `Source Han Sans SC`, and other available
330
+ CJK fonts.
331
+
332
+ For stable CJK output in Linux containers or agent sandboxes where Microsoft
333
+ YaHei is not installed, install the CJK font you want to use. Noto CJK is a
334
+ practical fallback on Debian or Ubuntu:
335
+
336
+ Emoji are rendered through the system emoji font. The default theme prefers
337
+ `Segoe UI Emoji` for emoji spans on every platform, including Linux. Windows
338
+ usually provides it; Linux containers only get the same glyphs if the runtime
339
+ provides that font. If Segoe UI Emoji is not available, the theme falls back to
340
+ `Apple Color Emoji`, `Noto Emoji`, `Noto Color Emoji`, and other installed emoji
341
+ fonts. Whether the final PDF keeps color emoji still depends on WeasyPrint,
342
+ Pango/Cairo, and the PDF viewer.
343
+
344
+ On Debian or Ubuntu, this is a practical open-font fallback baseline:
345
+
346
+ ```shell
347
+ sudo apt-get install -y fonts-noto-cjk fonts-noto-color-emoji fonts-stix fonts-dejavu-core
348
+ fc-cache -f
349
+ ```
350
+
294
351
  On Windows, install the native libraries separately. A common MSYS2 setup is:
295
352
 
296
353
  ```powershell
@@ -310,7 +367,8 @@ if MSYS2 is installed somewhere else:
310
367
  setx WEASYPRINT_DLL_DIRECTORIES "C:\msys64\mingw64\bin"
311
368
  ```
312
369
 
313
- Run this after installation:
370
+ Run this after installation. The JSON output also reports whether recommended
371
+ CJK, emoji, monospace, and math fallback fonts are present:
314
372
 
315
373
  ```shell
316
374
  mdtopdf doctor --json
@@ -336,3 +394,8 @@ python -m twine check dist/*
336
394
 
337
395
  MIT. Bundled KaTeX assets are also distributed under the MIT license; see
338
396
  `mdtopdf/vendor/katex/LICENSE`.
397
+
398
+ `mdtopdf` does not bundle CJK body fonts, emoji fonts, or proprietary system
399
+ fonts. The default theme references local system fonts such as Microsoft YaHei,
400
+ PingFang SC, Segoe UI, Segoe UI Emoji, Noto Emoji, Noto Color Emoji, and Consolas, but
401
+ those font files come from the user's operating system or runtime environment.
@@ -99,10 +99,10 @@ mdtopdf html report.md -o report.html --overwrite --json
99
99
  mdtopdf convert report.md -o report.pdf --overwrite --json
100
100
  ```
101
101
 
102
- `convert --json` returns the input path, output path, file size, theme, and
103
- render method. If conversion fails in JSON mode, the error is structured enough
104
- for an agent to show the command, explain the likely cause, and retry after a
105
- fix.
102
+ `convert --json` returns the input path, output path, file size, theme, font
103
+ check summary, warnings, and render method. If conversion fails in JSON mode,
104
+ the error is structured enough for an agent to show the command, explain the
105
+ likely cause, and retry after a fix.
106
106
 
107
107
  ## Visual output
108
108
 
@@ -134,7 +134,7 @@ remain visible as highlighted code.
134
134
  | Feature | Notes |
135
135
  | --- | --- |
136
136
  | JSON output | `--json` is available for conversion, HTML preview, doctor, and theme listing. |
137
- | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, and Mermaid availability. |
137
+ | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, Mermaid availability, and recommended fonts. |
138
138
  | Local rendering | Markdown, CSS, math, Mermaid SVG generation, and PDF export stay on the machine. |
139
139
  | HTML preview | Generate standalone HTML before PDF export for fast visual inspection. |
140
140
  | Obsidian compatibility | Wikilinks, aliases, frontmatter hiding, comments, highlights, and typed callouts. |
@@ -174,6 +174,38 @@ mdtopdf convert report.md -o report.pdf --base-url assets
174
174
  mdtopdf convert report.md -o report.pdf --resource-dir attachments
175
175
  ```
176
176
 
177
+ Custom CSS is the style extension point. Put document-specific rules in a CSS
178
+ file; fonts, spacing, colors, page rules, and code block styling all live there.
179
+ Use a system-installed font directly, or define `@font-face` for a local font
180
+ file. Relative URLs in CSS are resolved from the Markdown file's base URL, so
181
+ use `--base-url` when those assets live next to your document:
182
+
183
+ ```css
184
+ @font-face {
185
+ font-family: "Report Sans";
186
+ src: url("fonts/NotoSansSC-Regular.otf");
187
+ }
188
+
189
+ :root {
190
+ font-family: "Report Sans", "Noto Sans SC", "Source Han Sans SC", sans-serif;
191
+ }
192
+
193
+ code,
194
+ pre {
195
+ font-family: "Cascadia Code", "Liberation Mono", monospace;
196
+ }
197
+ ```
198
+
199
+ Then pass the CSS file:
200
+
201
+ ```shell
202
+ mdtopdf convert report.md -o report.pdf --css print.css --base-url .
203
+ ```
204
+
205
+ During export, `mdtopdf` checks the final CSS font stacks. Missing fonts do not
206
+ stop PDF generation, but they are reported in CLI warnings and in the JSON
207
+ `warnings` field.
208
+
177
209
  Return JSON:
178
210
 
179
211
  ```shell
@@ -250,6 +282,31 @@ rendering is available.
250
282
  WeasyPrint also needs native libraries such as Pango, GLib, and Cairo. Linux
251
283
  and macOS package managers usually provide them through system packages.
252
284
 
285
+ The default theme names `Microsoft YaHei` first in its CSS on every platform,
286
+ including Linux. If that font is installed in the environment, WeasyPrint will
287
+ use it. If it is missing, the theme falls back to `PingFang SC`,
288
+ `Noto Sans SC`, `Noto Sans CJK SC`, `Source Han Sans SC`, and other available
289
+ CJK fonts.
290
+
291
+ For stable CJK output in Linux containers or agent sandboxes where Microsoft
292
+ YaHei is not installed, install the CJK font you want to use. Noto CJK is a
293
+ practical fallback on Debian or Ubuntu:
294
+
295
+ Emoji are rendered through the system emoji font. The default theme prefers
296
+ `Segoe UI Emoji` for emoji spans on every platform, including Linux. Windows
297
+ usually provides it; Linux containers only get the same glyphs if the runtime
298
+ provides that font. If Segoe UI Emoji is not available, the theme falls back to
299
+ `Apple Color Emoji`, `Noto Emoji`, `Noto Color Emoji`, and other installed emoji
300
+ fonts. Whether the final PDF keeps color emoji still depends on WeasyPrint,
301
+ Pango/Cairo, and the PDF viewer.
302
+
303
+ On Debian or Ubuntu, this is a practical open-font fallback baseline:
304
+
305
+ ```shell
306
+ sudo apt-get install -y fonts-noto-cjk fonts-noto-color-emoji fonts-stix fonts-dejavu-core
307
+ fc-cache -f
308
+ ```
309
+
253
310
  On Windows, install the native libraries separately. A common MSYS2 setup is:
254
311
 
255
312
  ```powershell
@@ -269,7 +326,8 @@ if MSYS2 is installed somewhere else:
269
326
  setx WEASYPRINT_DLL_DIRECTORIES "C:\msys64\mingw64\bin"
270
327
  ```
271
328
 
272
- Run this after installation:
329
+ Run this after installation. The JSON output also reports whether recommended
330
+ CJK, emoji, monospace, and math fallback fonts are present:
273
331
 
274
332
  ```shell
275
333
  mdtopdf doctor --json
@@ -295,3 +353,8 @@ python -m twine check dist/*
295
353
 
296
354
  MIT. Bundled KaTeX assets are also distributed under the MIT license; see
297
355
  `mdtopdf/vendor/katex/LICENSE`.
356
+
357
+ `mdtopdf` does not bundle CJK body fonts, emoji fonts, or proprietary system
358
+ fonts. The default theme references local system fonts such as Microsoft YaHei,
359
+ PingFang SC, Segoe UI, Segoe UI Emoji, Noto Emoji, Noto Color Emoji, and Consolas, but
360
+ those font files come from the user's operating system or runtime environment.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-markdown-pdf
3
- Version: 0.1.2
3
+ Version: 0.2.0
4
4
  Summary: Agent-friendly Markdown-to-PDF CLI with HTML preview and JSON diagnostics
5
5
  Author: rainp
6
6
  License-Expression: MIT
@@ -140,10 +140,10 @@ mdtopdf html report.md -o report.html --overwrite --json
140
140
  mdtopdf convert report.md -o report.pdf --overwrite --json
141
141
  ```
142
142
 
143
- `convert --json` returns the input path, output path, file size, theme, and
144
- render method. If conversion fails in JSON mode, the error is structured enough
145
- for an agent to show the command, explain the likely cause, and retry after a
146
- fix.
143
+ `convert --json` returns the input path, output path, file size, theme, font
144
+ check summary, warnings, and render method. If conversion fails in JSON mode,
145
+ the error is structured enough for an agent to show the command, explain the
146
+ likely cause, and retry after a fix.
147
147
 
148
148
  ## Visual output
149
149
 
@@ -175,7 +175,7 @@ remain visible as highlighted code.
175
175
  | Feature | Notes |
176
176
  | --- | --- |
177
177
  | JSON output | `--json` is available for conversion, HTML preview, doctor, and theme listing. |
178
- | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, and Mermaid availability. |
178
+ | Environment checks | `doctor --json` checks Python imports, native WeasyPrint libraries, Windows DLL paths, Mermaid availability, and recommended fonts. |
179
179
  | Local rendering | Markdown, CSS, math, Mermaid SVG generation, and PDF export stay on the machine. |
180
180
  | HTML preview | Generate standalone HTML before PDF export for fast visual inspection. |
181
181
  | Obsidian compatibility | Wikilinks, aliases, frontmatter hiding, comments, highlights, and typed callouts. |
@@ -215,6 +215,38 @@ mdtopdf convert report.md -o report.pdf --base-url assets
215
215
  mdtopdf convert report.md -o report.pdf --resource-dir attachments
216
216
  ```
217
217
 
218
+ Custom CSS is the style extension point. Put document-specific rules in a CSS
219
+ file; fonts, spacing, colors, page rules, and code block styling all live there.
220
+ Use a system-installed font directly, or define `@font-face` for a local font
221
+ file. Relative URLs in CSS are resolved from the Markdown file's base URL, so
222
+ use `--base-url` when those assets live next to your document:
223
+
224
+ ```css
225
+ @font-face {
226
+ font-family: "Report Sans";
227
+ src: url("fonts/NotoSansSC-Regular.otf");
228
+ }
229
+
230
+ :root {
231
+ font-family: "Report Sans", "Noto Sans SC", "Source Han Sans SC", sans-serif;
232
+ }
233
+
234
+ code,
235
+ pre {
236
+ font-family: "Cascadia Code", "Liberation Mono", monospace;
237
+ }
238
+ ```
239
+
240
+ Then pass the CSS file:
241
+
242
+ ```shell
243
+ mdtopdf convert report.md -o report.pdf --css print.css --base-url .
244
+ ```
245
+
246
+ During export, `mdtopdf` checks the final CSS font stacks. Missing fonts do not
247
+ stop PDF generation, but they are reported in CLI warnings and in the JSON
248
+ `warnings` field.
249
+
218
250
  Return JSON:
219
251
 
220
252
  ```shell
@@ -291,6 +323,31 @@ rendering is available.
291
323
  WeasyPrint also needs native libraries such as Pango, GLib, and Cairo. Linux
292
324
  and macOS package managers usually provide them through system packages.
293
325
 
326
+ The default theme names `Microsoft YaHei` first in its CSS on every platform,
327
+ including Linux. If that font is installed in the environment, WeasyPrint will
328
+ use it. If it is missing, the theme falls back to `PingFang SC`,
329
+ `Noto Sans SC`, `Noto Sans CJK SC`, `Source Han Sans SC`, and other available
330
+ CJK fonts.
331
+
332
+ For stable CJK output in Linux containers or agent sandboxes where Microsoft
333
+ YaHei is not installed, install the CJK font you want to use. Noto CJK is a
334
+ practical fallback on Debian or Ubuntu:
335
+
336
+ Emoji are rendered through the system emoji font. The default theme prefers
337
+ `Segoe UI Emoji` for emoji spans on every platform, including Linux. Windows
338
+ usually provides it; Linux containers only get the same glyphs if the runtime
339
+ provides that font. If Segoe UI Emoji is not available, the theme falls back to
340
+ `Apple Color Emoji`, `Noto Emoji`, `Noto Color Emoji`, and other installed emoji
341
+ fonts. Whether the final PDF keeps color emoji still depends on WeasyPrint,
342
+ Pango/Cairo, and the PDF viewer.
343
+
344
+ On Debian or Ubuntu, this is a practical open-font fallback baseline:
345
+
346
+ ```shell
347
+ sudo apt-get install -y fonts-noto-cjk fonts-noto-color-emoji fonts-stix fonts-dejavu-core
348
+ fc-cache -f
349
+ ```
350
+
294
351
  On Windows, install the native libraries separately. A common MSYS2 setup is:
295
352
 
296
353
  ```powershell
@@ -310,7 +367,8 @@ if MSYS2 is installed somewhere else:
310
367
  setx WEASYPRINT_DLL_DIRECTORIES "C:\msys64\mingw64\bin"
311
368
  ```
312
369
 
313
- Run this after installation:
370
+ Run this after installation. The JSON output also reports whether recommended
371
+ CJK, emoji, monospace, and math fallback fonts are present:
314
372
 
315
373
  ```shell
316
374
  mdtopdf doctor --json
@@ -336,3 +394,8 @@ python -m twine check dist/*
336
394
 
337
395
  MIT. Bundled KaTeX assets are also distributed under the MIT license; see
338
396
  `mdtopdf/vendor/katex/LICENSE`.
397
+
398
+ `mdtopdf` does not bundle CJK body fonts, emoji fonts, or proprietary system
399
+ fonts. The default theme references local system fonts such as Microsoft YaHei,
400
+ PingFang SC, Segoe UI, Segoe UI Emoji, Noto Emoji, Noto Color Emoji, and Consolas, but
401
+ those font files come from the user's operating system or runtime environment.
@@ -13,6 +13,7 @@ mdtopdf/api.py
13
13
  mdtopdf/mdtopdf_cli.py
14
14
  mdtopdf/core/__init__.py
15
15
  mdtopdf/core/doctor.py
16
+ mdtopdf/core/fonts.py
16
17
  mdtopdf/core/html.py
17
18
  mdtopdf/core/inline.py
18
19
  mdtopdf/core/katex.py
@@ -13,6 +13,7 @@ from typing import Any
13
13
  from urllib.parse import urlparse
14
14
 
15
15
  from mdtopdf.core.doctor import add_weasyprint_dll_directories
16
+ from mdtopdf.core.fonts import inspect_css_font_usage, summarize_font_usage
16
17
  from mdtopdf.core.html import convert_markdown_file_to_html
17
18
  from mdtopdf.core.markdown import DEFAULT_THEME, RenderedHTML, render_markdown_to_html
18
19
  from mdtopdf.core.obsidian import build_resource_resolver, resolve_resource_dir
@@ -143,6 +144,7 @@ def markdown_to_pdf(
143
144
  include_page_footer=include_page_footer,
144
145
  page_numbers=page_numbers,
145
146
  )
147
+ font_usage = inspect_css_font_usage(rendered.css, document_text=markdown_text)
146
148
 
147
149
  output.parent.mkdir(parents=True, exist_ok=True)
148
150
  try:
@@ -174,6 +176,8 @@ def markdown_to_pdf(
174
176
  "page_header": effective_header,
175
177
  "page_footer": effective_footer,
176
178
  "page_numbers": bool(include_page_footer and page_numbers),
179
+ "font_check": summarize_font_usage(font_usage),
180
+ "warnings": font_usage.get("warnings", []),
177
181
  "method": "markdown-it-py+weasyprint",
178
182
  }
179
183
 
@@ -8,6 +8,7 @@ import sys
8
8
  from pathlib import Path
9
9
  from typing import Any
10
10
 
11
+ from mdtopdf.core.fonts import inspect_recommended_font_groups
11
12
  from mdtopdf.core.mermaid import inspect_mermaid_backend
12
13
 
13
14
 
@@ -21,8 +22,6 @@ COMMON_WINDOWS_DLL_DIRS = (
21
22
  r"C:\msys64\mingw64\bin",
22
23
  r"D:\Environment\msys64\mingw64\bin",
23
24
  )
24
-
25
-
26
25
  def add_weasyprint_dll_directories() -> list[str]:
27
26
  """Register Windows DLL search directories from ``WEASYPRINT_DLL_DIRECTORIES``."""
28
27
 
@@ -68,6 +67,7 @@ def run_doctor() -> dict[str, Any]:
68
67
  "packages": {},
69
68
  "tools": {},
70
69
  "native_libraries": _inspect_native_libraries(),
70
+ "fonts": _inspect_fonts(),
71
71
  "recommendations": [],
72
72
  }
73
73
 
@@ -115,6 +115,19 @@ def format_doctor_text(result: dict[str, Any]) -> str:
115
115
  f"missing={', '.join(probe['missing']) or '(none)'}"
116
116
  )
117
117
 
118
+ if result.get("fonts"):
119
+ lines.extend(["", "Fonts:"])
120
+ font_error = result["fonts"].get("error")
121
+ if font_error:
122
+ lines.append(f" - font inspection: FAIL - {font_error}")
123
+ for name, info in result["fonts"].get("groups", {}).items():
124
+ found = ", ".join(info.get("found", [])) or "(none)"
125
+ recommended = ", ".join(info.get("recommended", []))
126
+ lines.append(
127
+ f" - {name}: {'OK' if info.get('ok') else 'MISSING'} "
128
+ f"found={found} recommended={recommended}"
129
+ )
130
+
118
131
  if result.get("recommendations"):
119
132
  lines.extend(["", "Recommendations:"])
120
133
  for item in result["recommendations"]:
@@ -194,6 +207,10 @@ def _env_dll_directories() -> list[str]:
194
207
  return [part.strip() for part in raw.split(os.pathsep) if part.strip()]
195
208
 
196
209
 
210
+ def _inspect_fonts() -> dict[str, Any]:
211
+ return inspect_recommended_font_groups()
212
+
213
+
197
214
  def _recommendations(result: dict[str, Any]) -> list[str]:
198
215
  recommendations: list[str] = []
199
216
  package_info = result.get("packages", {}).get("weasyprint", {})
@@ -216,6 +233,34 @@ def _recommendations(result: dict[str, Any]) -> list[str]:
216
233
  "npm install -g @mermaid-js/mermaid-cli"
217
234
  )
218
235
 
236
+ font_info = result.get("fonts", {})
237
+ font_groups = font_info.get("groups", {})
238
+ if font_info.get("error"):
239
+ recommendations.append("Font inspection failed; run conversion once and verify CJK text visually.")
240
+ if font_groups.get("cjk_sans") and not font_groups["cjk_sans"].get("ok"):
241
+ recommendations.append(
242
+ "Install Microsoft YaHei when you want the default theme to match its first-choice CJK font. "
243
+ "On Debian or Ubuntu, Noto CJK is a practical fallback: sudo apt-get install fonts-noto-cjk"
244
+ )
245
+ if font_groups.get("monospace") and not font_groups["monospace"].get("ok"):
246
+ recommendations.append(
247
+ "Optional: install a monospace font such as Cascadia Code or Liberation Mono for stable code blocks."
248
+ )
249
+ if font_groups.get("math") and not font_groups["math"].get("ok"):
250
+ recommendations.append(
251
+ "Optional: install STIX fonts for math fallback, for example: sudo apt-get install fonts-stix"
252
+ )
253
+ if font_groups.get("emoji") and not font_groups["emoji"].get("ok"):
254
+ recommendations.append(
255
+ "Provide Segoe UI Emoji in the runtime if you want the default theme's first-choice "
256
+ "emoji glyphs. If that is not available, install another emoji font and run fc-cache -f."
257
+ )
258
+ elif font_groups.get("emoji") and "Segoe UI Emoji" in font_groups["emoji"].get("missing", []):
259
+ recommendations.append(
260
+ "Optional: provide Segoe UI Emoji if you want the default theme's preferred emoji glyphs. "
261
+ "Existing emoji fallback fonts will still be used."
262
+ )
263
+
219
264
  if os.name == "nt":
220
265
  env_value = result.get("environment", {}).get(WINDOWS_DLL_ENV)
221
266
  probes = result.get("native_libraries", [])