with one click
md2pdf
// Convert markdown files to styled PDFs. Supports Mermaid diagrams, tables, professional typography. Individual or combined output.
// Convert markdown files to styled PDFs. Supports Mermaid diagrams, tables, professional typography. Individual or combined output.
| name | md2pdf |
| description | Convert markdown files to styled PDFs. Supports Mermaid diagrams, tables, professional typography. Individual or combined output. |
| user-invocable | true |
| argument-hint | <file.md> [file2.md ...] [--combined output.pdf] [--css custom.css] [-o output_dir] [--outbox NAME] [--vault PATH] [--subject TEXT] |
Convert markdown documents to professionally styled PDFs using weasyprint.
/md2pdf path/to/document.md
/md2pdf doc1.md doc2.md doc3.md
/md2pdf doc1.md doc2.md --combined package.pdf
/md2pdf doc.md --css ~/my-brand.css -o ~/Desktop
/md2pdf doc1.md doc2.md --outbox erik-lindgren_bravo --subject "Sammanfattning"
```markmap fenced blocks into Mermaid mindmap blocks (heading levels + bullets become indentation)mmdc (high-res, scale 3x)markdown library), with pymdownx.tasklist enabled when available so - [ ] / - [x] become real checkboxesstyle.css in this skill directory)Note: Mermaid is rendered as PNG, not SVG, because Mermaid SVGs use foreignObject for text labels which weasyprint cannot render.
Author mindmaps using a fenced ```markmap block. The skill converts it to a Mermaid mindmap automatically before rendering:
```markmap
# Root
## Branch A
- Leaf A1
- Leaf A2
## Branch B
- Leaf B1
- Sub-leaf
```
Rules:
# heading is the root (depth 0). ## is depth 1, ### is depth 2, etc.- / *) under a heading inherit the heading's depth and add their own indent (each two spaces / tab = one extra level).mmdc must be installed for the diagram to render. Without mmdc the block falls back to a plain code listing.Pass depth=N as a fence attribute to prune nodes deeper than N. Depth 0 is the root, so depth=2 keeps the root + two levels of branches and drops everything deeper.
```markmap depth=2
# Root
## Branch A
- Leaf A1 (kept — depth 2)
- Drilldown (dropped — depth 3)
## Branch B
- Leaf B1 (kept)
```
Use a small depth (1-2) for an executive overview and omit the attribute (or use a higher value) for a detailed map.
Run the converter script:
python3 ~/.claude/skills/md2pdf/md2pdf.py <args>
| Arg | Description |
|---|---|
files | One or more .md files to convert |
-o, --output-dir | Output directory (default: current dir) |
--combined NAME.pdf | Merge all files into one PDF |
--css FILE | Custom CSS (default: built-in professional style) |
--outbox NAME | Package PDFs into <vault>/_outbox/YYMMDD-NAME/ with _manifest.md + email stub. NAME follows the contact convention (förnamn-efternamn_organisation). |
--vault PATH | Vault root for --outbox mode (default: walk up from cwd looking for _outbox/ or _contacts/, then $OBSIDIAN_VAULT). |
--subject TEXT | Pre-fill the email subject line in --outbox mode. |
Single file:
python3 ~/.claude/skills/md2pdf/md2pdf.py report.md -o ~/Desktop
Multiple files, individual PDFs:
python3 ~/.claude/skills/md2pdf/md2pdf.py summary.md strategy.md diagram.md -o ./export
Combined document:
python3 ~/.claude/skills/md2pdf/md2pdf.py summary.md strategy.md --combined full-report.pdf -o ~/Desktop
Custom styling:
python3 ~/.claude/skills/md2pdf/md2pdf.py doc.md --css ~/brand/style.css
Outbox mode (auto-package for sending):
python3 ~/.claude/skills/md2pdf/md2pdf.py nulaege.md strategi.md --outbox erik-lindgren_bravo --subject "Sammanfattning från mötet"
Outbox mode produces:
<vault>/_outbox/YYMMDD-erik-lindgren_bravo/
├── _manifest.md # status, kanal, kontakt, projekt, Innehåll-tabell
├── 260415-erik-lindgren_bravo-mejl.txt # ämne ifyllt, bilagor listade, body tom
├── nulaege.pdf
└── strategi.pdf
The manifest and email stub are skeletons. After generating, you MUST fill in:
mejl.txt): Write a complete email with context — what's attached and why, key decisions or outcomes, open questions, and what's expected from the recipient. Never leave the body as <!-- fyll i meddelandetext -->. IMPORTANT: The email file must be plain text only — no markdown syntax. Do not use ##, **, ---, backticks, or any other markdown formatting. Use UPPERCASE for section headings, plain dashes/numbers for lists, and spaces for alignment. The text is copied directly into a mail client where markdown renders as ugly raw syntax.After sending, flip **Status:** ej skickad to skickad in the manifest. Combining --outbox with --combined paket.pdf produces a single PDF inside the outbox folder instead of one per source file.
- [ ] / - [x] task lists as proper checkboxes (without it the checkboxes show up as literal [ ] text after the bullet)@mermaid-js/mermaid-cli) -- Mermaid diagram rendering, required for mindmap and mermaid blocks (optional only if neither block type is used)# Python deps
pip install weasyprint markdown pymdown-extensions
# Mermaid CLI (required for ```mermaid and ```markmap blocks)
npm install -g @mermaid-js/mermaid-cli
Verify:
mmdc --version # should print a version
weasyprint --version
If mmdc is missing, mermaid/markmap blocks will fall back to a plain code listing in the PDF (no diagram rendered) -- the build still succeeds.
Override the default style.css with --css. The CSS uses @page rules for print layout (A4, margins, page numbers). See style.css in this directory for the full default template.
This skill pairs well with:
/ops -- generate meeting summaries, then export as PDF/preparation -- create meeting prep docs, export for print/sharing/transcript -- process transcripts, deliver as PDFWorkflow: generate markdown with the source skill, then /md2pdf to export.
[HINT] Download the complete skill directory including SKILL.md and all related files