Die Oberfläche ist lokalisiert; Skill-Beschreibungen und -Dokumente werden per KI automatisch in Ihre Sprache übersetzt. Code, Befehle, Pfade und Fachbegriffe bleiben im Original, maßgeblich ist das Dokument des Autors.
Skills entdecken
Dokumente · SKILL.md

pdf-converter

pdf-converter

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.

Independent GitHub snapshot · Automated classification · Original documentation governs

Skill-Dokumentation

GitHub

name: pdf-converter description: > 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. compatibility: Python 3, pandoc, typst, py3-pillow; Alpine (iSH) / Termux (Android) / Debian

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.

PlatformInstall
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 / Ubuntuapt 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.pdf

Step 3 — Verify the output

ls -la out.pdf

On 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 cache

On 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)
ComponentRole
pandocConverts MD / HTML / reST / org / latex → typst markup
typstRust binary; compiles typst markup → PDF with native font fallback
Twemoji SVGEmoji → vector images; CDN download + local cache
PILImage merging (lazy-imported; image-only mode skips pandoc/typst entirely)

Font Strategy

Character typeFontHandling
ASCII (digits / letters)DejaVu Sanstypst native fallback — half-width glyphs
ChineseWenQuanYi Zen Heitypst native fallback
EmojiTwemoji SVGCDN download → typst image() embed

Configuration (environment variables)

VariableDefaultPurpose
EMOJI_CDN_BASEunsetOverride 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_WORKERS8 on Termux, 4 elsewhereConcurrency for SVG prefetch. iSH defaults lower because emulated x86 has tight fd / memory limits.
EMOJI_SVG_TIMEOUT15Per-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

ConditionBehavior
Missing input filePython 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 errorstderr ❌ pandoc: <msg>, exit 1
typst compile errorstderr ❌ typst: <msg>, exit 1
typst compile timeoutdefault 120 s; stderr error, exit 1
Emoji SVG download fails on all mirrorsFalls 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 KB

Check 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's inset; use block(inset: ...) instead to preserve padding.
  • Table width: pandoc emits columns: N for narrow tables → rewritten to 1fr columns 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-27BF uses a precise frozenset of 116 Twemoji-provided codepoints (not the full range — symbols like ☐☒★♔♪ aren't Twemoji and would 404); U+1F300-1FAFF uses 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.
Gespeicherte Skills