Permission Setup Review
python scripts/_prepare_workspace.py is an optional setup helper for the 1. Copy the bundled scripts to a working directory skill. It may apply broad filesystem permissions for compatibility. Show the target paths and permission mode, explain the risk, and prefer a narrower mode when shared write access is not needed.
1. Copy the bundled scripts to a working directory
cp /scripts/html-to-pdf.js ./ cp /scripts/package.json ./
2. Install the only dependency (downloads Chromium automatically, ~170 MB, one-time)
npm install
3. Run
node html-to-pdf.js report.html report.pdf
`<skill-dir>` is the directory that contains this SKILL.md file.
> **Note:** `npm install puppeteer` (~170 MB) downloads a pinned Chromium binary.
> This is the only install step — no system Chrome, no wkhtmltopdf, no separate server needed.
> If the environment already has Puppeteer installed, skip step 2.
---
## Command reference
node html-to-pdf.js <input.html> <output.pdf> [options]
Options: --paginated A4-paginated mode (respects @media print, page-breaks) --format Page format: A4 (default), A3, Letter, Legal --width Viewport width for single-page mode (default: 1440) --wait Extra milliseconds to wait after page load (for JS-rendered content) --header-footer Add page-number footer in paginated mode
### Examples
```bash
# Single-page full-height (atypica report style)
node html-to-pdf.js report.html report.pdf
# A4 paginated document
node html-to-pdf.js document.html document.pdf --paginated
# A4 with page numbers
node html-to-pdf.js document.html document.pdf --paginated --header-footer
# Narrower single-page layout
node html-to-pdf.js report.html report.pdf --width 1280
# Wait 2 s for JavaScript-rendered charts
node html-to-pdf.js dashboard.html dashboard.pdf --wait 2000
How it works (mirrors atypica's browser service)
- Launches headless Chromium via Puppeteer with sandbox disabled and CJK font hints enabled.
- Loads the HTML from a
file://URL so relative assets (images, local CSS) resolve correctly. - Injects system-font CSS to ensure Chinese/Japanese/Korean characters render on any OS.
- Single-page mode: measures
document.body.scrollHeight, sets viewport to that height, and generates a single-page PDF at that exact size — no clipping, no page breaks. - Paginated mode: injects
@media printCSS for clean page-breaks, then generates a standard-format paginated PDF. - Writes the PDF buffer to the output path.
Handling common issues
| Problem | Fix |
|---|---|
Chromium not found after npm install puppeteer |
Run npx puppeteer browsers install chrome |
| Missing system fonts / boxes instead of CJK chars | Inject works for most cases; for guaranteed rendering install fonts-noto-cjk (Linux) or ensure macOS system fonts are accessible |
| JavaScript-rendered content missing | Add --wait 2000 (or more) to let JS execute after load |
| Images not loading | Make sure image src paths are relative to the HTML file location |
| PDF cut off at bottom | The script auto-measures height; if content loads lazily add --wait |
--no-sandbox error in strict container |
Puppeteer requires --no-sandbox in Docker/CI; this flag is already set |
Dependency notes
- Node.js ≥ 18 required (≥ 20 recommended)
puppeteeris the onlynpmdependency — it self-contains Chromium- No global Chrome installation needed
- Works on macOS, Linux, and Windows (WSL)
- In CI/Docker, add
--disable-dev-shm-usage(already included in the script)