pdf-converter
Skill584 starsChanged 59 days agoMITView on GitHub
Convert documents to PDF via a typst-based pipeline. Supports Markdown, HTML, plain text, images, and any pandoc-supported format. Use this skill whenever the user asks to "convert to PDF", "generate a PDF", "export as PDF", "turn X into a PDF", or says "转PDF" / "生成PDF" / "导出PDF". Also covers merging multiple images into one PDF.
- Installs packages
We split this skill into the rules it gives an agent
3 rules. 0 are common, 2 are distinctive, and 1 is very specific to this project.
0
Common
Most of the 4 edited versions we read keep these.
2
Distinctive
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 19
Use this skill when the user needs to:
- Distinctive: line 161
Verify the install (and any dependency change) using the bundled format-test document, then sanity-check against the bundled reference PDF:
- Very specific: line 170
Check visually: amber table headers at full width, SVG emoji rendered (not tofu boxes), half-width digits inside CJK paragraphs, all …
“Common” is measured: kept by at least 6 in 10 of the 4 edited versions of this file we could read. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
pdf-converter
Convert documents to PDF with proper CJK rendering, half-width digits, and emoji support. Uses a typst-based pipeline that compiles markup directly to PDF in ~5 s per conversion for a typical 10-page document.
When to Use This Skill
Use this skill when the user needs to:
- Convert Markdown (
.md) to PDF preserving tables, code blocks, emoji, and Chinese text - Convert HTML (
.htm,.html) to PDF - Convert plain text (
.txt) to PDF - Convert images (
.png/.jpg/.jpeg/.gif/.bmp/.webp) to PDF, including multi-image merge into one PDF - Convert any pandoc-supported format (
.rst,.org,.latex, etc.) to PDF
Workflow
Step 1 — Prerequisites (self-checked on every run)
The script verifies pandoc + typst are on PATH (and PIL for the
image-merge path). If anything is missing, it prints platform-specific install
commands and exits non-zero — no silent pandoc/typst failure later.
| Platform | Install |
| Alpine (iSH / Docker) | apk add pandoc typst py3-pillow font-wqy-zenhei font-dejavu font-noto-emoji |
| Termux (Android) | pkg install pandoc typst python-pillow font-wqy-zenhei font-dejavu noto-color-emoji |
| Debian / Ubuntu | apt install pandoc typst python3-pillow fonts-wqy-zenhei fonts-dejavu fonts-noto-color-emoji |
The font directory is auto-detected from candidate paths (/usr/share/fonts,
$PREFIX/share/fonts, /usr/local/share/fonts).
Step 2 — Run the conversion
Format is detected by the file extension:
# Markdown → PDF (formatting, emoji, Chinese, half-width digits, amber theme)
python3 scripts/to_pdf.py doc.md -o out.pdf
# HTML → PDF
python3 scripts/to_pdf.py page.html -o out.pdf
# Plain text → PDF (file stem used as title unless --title given)
python3 scripts/to_pdf.py notes.txt -o out.pdf --title "My Notes"
# Merge images into one PDF (one page per image)
python3 scripts/to_pdf.py img1.jpg img2.png -o merged.pdf
# Any pandoc-supported format (.rst/.org/.latex…) → PDF
python3 scripts/to_pdf.py doc.rst -o out.pdfStep 3 — Verify the output
ls -la out.pdfOn success the script prints ✅ PDF generated: <path> and exits 0. On failure
it prints a ❌-prefixed diagnostic to stderr and exits non-zero.
Performance
pandoc (input → typst markup) ~1-2 s
emoji SVG prefetch (parallel) ~0 s warm cache, ~30 s first-run for ~90 emoji
typst compile (typst → PDF) ~1-3 s for a 10-page document
─────────────────────────────────────────
total ~5 s warm cacheOn iOS (iSH, emulated x86) expect a 5–10× slowdown; for very large documents or first-run emoji downloads, run in the background to avoid iOS killing the app:
nohup python3 scripts/to_pdf.py big.md -o big.pdf > /tmp/pdf.log 2>&1 &Output Formatting (amber theme)
- Headings: h1 with amber underline (
#D97706), h1–h4 hierarchy - Tables: amber header (white bold text) + zebra stripes + thin grid borders, spans full content width
- Code blocks: light gray background (
#f2f3f5) + DejaVu Sans Mono + top gray bar - Blockquotes: amber left bar + light orange background (
#fef7ed) - Emoji: Twemoji SVG vector images, baseline-aligned with CJK text
- Footer: centered page number
How It Works
pandoc (MD/HTML/… → typst) → [emoji → SVG, table-width fix] → typst compile (→ PDF)| Component | Role |
| pandoc | Converts MD / HTML / reST / org / latex → typst markup |
| typst | Rust binary; compiles typst markup → PDF with native font fallback |
| Twemoji SVG | Emoji → vector images; CDN download + local cache |
| PIL | Image merging (lazy-imported; image-only mode skips pandoc/typst entirely) |
Font Strategy
| Character type | Font | Handling |
| ASCII (digits / letters) | DejaVu Sans | typst native fallback — half-width glyphs |
| Chinese | WenQuanYi Zen Hei | typst native fallback |
| Emoji | Twemoji SVG | CDN download → typst image() embed |
Configuration (environment variables)
| Variable | Default | Purpose |
EMOJI_CDN_BASE | unset | Override the Twemoji CDN with a single mirror URL (corporate proxy, ghproxy, air-gapped cache). When unset, a GitHub raw → jsDelivr → unpkg fallback chain is used. |
PDF_CONVERTER_WORKERS | 8 on Termux, 4 elsewhere | Concurrency for SVG prefetch. iSH defaults lower because emulated x86 has tight fd / memory limits. |
EMOJI_SVG_TIMEOUT | 15 | Per-request timeout in seconds for SVG downloads. Raise on very slow networks; lower on fast reliable ones. |
File Structure
pdf-converter/
├── SKILL.md
├── .gitignore
├── assets/
│ ├── template.typ # typst amber-theme template (committed)
│ └── emoji_cache/ # Twemoji SVG cache (gitignored, created at runtime)
├── scripts/
│ └── to_pdf.py # main script (pandoc + typst + SVG emoji)
└── evals/
├── evals.json # test cases
├── pdf-format-test.md # comprehensive format test document
└── pdf-format-test.pdf # expected output reference (10 pages, ~275 KB)Error Handling
| Condition | Behavior |
| Missing input file | Python IOError / pandoc error, exit non-zero |
Missing pandoc / typst (text mode) | Self-check prints install hints, exit 1 |
Missing PIL (image mode) | Self-check prints install hint, exit 1 |
| pandoc parse error | stderr ❌ pandoc: <msg>, exit 1 |
| typst compile error | stderr ❌ typst: <msg>, exit 1 |
| typst compile timeout | default 120 s; stderr error, exit 1 |
| Emoji SVG download fails on all mirrors | Falls back to Noto Color Emoji bitmap font; stderr warning, conversion continues |
Testing
Verify the install (and any dependency change) using the bundled format-test document, then sanity-check against the bundled reference PDF:
python3 scripts/to_pdf.py evals/pdf-format-test.md -o /tmp/test.pdf
pdfinfo /tmp/test.pdf | grep Pages # expect: Pages: 10
ls -la /tmp/test.pdf # expect: ~200-350 KBCheck visually: amber table headers at full width, SVG emoji rendered (not
tofu boxes), half-width digits inside CJK paragraphs, all sections present.
Compare against evals/pdf-format-test.pdf (generated from the same source).
Key Implementation Notes
- Table header height: a show rule replacing cells with plain
text()drops the cell'sinset; useblock(inset: ...)instead to preserve padding. - Table width: pandoc emits
columns: Nfor narrow tables → rewritten to1frcolumns so tables span full content width. - Emoji alignment:
box(image(...), baseline: 5%)aligns the image bottom with the CJK text baseline. - Emoji detection:
U+2600-27BFuses a precise frozenset of 116 Twemoji-provided codepoints (not the full range — symbols like ☐☒★♔♪ aren't Twemoji and would 404);U+1F300-1FAFFuses the full range. - Parallel SVG prefetch: unique emoji sequences are collected, then missing SVGs are batch-downloaded concurrently before the replacement pass — first-run (empty cache) ~30 s instead of >180 s serial.
- CDN fallback: each SVG tries GitHub raw → jsDelivr → unpkg (or the single URL in
EMOJI_CDN_BASE); a 404 or timeout on one mirror transparently retries the next, with a per-request timeout (EMOJI_SVG_TIMEOUT, default 15 s) to prevent hung connections from stalling the prefetch batch. - Mode-aware dependency check: image-merge mode requires only PIL; text/markup mode requires pandoc + typst. Image-only users aren't forced to install the heavy pandoc/typst toolchain.
Other versions5 projects use a version of this.
Word for word · 0
None found.
Edited · 1
- lsongdev/skills★ 014% same
Wrote their own version · 4
- ComPDFKit/compdf-skills★ 108same name
- tanis90/pdf-converter-mineru★ 55same name
- baklib-tools/skills★ 2same name
- anglinai/theaccessible-skill★ 0same name
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository56 other files it gives its agents.
- android-devSkill
- android-ui-automationSkill
- apple-remindersSkill
- appstoreprice-hubSkill
- asc-cliSkill
- bilibili-hubSkill
- Clash 控制器Skill
- cloudflare-dnsSkill
- codex-imageSkill
- codex-on-ishSkill
- contact-vcard-extractorSkill
- coredevice-toolkitSkill
- deepseek-usageSkill
- doubao-ttsSkill
- douyin-downloaderSkill
- evidence-chain-builderSkill
- exa-searchSkill
- free-ttsSkill
- fucai3d-latestSkill
- generative-ui-minisSkill
- github-sync-helperSkill
- health-sleep-analysisSkill
- health-training-checkinSkill
- hyperframes-cliSkill
- hyperframesSkill
- ios-devSkill
- korea-stockSkill
- maimai-hubSkill
- memos-apiSkill
- nano-bananaSkill
- notion-hubSkill
- openstreetmap-markerSkill
- production-agent-publicSkill
- qbt-hubSkill
- quark-hubSkill
- reverse-dcfSkill
- self-improving-agentSkill
- shortcuts-builderSkill
- shortcut-share-fileSkill
- spotify-hubSkill
- stock-fund-flowSkill
- stock-priceSkill
- tavily-searchSkill
- tg-hubSkill
- todoocardSkill
- twitter-downloaderSkill
- twitter-x-hubSkill
- us-stockSkill
- web-content-extractorSkill
- web-searchSkill
- weibo-hubSkill
- whenpeakSkill
- xianyu-hubSkill
- xiaohongshu-hubSkill
- youtube-downloaderSkill
- ytmusic-hubSkill
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

