| name | pdf |
| type | skill |
| title | PDF 文档生成 |
| description | Generate PDF documents from Markdown, HTML, or structured data in the sandbox, with correct Chinese (CJK) rendering. Use when (1) the task asks for a PDF file or 导出/转成 PDF; (2) Markdown 或 HTML 需要排版成可打印文档; (3) 之前生成的 PDF 中文乱码或黑方块。触发词:PDF、导出 pdf、md 转 pdf、打印、排版。 |
| date | 2026-08-27 |
When to Use
Use when the deliverable is a .pdf file, especially Markdown-to-PDF conversion, report/合同/方案 排版导出, or any task where Chinese text must render correctly in the output.
Core Rules
1. 首选 weasyprint,不要自己装依赖
- 沙箱已预装
weasyprint(apt 系统包)和 markdown-it-py,直接 import 使用。
- 不要执行
pip install weasyprint:pip 版本需要 pango/cairo 系统库配合,重复安装只会浪费时间;遇到 import 报错先检查是否误用了 pip 安装的副本。
- pandoc、wkhtmltopdf、md2pdf 均不可用,不要尝试。
- 标准路径:Markdown →(markdown-it-py)→ HTML →(weasyprint)→ PDF。
from markdown_it import MarkdownIt
from weasyprint import HTML
html_body = MarkdownIt("commonmark", {"breaks": True}).enable("table").render(md_text)
html = f"""<!DOCTYPE html><html><head><meta charset="utf-8">
<style>
body {{ font-family: "WenQuanYi Micro Hei", sans-serif; font-size: 11pt; line-height: 1.6; }}
h1, h2, h3 {{ font-family: "WenQuanYi Micro Hei", sans-serif; }}
table {{ border-collapse: collapse; width: 100%; }}
th, td {{ border: 1px solid #999; padding: 4px 8px; }}
code {{ font-family: monospace; background: #f4f4f4; }}
@page {{ size: A4; margin: 2cm; }}
</style></head><body>{html_body}</body></html>"""
HTML(string=html).write_pdf("output.pdf")
2. 中文渲染必须显式指定字体
- 沙箱内可用的中文字体是 文泉驿微米黑(WenQuanYi Micro Hei),CSS
font-family 里必须声明它,否则中文全部渲染为黑方块。
- 西文/数字会回退到 sans-serif,混排无需特殊处理。
- 没有粗体/斜体字重变体,避免依赖
font-weight: bold 的视觉差异做关键强调;用颜色或边框代替。
- 生成的 PDF 嵌入字体子集,发给别人不需要对方装字体。
3. 排版质量靠 HTML+CSS,不要折腾 reportlab
- weasyprint 支持
@page 规则控制纸张(A4/Letter)、页边距、页眉页脚、页码(counter(page))。
- 表格用标准
<table> 加 border CSS;长表格跨页时 thead 会自动重复。
- 图片用
<img src="file://绝对路径"> 或 base64 data URI 嵌入。
- reportlab 仅作为程序化生成(如精确座标绘图、票据)的备选;用它处理中文需自行注册 TTF,不要作为 md 转 pdf 的路径。
4. 交付前验证
- 生成后用
pypdf 抽取第一页文本确认中文可提取(提取出乱码说明字体映射有问题)。
- 检查页数合理(空 PDF 或 1 页截断通常是 HTML 结构错误)。
- 文件体积异常小(<10KB)通常意味着内容没渲染进去。
Common Traps
- 中文黑方块 = 没声明
font-family: "WenQuanYi Micro Hei",不是编码问题,改 CSS 即可。
pip install weasyprint 后 import 仍失败 = pip 版本覆盖了 apt 版本且缺系统库;用 pip uninstall weasyprint 恢复。
- Markdown 里的表格没变成表格 = 忘了
.enable("table")。
- 中文引号、破折号在某些字体下宽度异常,属正常现象,不影响阅读。
- HTML 里
<meta charset="utf-8"> 缺失会导致非 ASCII 字符解析错误。