pdf-creator

Convert markdown files to professional PDF documents with proper Chinese font support, theme system, and visual self-check. Use whenever the user asks to…

INSTALLATION
npx skills add https://github.com/daymade/claude-code-skills --skill pdf-creator
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

No weasyprint? Use Chrome backend (auto-detected if weasyprint unavailable)

python scripts/md_to_pdf.py input.md --theme warm-terra --backend chrome

List available themes

python scripts/md_to_pdf.py --list-themes dummy.md

## Themes

Stored in `themes/*.css`. Each theme is a standalone CSS file.

| Theme | Page Size | Font | Color | Best for |

|-------|-----------|------|-------|----------|

| `default` | A4 | Songti SC + Heiti SC | Black/grey | Legal docs, contracts, formal reports |

| `warm-terra` | A4 | PingFang SC | Terra cotta (#d97756) + warm neutrals | Course outlines, training materials, workshops |

| `mobile` | 148mm × 210mm | PingFang SC | Terra cotta + warm neutrals | Phone reading, WeChat sharing, on-the-go reference |

To create a new theme: copy `themes/default.css`, modify, save as `themes/your-theme.css`.

## Print vs Mobile: Choose the Right Theme

| Scenario | Recommended Theme | Why |

|----------|-------------------|-----|

| Print on A4 paper, handouts, contracts | `default` | Standard page size, formal typography |

| Training materials, course outlines | `warm-terra` | Warm accent color, readable for workshop contexts |

| Send via WeChat, read on phone | `mobile` | Narrow page (148mm), 15px font, 1.9 line-height — comfortable on small screens |

| Both print AND mobile needed | Run twice with different themes | The skill is fast; generate both versions |

**Decision rule:** If the user does not specify, default to `warm-terra` for training/course content and `default` for formal documents. Ask "是否需要手机版?" only when the output channel is unclear.

## Backends

The script auto-detects the best available backend:

| Backend | Install | Pros | Cons |

|---------|---------|------|------|

| `weasyprint` | `pip install weasyprint` | Precise CSS rendering, no browser needed | Requires system libs (cairo, pango) |

| `chrome` | Google Chrome installed | Zero Python deps, great CJK support | Larger binary, slightly less CSS control |

Override with `--backend chrome` or `--backend weasyprint`.

## Batch Convert

Default theme, same directory

uv run --with weasyprint scripts/batch_convert.py *.md

Specific theme, output directory, skip previews for speed

uv run --with weasyprint scripts/batch_convert.py *.md --theme warm-terra --output-dir ./pdfs --no-preview

Mobile theme for phone reading

uv run --with weasyprint scripts/batch_convert.py *.md --theme mobile --output-dir ./mobile-pdfs --no-preview


## Anti-Pattern: Do NOT Manually Invoke pandoc + Chrome

**Why this skill exists:** Manual `pandoc input.md -o out.html` + `chrome --headless --print-to-pdf` workflows silently fail in ways that are hard to detect:

Manual Step
What Goes Wrong
This Skill Fixes

`pandoc -o out.html`
No CJK-aware CSS → boxes/blanks for Chinese
Injects CJK font stack + typography patch

Chrome `--print-to-pdf`
Default header/footer appears (filename, date, URL, page numbers)
Passes `--no-pdf-header-footer`

No post-render check
"Exit code 0" assumed success; rendering bugs hidden
Auto-generates per-page PNG previews + typography lint

No theme system
One-size-fits-all; phone reading impossible
Three curated themes (default / warm-terra / mobile)

`batch_convert.py` missing
Writing ad-hoc loops, inconsistent flags
Built-in batch mode with `--theme` support

**Rule:** When the user asks for PDF conversion, ALWAYS use this skill. Never bypass it with manual pandoc/Chrome commands.

## Troubleshooting

**Chinese characters display as boxes**: Ensure Chinese fonts are installed (Songti SC, PingFang SC, etc.)

**weasyprint import error**: Run with `uv run --with weasyprint` or use `--backend chrome` instead.

**CJK text in code blocks garbled (weasyprint)**: The script auto-detects code blocks containing Chinese/Japanese/Korean characters and converts them to styled divs with CJK-capable fonts. If you still see issues, use `--backend chrome` which has native CJK support. Alternatively, convert code blocks to markdown tables before generating the PDF.

**Chrome header/footer appearing**: The script passes `--no-pdf-header-footer`. If it still appears, your Chrome version may not support this flag — update Chrome. **Note:** If you bypassed this skill and used manual Chrome headless, this is the first symptom — see "Anti-Pattern" section above.

**Inline code with mixed CJK + ASCII shows blanks in macOS Preview** (e.g. ``Terminal/终端`` renders only `Terminal/` with the CJK part missing): weasyprint subset-embeds PingFang SC as **OpenType (CID Type 0C)**, which strict PDF readers (macOS Preview / Adobe Reader) fail to render. Chrome's PDF viewer falls back automatically and hides the bug. Fix is in the default theme: code font-family chain prioritizes **CID TrueType** CJK fonts (Songti SC / Heiti SC) before OpenType ones (PingFang SC). To verify: `pdfplumber` + check `font['fontname']` of CJK chars — if any references `PingFang-SC` (CID Type 0C OT), readers will likely fail. Reorder font chain to put CID TrueType first.

**Table column 1 with short label gets mid-broken** (e.g. `4/28(周|二)下|午`): pandoc auto-emits `<colgroup><col style="width:X%">` from dash counts in the markdown separator row. For `| ----- | --- | --- | -------- |` (uneven dash widths), pandoc allocates col 1 ~17% — too narrow for a 9-char CJK label. Inline `style=""` beats external CSS at equal specificity, so `td:first-child { width:... }` is silently shadowed. Fix is in default theme: `table colgroup col { width: auto !important }` neutralizes pandoc's hint, letting `table-layout: fixed` distribute equally (25% per column for a 4-col table). To verify: `pandoc input.md -t html | grep colgroup` — if it shows `<col style="width:X%">`, the bug applies.

## Visual Self-Check (MANDATORY — Do Not Skip)

**This is not optional.** After every PDF generation, the script automatically:

- Converts each page to PNG via `pdftoppm` (poppler-utils) into a `<pdf-name>-preview/` directory next to the PDF

- Prints a structured self-check checklist reminding the caller to visually inspect each page

- Runs typography lint to detect CJK line-break anti-patterns

**Why mandatory**: "PDF generated cleanly" ≠ "rendering matches markdown intent". Common silent failures include:

- Paragraphs collapsing into one (CommonMark soft-break on consecutive non-blank lines)

- Tables overflowing page margins

- Missing CJK / emoji glyphs

- Code block garbling

- Chrome default headers/footers (if bypassed this skill)

**Workflow**: After running the script, `Read` each `page-NN.png` and verify against the markdown source. If anything renders differently from intent, **fix the markdown** (use `- ` real lists instead of pseudo-lists, insert blank lines, restructure tables) and rerun. The script does NOT silently "fix" non-standard markdown — that would mask the signal that the source is wrong, causing the same markdown to render incorrectly in other processors (Obsidian, GitHub, VS Code preview).

**Disable** with `--no-preview` for batch / non-interactive runs:

python scripts/md_to_pdf.py input.md output.pdf --no-preview

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card