
Lovstudio Any2pdf
- 98 installs
- 198 repo stars
- Updated May 30, 2026
- lovstudio/any2pdf
Helps with ai & agent building tasks.
About
lovstudio-any2pdf is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- lovstudio-any2pdf
- AI & Agent Building
- AI-coding skill
Lovstudio Any2pdf by the numbers
- 98 all-time installs (skills.sh)
- Ranked #4,439 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/lovstudio/any2pdf --skill lovstudio-any2pdfAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 98 |
|---|---|
| repo stars | ★ 198 |
| Last updated | May 30, 2026 |
| Repository | lovstudio/any2pdf ↗ |
What it does
Helps with ai & agent building tasks.
Files
any2pdf — Markdown to Professional PDF
This skill converts any Markdown file into a publication-quality PDF using Python's reportlab library. It was developed through extensive iteration on real Chinese technical reports and solves several hard problems that naive MD→PDF converters get wrong.
When to Use
- User wants to convert
.md→.pdf - User has a markdown report/document and wants professional typesetting
- Document contains CJK characters (Chinese/Japanese/Korean) mixed with Latin text
- Document has fenced code blocks, markdown tables, or nested lists
- Document has local/remote images, Obsidian callouts, emoji, or math formulas
- User wants a cover page, table of contents, or watermark in their PDF
Quick Start
python md2pdf/scripts/md2pdf.py \
--input report.md \
--output report.pdf \
--title "My Report" \
--author "Author Name" \
--theme warm-academicAll parameters except --input are optional — sensible defaults are applied.
Pre-Conversion Options (MANDATORY)
IMPORTANT: You MUST use the `AskUserQuestion` tool to ask these questions BEFORE running the conversion. Do NOT list options as plain text — use the tool so the user gets a proper interactive prompt. Ask all options in a SINGLE `AskUserQuestion` call.
Use AskUserQuestion with the following template. The tone should be friendly and concise — like a design assistant, not a config form:
开始转 PDF!先帮你确认几个选项 👇
━━━ 📐 设计风格 ━━━
a) 暖学术 — 陶土色调,温润典雅,适合人文/社科报告
b) 经典论文 — 棕色调,灵感源自 LaTeX classicthesis,适合学术论文
c) Tufte — 极简留白,深红点缀,适合数据叙事/技术写作
d) 期刊蓝 — 藏蓝严谨,灵感源自 IEEE,适合正式发表风格
e) 精装书 — 咖啡色调,书卷气,适合长篇专著/技术书
f) 中国红 — 朱红配暖纸,适合中文正式报告/白皮书
g) 水墨 — 纯灰黑,素雅克制,适合文学/设计类内容
h) GitHub — 蓝白极简,程序员熟悉的风格
i) Nord 冰霜 — 蓝灰北欧风,清爽现代
j) 海洋 — 青绿色调,清新自然
━━━ 🖼 扉页图片(封面之后的全页插图) ━━━
1) 跳过
2) 我提供本地图片路径
3) AI 根据内容自动生成一张
━━━ 💧 水印 ━━━
1) 不加
2) 自定义文字(如 "DRAFT"、"内部资料")
━━━ 📇 封底物料(名片/二维码/品牌) ━━━
1) 跳过
2) 我提供图片
3) 纯文字信息
示例回复:"a, 扉页跳过, 水印:仅供学习参考, 封底图片:/path/qr.png"
直接说人话就行,不用记编号 😄Mapping User Choices to CLI Args
| Choice | CLI arg |
|---|---|
| Design style a-j | --theme with value from table below |
| Frontispiece local | --frontispiece <path> |
| Frontispiece AI | Generate image first, then --frontispiece /tmp/frontispiece.png |
| Watermark text | --watermark "文字" |
| Back cover image | --banner <path> |
| Back cover text | --disclaimer "声明" and/or --copyright "© 信息" |
Theme Name Mapping
| Choice | --theme value | Inspiration |
|---|---|---|
| a) 暖学术 | warm-academic | Lovstudio design system |
| b) 经典论文 | classic-thesis | LaTeX classicthesis |
| c) Tufte | tufte | Edward Tufte's books |
| d) 期刊蓝 | ieee-journal | IEEE journal format |
| e) 精装书 | elegant-book | LaTeX ElegantBook |
| f) 中国红 | chinese-red | Chinese formal documents |
| g) 水墨 | ink-wash | 水墨画 / ink wash painting |
| h) GitHub | github-light | GitHub Markdown style |
| i) Nord | nord-frost | Nord color scheme |
| j) 海洋 | ocean-breeze | — |
Handling AI-Generated Frontispiece
If user chose AI generation: read the document title + first paragraphs, use an image generation tool to create a themed illustration matching the chosen design style, show for approval, then pass via --frontispiece /path/to/image.png
Architecture
Markdown → Preprocess (split merged headings) → Parse (code-fence-aware) → Story (reportlab flowables) → PDF buildKey components: 1. Font system: Palatino (Latin body), Songti SC (CJK body), Menlo (code) on macOS; auto-fallback on Linux 2. CJK wrapper: _font_wrap() wraps CJK character runs in <font> tags for automatic font switching 3. Mixed text renderer: _draw_mixed() handles CJK/Latin mixed text on canvas (cover, headers, footers) 4. Code block handler: esc_code() preserves indentation and line breaks in reportlab Paragraphs 5. Smart table widths: Proportional column widths based on content length, with 18mm minimum 6. Bookmark system: ChapterMark flowable creates PDF sidebar bookmarks + named anchors 7. Heading preprocessor: _preprocess_md() splits merged headings like # Part## Chapter into separate lines 8. Image handler: local, relative, file://, and remote markdown images are scaled into the body frame with fallback text on errors 9. Callout renderer: Obsidian-style > [!NOTE] blocks render as themed boxed callouts 10. Formula renderer: display formulas use optional matplotlib mathtext images, with styled text fallback 11. Emoji fallback: emoji are rendered as cached Twemoji PNGs when available, or with a local emoji font fallback
Hard-Won Lessons
CJK Characters Rendering as □
reportlab's Paragraph only uses the font in ParagraphStyle. If fontName="Mono" but text contains Chinese, they 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 top-of-file YAML-style frontmatter. Explicit CLI arguments take precedence over frontmatter values.
| 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
Available: warm-academic, nord-frost, github-light, solarized-light, paper-classic, ocean-breeze.
Each theme defines: page background, ink color, accent color, faded text, border, code background, watermark tint.
Dependencies
pip install reportlab --break-system-packages
# Optional formula rendering:
pip install matplotlib --break-system-packagesRecommended Ubuntu/Debian fonts:
sudo apt install fonts-dejavu-core fonts-liberation fonts-freefont-ttf fonts-noto fonts-noto-cjk fonts-noto-color-emojiTheme Reference
Each theme is a Python dict with these keys. All values are hex color strings.
Theme Structure
THEME = {
"canvas": "#F9F9F7", # page background
"canvas_sec": "#F0EEE6", # secondary bg (code blocks, alternating rows)
"ink": "#181818", # primary text
"ink_faded": "#87867F", # secondary text (subtitles, captions)
"accent": "#CC785C", # primary accent (headings, rules, table headers)
"accent_light":"#D99A82", # lighter accent
"border": "#E8E6DC", # borders, horizontal rules
"code_bg": "#F0EEE6", # code block background (usually = canvas_sec)
"watermark": (0.82, 0.80, 0.76, 0.12), # RGBA tuple for watermark
}Available Themes
warm-academic (default)
Warm ivory canvas with terracotta accents. Inspired by academic papers on aged paper. Best for: Chinese technical reports, research papers, documentation.
{"canvas":"#F9F9F7","canvas_sec":"#F0EEE6","ink":"#181818","ink_faded":"#87867F",
"accent":"#CC785C","accent_light":"#D99A82","border":"#E8E6DC"}nord-frost
Cool blue-gray palette from the Nord color scheme. Best for: Developer documentation, technical specs.
{"canvas":"#ECEFF4","canvas_sec":"#E5E9F0","ink":"#2E3440","ink_faded":"#4C566A",
"accent":"#5E81AC","accent_light":"#81A1C1","border":"#D8DEE9"}github-light
Clean white with blue accents, matching GitHub's documentation style. Best for: Open-source project docs, README-style reports.
{"canvas":"#FFFFFF","canvas_sec":"#F6F8FA","ink":"#1F2328","ink_faded":"#656D76",
"accent":"#0969DA","accent_light":"#218BFF","border":"#D0D7DE"}monokai-warm
Dark background with warm accent colors. Best for: Code-heavy reports, developer presentations.
{"canvas":"#272822","canvas_sec":"#1E1F1C","ink":"#F8F8F2","ink_faded":"#75715E",
"accent":"#F92672","accent_light":"#FD971F","border":"#49483E"}solarized-light
Ethan Schoonover's Solarized Light palette. Best for: Long-form reading, academic papers.
{"canvas":"#FDF6E3","canvas_sec":"#EEE8D5","ink":"#657B83","ink_faded":"#93A1A1",
"accent":"#CB4B16","accent_light":"#DC322F","border":"#EEE8D5"}dracula-soft
Softened Dracula theme with muted dark purple background. Best for: Evening reading, dark-mode preference reports.
{"canvas":"#282A36","canvas_sec":"#21222C","ink":"#F8F8F2","ink_faded":"#6272A4",
"accent":"#BD93F9","accent_light":"#FF79C6","border":"#44475A"}paper-classic
Pure white with black text and minimal red accents. Traditional print look. Best for: Formal documents, print-ready reports, submissions.
{"canvas":"#FFFFFF","canvas_sec":"#FAFAFA","ink":"#000000","ink_faded":"#666666",
"accent":"#CC0000","accent_light":"#FF3333","border":"#DDDDDD"}ocean-breeze
Light teal/aqua tones for a fresh, modern feel. Best for: Product reports, marketing docs, light technical content.
{"canvas":"#F0F7F4","canvas_sec":"#E0EDE8","ink":"#1A2E35","ink_faded":"#5A7D7C",
"accent":"#2A9D8F","accent_light":"#64CCBF","border":"#C8DDD6"}Custom Theme
Pass a JSON file path to --theme-file:
{
"canvas": "#FEFEFE",
"canvas_sec": "#F5F5F5",
"ink": "#222222",
"ink_faded": "#888888",
"accent": "#E74C3C",
"accent_light": "#F39C12",
"border": "#DDDDDD"
}