any2pdf
GitHub将Markdown转换为出版级PDF,支持CJK混合排版、代码块保留、公式及水印等高级功能。
Trigger Scenarios
Install
npx skills add cosmicstack-labs/mercury-agent-skills --skill any2pdf -g -y
SKILL.md
Frontmatter
{
"name": "any2pdf",
"metadata": {
"tags": [
"markdown",
"pdf",
"cjk",
"reportlab",
"typesetting",
"themes",
"any2pdf"
],
"author": "lovstudio",
"source": "https:\/\/github.com\/lovstudio\/any2pdf",
"curator": "cosmicstack-labs",
"license": "MIT",
"version": "1.1.0",
"category": "pdf-generation"
},
"description": "Convert Markdown to publication-quality PDF with reportlab — CJK\/Latin mixed text, themes, cover pages, watermarks, callouts, formulas, and interactive theme selection"
}
any2pdf — Markdown to Professionally Typeset PDF
Credits. This skill is adapted from
lovstudio/any2pdfby lovstudio, distributed under the MIT license. The original repository ships the Python implementation (md2pdf.py), preview gallery, and reference theme JSONs. This document is the Mercury-compatibleSKILL.mdadaptation; the runtime code and design credit belong entirely to the original author.
- Upstream: https://github.com/lovstudio/any2pdf
- License: MIT (see upstream
LICENSE)- Author: lovstudio
- Curator (this entry): cosmicstack-labs
This skill converts any Markdown file into a publication-quality PDF using Python's reportlab. It was developed through extensive iteration on real Chinese technical reports and solves several hard problems that naive MD→PDF converters get wrong — CJK/Latin mixed text wrapping, canvas CJK rendering on cover/headers/footers, code-block whitespace preservation, and mixed-font fallbacks across macOS, Linux, and Windows.
When to Use
Trigger this skill whenever the user:
- Wants to convert
.md→.pdf - Has a markdown report or document and wants professional typesetting
- Mentions "markdown to PDF", "md2pdf", "any2pdf", "md转pdf", "报告生成", or asks for a "typeset" or "professionally formatted" PDF from markdown source
- Has a document with CJK characters mixed with Latin text
- Has fenced code blocks, markdown tables, or nested lists that need to survive conversion
- Needs local/remote images, Obsidian callouts, emoji, or LaTeX-style math formulas
- Wants a cover page, table of contents, watermark, or back cover in their PDF
Where the Runtime Lives
After installing this skill via the Mercury CLI:
mercury skills install pdf-generation/any2pdf
the SKILL.md lands at ~/.mercury/skills/pdf-generation/any2pdf/SKILL.md.
The Python implementation (md2pdf.py), preview images, and theme files are not vendored into Mercury Skills — they live in the upstream repository. To use the skill end-to-end, also clone or install the upstream runtime:
# Option A: clone alongside (recommended for development)
git clone https://github.com/lovstudio/any2pdf.git
# The script is at: any2pdf/lovstudio-any2pdf/scripts/md2pdf.py
# Option B: install via the upstream's own installer
npx skills add lovstudio/any2pdf -g -y
When the AI agent runs the conversion, treat the script path as wherever the user cloned it. If unsure, ask:
"Where is the
md2pdf.pyscript on your system? (e.g../any2pdf/lovstudio-any2pdf/scripts/md2pdf.py)"
Quick Start
python <path-to>/md2pdf.py \
--input report.md \
--output report.pdf \
--title "My Report" \
--author "Author Name" \
--theme warm-academic
All parameters except --input are optional — sensible defaults are applied.
Pre-Conversion Options (MANDATORY)
IMPORTANT for AI agents: You MUST present these options to the user before running the conversion. Use whatever interactive question primitive your runtime provides (AskUserQuestion, a structured prompt, an MCP tool, etc.). Present all options in a single question so the user answers once.
The tone should be a friendly design assistant, not a config form.
Suggested Prompt Template (English)
Starting PDF conversion — quick choices first
━━━ Design Style ━━━
a) Warm Academic — terracotta tones, refined and elegant; humanities / social science
b) Classic Thesis — brown tones, LaTeX classicthesis inspired; academic papers
c) Tufte — minimal whitespace, deep red accents; data narratives, technical writing
d) IEEE Journal — navy blue, journal-formal; conferences and journals
e) Elegant Book — coffee tones, book-like; long-form monographs / technical books
f) Chinese Red — vermilion on warm paper; Chinese formal reports / whitepapers
g) Ink Wash — pure grayscale, restrained and elegant; literary / design content
h) GitHub — blue-and-white minimal; developer-familiar
i) Nord Frost — Nordic blue-gray; clean modern
j) Ocean Breeze — teal-green; fresh and natural
━━━ Frontispiece (full-page image after cover) ━━━
1) Skip
2) I'll provide a local image path
3) AI generates one based on document content
━━━ Watermark ━━━
1) None
2) Custom text (e.g. "DRAFT", "Internal Use Only")
━━━ Back Cover Material (business card / QR code / brand) ━━━
1) Skip
2) I'll provide an image
3) Plain text only
Example reply: "a, frontispiece skip, watermark: For Reference Only, back cover: /path/qr.png"
Plain English is fine — no need to memorize the letters.
Mapping User Choices to CLI Args
| Choice | CLI argument |
|---|---|
| Design style a–j | --theme <value-from-table-below> |
| Frontispiece local | --frontispiece <path> |
| Frontispiece AI | Generate image first, then --frontispiece /tmp/frontispiece.png |
| Watermark text | --watermark "TEXT" |
| Back cover image | --banner <path> |
| Back cover text | --disclaimer "..." and/or --copyright "..." |
Theme Name Mapping
| Choice | --theme value |
Inspiration |
|---|---|---|
| a) Warm Academic | warm-academic |
Lovstudio design system |
| b) Classic Thesis | classic-thesis |
LaTeX classicthesis |
| c) Tufte | tufte |
Edward Tufte's books |
| d) IEEE Journal | ieee-journal |
IEEE journal format |
| e) Elegant Book | elegant-book |
LaTeX ElegantBook |
| f) Chinese Red | chinese-red |
Chinese formal documents |
| g) Ink Wash | ink-wash |
水墨画 / ink wash painting |
| h) GitHub | github-light |
GitHub Markdown style |
| i) Nord Frost | nord-frost |
Nord color scheme |
| j) Ocean Breeze | ocean-breeze |
— |
Handling AI-Generated Frontispiece
If the user chose AI generation: read the document title and the first few paragraphs, use an image-generation tool to create a themed illustration matching the chosen design style, show the result for approval, then pass via --frontispiece /path/to/image.png.
Architecture
Markdown
→ Preprocess (split merged headings)
→ Parse (code-fence aware)
→ Story (reportlab flowables)
→ PDF build
Key components:
- Font system — Palatino (Latin body), Songti SC (CJK body), Menlo (code) on macOS; auto-fallback on Linux / Windows.
- CJK wrapper —
_font_wrap()wraps CJK character runs in<font>tags for automatic font switching. - Mixed text renderer —
_draw_mixed()handles CJK/Latin mixed text on canvas (cover, headers, footers). - Code block handler —
esc_code()preserves indentation and line breaks in reportlab Paragraphs. - Smart table widths — proportional column widths based on content length, with 18 mm minimum.
- Bookmark system —
ChapterMarkflowable creates PDF sidebar bookmarks and named anchors. - Heading preprocessor —
_preprocess_md()splits merged headings like# Part## Chapterinto separate lines. - Image handler — local, relative,
file://, and remote markdown images are scaled into the body frame with fallback text on errors. - Callout renderer — Obsidian-style
> [!NOTE]blocks render as themed boxed callouts. - Formula renderer — display formulas use optional
matplotlibmathtext images, with styled text fallback. - Emoji fallback — emojis render as cached Twemoji PNGs when available, or with a local emoji font fallback.
Hard-Won Lessons
These are real bugs that came out of shipping real reports — preserve the fixes if you're customising the script.
CJK Characters Rendering as □
reportlab's Paragraph only uses the font set in ParagraphStyle. If fontName="Mono" but the text contains Chinese, characters render as □. Fix: always apply _font_wrap() to all text that might contain CJK, including code blocks.
Code Blocks Losing Line Breaks
reportlab treats \n as whitespace. Fix: esc_code() converts \n → <br/> and all spaces → , preserving indentation and mid-line alignment before _font_wrap().
CJK/Latin Word Wrapping
Default reportlab breaks lines only at spaces, causing ugly splits like Claude\nCode. Fix: set wordWrap='CJK' on body / bullet styles to allow breaks at CJK character boundaries.
Canvas Text with CJK (Cover / Footer)
drawString() / drawCentredString() with a Latin font can't render 年/月/日 etc. Fix: use _draw_mixed() for all user-content canvas text (dates, stats, disclaimers).
Configuration Reference
Most options can also be set in the markdown file's YAML frontmatter. Explicit CLI arguments take precedence over frontmatter values.
| CLI Argument | Frontmatter Key | Default | Description |
|---|---|---|---|
--input |
— | (required) | Path to markdown file |
--output |
— | output.pdf |
Output PDF path |
--title |
title |
From first H1 | Document title for cover page |
--subtitle |
subtitle |
"" |
Subtitle text |
--author |
author |
"" |
Author name |
--date |
date |
Today | Date string |
--version |
version |
"" |
Version string for cover |
--watermark |
watermark |
"" |
Watermark text (empty = none) |
--theme |
theme |
warm-academic |
Color theme name |
--theme-file |
— | "" |
Custom theme JSON file path |
--cover |
cover |
true |
Generate cover page |
--toc |
toc |
true |
Generate table of contents |
--page-size |
page-size |
A4 |
Page size (A4 or Letter) |
--frontispiece |
frontispiece |
"" |
Full-page image after cover |
--banner |
banner |
"" |
Back cover banner image |
--header-title |
header-title |
"" |
Report title in page header |
--footer-left |
footer-left |
author | Brand / author in footer |
--stats-line |
stats-line |
"" |
Stats on cover |
--stats-line2 |
stats-line2 |
"" |
Second stats line |
--edition-line |
edition-line |
"" |
Edition line at cover bottom |
--disclaimer |
disclaimer |
"" |
Back cover disclaimer |
--copyright |
copyright |
"" |
Back cover copyright |
--code-max-lines |
code-max-lines |
30 |
Max lines per code block |
Themes
Built-in: warm-academic, classic-thesis, tufte, ieee-journal, elegant-book, chinese-red, ink-wash, github-light, nord-frost, ocean-breeze.
Each theme defines: page background, ink color, accent color, faded text color, border color, code background, and watermark tint. Preview images for every theme live in the upstream repository under previews/.
Dependencies
pip install reportlab
# Optional — render display formulas as images instead of styled text:
pip install matplotlib
Fonts
-
macOS: Palatino, Songti SC (宋体), Menlo — pre-installed.
-
Windows: Times New Roman, SimSun / 微软雅黑, Consolas — pre-installed.
-
Linux (Ubuntu/Debian recommended setup):
sudo apt install fonts-dejavu-core fonts-liberation fonts-freefont-ttf \ fonts-noto fonts-noto-cjk fonts-noto-color-emoji
Fonts are auto-discovered from system paths. Missing fonts produce a helpful error with the exact install command for your OS.
What You Get
- Cover page — title, subtitle, author, version, stats lines
- Clickable table of contents — with PDF bookmark sidebar
- Frontispiece — full-page image after cover (local or AI-generated)
- Running headers — stable report / document title without page-lagged chapter labels
- Running footers — author / brand, page number, date
- Watermark — faint diagonal text on every content page
- Back cover — banner image or text branding (QR codes, business cards)
- 10 design themes — from warm academic to ink wash minimalist
- Markdown images — local and remote
with graceful fallback text - Obsidian callouts —
> [!NOTE], warnings, tips, quotes, and related callout types - LaTeX-style formulas — inline
$...$and display$$...$$/\[...\]; installmatplotlibfor rendered math images - Emoji fallback — Twemoji image rendering when online, with local emoji-font fallback when available
- YAML frontmatter — set title, theme, watermark, cover, TOC, and other options inside the Markdown file
License & Attribution
This skill entry is a derivative work licensed under MIT, matching the upstream project.
- Original work: lovstudio/any2pdf — Copyright (c) lovstudio
- License: MIT
- This SKILL.md adaptation: curated for Mercury Skills by cosmicstack-labs; no code is redistributed, only documentation and workflow guidance.
If you ship this skill in a product, retain the upstream attribution and the MIT license notice from the original repository.
Version History
- 38e2523 Current 2026-07-05 19:41
Dependencies
-
suggested
lovstudio/any2pdf


