onepage-pdf
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseonepage-pdf
onepage-pdf
Vendored from github.com/xntj-ai/onepage-pdf by 张拼拼 · XNTJ, under the MIT License. See LICENSE.
Render HTML to one tall PDF page via headless Chrome, then crop the page to the
real content height with PyMuPDF. Height is never predicted (print layout is
not screen layout); it is measured after rendering, which is exact.
Requires: Python with , plus a local Chrome or Edge. No API token.
pymupdf源自 github.com/xntj-ai/onepage-pdf 由张拼拼 · XNTJ开发,基于MIT许可证。详见LICENSE。
通过无头Chrome将HTML渲染为一个长PDF页面,然后使用PyMuPDF将页面裁剪至实际内容高度。高度不会提前预测(打印布局并非屏幕布局),而是在渲染后精确测量得出。
依赖要求: 安装有的Python环境,以及本地Chrome或Edge浏览器。无需API令牌。
pymupdfWorkflow
工作流程
1. Inspect the source HTML first
1. 先检查源HTML
Read the HTML and check four things; they decide whether is needed:
--extra-css- Responsive breakpoints. Print media queries evaluate against the default
paper width (~741px), NOT the size. Any
@pagewith N ≥ 741 will fire during print and collapse the desktop layout. For each such rule, write an override locking the desktop value with@media (max-width: N)(e.g.!important)..grid{grid-template-columns:repeat(3,1fr)!important} - Glassmorphism. blur is silently dropped in PDF output. If glass elements sit on busy backgrounds, add a print fallback:
backdrop-filter..glass{backdrop-filter:none!important;background:rgba(255,255,255,.88)!important} - Scroll-reveal animations. Common class patterns (,
fade*,reveal*,animate*) are forced visible automatically. Anything else that starts ataosneeds an explicitopacity:0override.opacity:1!important - vh/vw sizing. Viewport units resolve against the page area in print and
drift ~1%; a hero becomes ~187in tall on the bedrock page. Override such rules with fixed px values.
min-height:100vh
Put all overrides in one CSS file and pass it via .
--extra-css读取HTML并检查四项内容,它们决定是否需要使用参数:
--extra-css- 响应式断点:打印媒体查询会针对默认纸张宽度(约741px)进行评估,而非尺寸。任何
@page且N≥741的规则会在打印时触发,导致桌面布局失效。对于此类规则,需编写覆盖样式,用@media (max-width: N)锁定桌面端值(例如:!important)。.grid{grid-template-columns:repeat(3,1fr)!important} - 毛玻璃效果:模糊效果在PDF输出中会被自动忽略。如果毛玻璃元素位于复杂背景之上,需添加打印回退样式:
backdrop-filter。.glass{backdrop-filter:none!important;background:rgba(255,255,255,.88)!important} - 滚动显示动画:常见的类模式(、
fade*、reveal*、animate*)会被自动强制显示。其他任何初始为aos的元素,需要显式添加opacity:0覆盖样式。opacity:1!important - 视口单位尺寸:视口单位在打印时会基于页面区域解析,存在约1%的偏差;设置的头部区域在基础页面上会变成约187英寸高。需用固定px值覆盖此类规则。
min-height:100vh
将所有覆盖样式放入一个CSS文件,并通过参数传入。
--extra-css2. Convert
2. 转换
Paths below are relative to this skill directory.
bash
python scripts/onepage_pdf.py input.html -o output.pdf --width 1280 \
[--extra-css fixes.css] [--replace subs.json --forbid words.txt]- : match the design width of the page (snapped to 8px; non-8px page sizes hit MediaBox rounding bugs that spawn phantom pages).
--width - : JSON
--replace, applied in order — put longer / more specific strings first. Use for redaction before publishing.[["old","new"], ...] - : one word per line; the script aborts if any survives in the HTML or in the final PDF text layer. Always pair with
--forbid.--replace - : switch to raster row-scanning if the vector crop misjudges (e.g. a decorative element painted taller than the real content).
--crop pixel
The script self-handles: oversized-bedrock rendering with auto-retry on
overflow, content cropping (MediaBox + CropBox rewritten identically for
viewer compatibility), CJK-safe output paths, single-page assertion.
A bundled example lives in — try it end to end:
examples/bash
python scripts/onepage_pdf.py examples/demo.html -o /tmp/demo.pdf \
--width 1280 --extra-css examples/demo-fixes.css以下路径均相对于此工具目录。
bash
python scripts/onepage_pdf.py input.html -o output.pdf --width 1280 \
[--extra-css fixes.css] [--replace subs.json --forbid words.txt]- :匹配页面的设计宽度(对齐到8px;非8px的页面尺寸会触发MediaBox舍入错误,产生空白页面)。
--width - :JSON格式的
--replace,按顺序应用——请将更长/更具体的字符串放在前面。用于发布前的脱敏处理。[["old","new"], ...] - :每行一个词;如果HTML或最终PDF文本层中存在任何该列表中的词,脚本会终止运行。请始终与
--forbid配合使用。--replace - :如果矢量裁剪判断错误(例如装饰元素的绘制高度超过实际内容),切换为光栅行扫描模式。
--crop pixel
脚本会自动处理:超大基础页面渲染及溢出时的自动重试、内容裁剪(为兼容查看器,MediaBox和CropBox会被重写为相同值)、支持CJK的输出路径、单页验证。
examples/bash
python scripts/onepage_pdf.py examples/demo.html -o /tmp/demo.pdf \
--width 1280 --extra-css examples/demo-fixes.css3. Verify
3. 验证
The script prints . Then:
OK 1 page, WxHpt- Render a thumbnail and eyeball it (layout intact, no collapsed grids,
backgrounds present, nothing cut at the bottom):
python
import pymupdf doc = pymupdf.open("output.pdf") doc[0].get_pixmap(dpi=40).save("check.png") - If redaction was used, the forbid check already ran against the PDF text; still spot-check the rendered image for sensitive content in raster form.
- Heed the script warnings: heights above 14400pt break Acrobat (Chrome, Firefox and WeChat preview are fine); "content nearly fills the bedrock" means inspect the tail for truncation.
脚本会输出。之后:
OK 1 page, WxHpt- 生成缩略图并目视检查(布局完整,无网格塌陷,背景存在,底部无内容截断):
python
import pymupdf doc = pymupdf.open("output.pdf") doc[0].get_pixmap(dpi=40).save("check.png") - 如果使用了脱敏功能,脚本已针对PDF文本层执行了禁用词检查;仍需抽查渲染图像,确认是否存在光栅形式的敏感内容。
- 注意脚本警告:高度超过14400pt会导致Acrobat无法正常显示(Chrome、Firefox和微信预览不受影响);“content nearly fills the bedrock”意味着需要检查末尾是否存在内容截断。
Troubleshooting and mechanics
故障排查与机制说明
Read references/mechanics.md when output looks wrong
(collapsed layout, missing backgrounds, blank page, phantom second page, blurry
or missing CJK glyphs) — it documents the Chrome print-rendering rules this
tool is built around, plus the CDP-based alternative route.
当输出异常时(布局塌陷、背景缺失、空白页面、出现空白第二页、CJK字体模糊或缺失),请阅读references/mechanics.md——其中记录了此工具所基于的Chrome打印渲染规则,以及基于CDP的替代方案。