Markdown PDF Skill
Turn Markdown into a professional PDF and prove that the rendered pages are sound. Treat pagination as part of the design, not as a final conversion step.
Workflow
-
Ask about the table of contents before doing any layout work.
- Ask the user:
是否需要加入目录? - Wait for the answer. Do not infer the choice from document length.
- Skip the question only when the current request already says to include or omit a table of contents.
- Pass
--tocfor yes or--no-tocfor no. The exporter rejects an omitted choice.
- Ask the user:
-
Inspect the source before exporting.
- Identify the language, title hierarchy, long tables, long code blocks, local or remote images, raw HTML, footnotes, math, and explicit page-break requests.
- Preserve the author's words and structure unless the user asks for editorial changes.
- Read references/markdown-support.md when the document uses unusual Markdown, diagrams, math, raw HTML, or oversized media.
-
Choose print geometry and style deliberately.
- Default to A4 portrait for CJK and international documents.
- Use Letter only for US-facing material.
- Use landscape for genuinely wide tables; do not shrink normal prose to rescue one table.
- Honor an explicitly requested theme. Otherwise keep
--theme autoand report the selected theme and reason. - Run
python3 scripts/export_markdown_pdf.py --list-themesor read references/themes.md when the user wants choices. - Read references/pagination.md before tuning a long or layout-sensitive document.
-
Export with the bundled renderer.
bashpython3 scripts/export_markdown_pdf.py INPUT.md -o OUTPUT.pdf --toc --theme autoUse
--remote-images freeze(the default) to download and embed online images. Add--orientation landscape, an explicit--theme,--math, or--css custom.cssonly when the content requires it. Use<!-- pagebreak -->for an intentional hard break. Use<div class="keep-together" markdown="1">...</div>sparingly for a short block that must remain intact. -
Inspect the actual PDF, not only the HTML.
bashpython3 scripts/inspect_pdf.py OUTPUT.pdf --output-dir tmp/pdfs/reviewOpen the generated contact sheet, then inspect suspicious pages at full resolution. Check every page for clipped content, awkward whitespace, orphaned headings, lonely final lines, table row breaks, repeated table headers, split captions, image scale, code wrapping, page numbering, and CJK glyph fallback.
-
Iterate until clean.
- Fix the source structure first, then CSS.
- Prefer local, targeted classes or page breaks over global font reduction.
- Re-export and re-run inspection after every meaningful layout change.
- Deliver only after the latest rendered pages show no visible defects.
Installation
Create an isolated environment and install the pinned capability set when imports are missing:
bashpython3 -m venv .venv .venv/bin/python -m pip install -r scripts/requirements.txt
The renderer uses Python-Markdown, WeasyPrint, and Matplotlib's vector math renderer. The inspector uses PyMuPDF, pypdf, and Pillow. If WeasyPrint installation fails because native libraries are absent, follow the platform instructions printed by WeasyPrint rather than silently switching renderers; pagination differs across engines.
Rendering Rules
- Keep headings with at least the next content block.
- Apply widows and orphans controls to prose and list items.
- Keep short tables, code blocks, quotes, and figures together; allow oversized blocks to split so they do not overflow or create blank pages.
- Repeat table headers across pages and never split a table row.
- Keep captions with their media.
- Preserve readable type size. Change orientation or restructure an oversized table before reducing body text.
- Use system CJK font fallbacks and verify every glyph visually.
- Keep links clickable, footnotes legible, and syntax highlighting printable in grayscale.
- Avoid a hard page break unless semantic grouping or visual balance clearly benefits.
Inputs and Outputs
- Accept UTF-8 Markdown and resolve relative images from the Markdown file's directory.
- Read optional YAML frontmatter keys:
title,subtitle,author,date, andlang. - Resolve local images from the Markdown directory. Download and embed remote images by default; use live URLs only when the user explicitly accepts non-reproducible output.
- Preserve raw HTML supported by WeasyPrint. Expect JavaScript-dependent content to require pre-rendering.
- Write final PDFs to the path requested by the user. Place temporary HTML, page images, and reports under
tmp/pdfs/and remove them after final approval. - Keep filenames stable and descriptive.
Manual Controls
- Insert
<!-- pagebreak -->for an explicit new page. - Wrap a short unit in
<div class="keep-together" markdown="1">...</div>to prohibit an internal break. - Wrap content in
<div class="avoid-break-before" markdown="1">...</div>to keep it near the preceding block. - Add a user stylesheet with
--css; keep overrides narrow and document-specific. - Save intermediate HTML with
--html-output PATHwhen diagnosing selector or asset problems.
Quality Gate
Require all of the following before delivery:
- The exporter completes without missing-asset or unsupported-feature warnings.
- The inspector reports the expected page size, no blank pages, no out-of-bounds text or image blocks, and no heading stranded at a page bottom.
- Contact-sheet review covers every page.
- Full-size review covers the first page, final page, every page transition around a table or code block, and every page reported as suspicious.
- Extracted text is non-empty and major headings appear in the expected order.
- The final PDF contains no placeholders, debug paths, tool tokens, or accidental intermediate content.
Use references/qa-checklist.md for the final visual pass.


