Markdown to PDF Converter
Convert Markdown documents to professionally styled PDFs using pandoc + weasyprint with customizable CSS templates.
Input
The user provides a Markdown file path (or multiple paths / glob): $ARGUMENTS
If no path is provided, ask the user which .md file to convert.
Dependencies
- pandoc —
brew install pandoc - weasyprint —
pip3 install --user weasyprint - CSS templates — bundled in
${CLAUDE_SKILL_DIR}/templates/
If either tool is not found, print install instructions.
Arguments
Parse $ARGUMENTS for:
- Input file(s) — one or more
.mdfile paths, or a glob pattern like*.md(required) --outputor-o— custom output path (optional, defaults to~/Desktop/<filename>.pdf; single file only)--titleor-t— document title for HTML metadata (optional, defaults to filename)--template— template name (optional, defaults toreport)
Templates
Available templates (CSS files in ${CLAUDE_SKILL_DIR}/templates/):
| Template | Description |
|---|---|
report | Professional report with dark table headers, zebra striping, page numbers (default) |
minimal | Clean, lightweight — GitHub-style tables, no border accents |
branded-example | Branded example with "visiAI — Confidential" footer |
Users can also pass a path to any .css file as the template value.
Template resolution order:
- If value ends in
.cssand file exists → use directly comms/templates/<name>.css(project-local override)${CLAUDE_SKILL_DIR}/templates/<name>.css(bundled)
Conversion Steps
Step 1: Locate files and parse arguments
Verify input file(s) exist. If a file is not found, use Glob to search for likely matches.
Step 2: Find CSS template
SKILL_DIR="${CLAUDE_SKILL_DIR}"
# Resolve template
find_css() {
local name="$1"
# Direct .css path
if [[ "$name" == *.css ]] && [[ -f "$name" ]]; then echo "$name"; return; fi
# Project-local
if [[ -f "comms/templates/${name}.css" ]]; then echo "comms/templates/${name}.css"; return; fi
# Skill-bundled
if [[ -f "${SKILL_DIR}/templates/${name}.css" ]]; then echo "${SKILL_DIR}/templates/${name}.css"; return; fi
}
CSS=$(find_css "${TEMPLATE:-report}")
Step 3: Convert MD to HTML
pandoc "<input.md>" \
-o "/tmp/md2pdf_temp.html" \
--standalone \
--metadata "title=<title>" \
--css "<css-path>" \
--embed-resources
Step 4: Convert HTML to PDF
weasyprint \
"/tmp/md2pdf_temp.html" \
"<output.pdf>" \
2>/dev/null
Step 5: Cleanup and report
rm -f /tmp/md2pdf_temp.html
Report:
- Output file path
- File size
- Remind user to open and verify formatting
Batch Mode
If the user provides multiple files or a glob pattern (e.g., *.md):
- Expand the glob to a list of files
- Convert each file individually (output to
~/Desktop/<filename>.pdf) - Report results in a summary table:
Status File Size
------ -------------------------------------------------- ----
OK ~/Desktop/report1.pdf 245K
OK ~/Desktop/report2.pdf 180K
FAIL broken.md conversion error
Alternatively, use the bundled shell script directly:
bash "${CLAUDE_SKILL_DIR}/scripts/md2pdf.sh" --template report *.md
Shell Script
A standalone scripts/md2pdf.sh is included for use outside Claude Code:
# Single file
bash ~/.claude/skills/pdf/scripts/md2pdf.sh report.md
# With template
bash ~/.claude/skills/pdf/scripts/md2pdf.sh --template minimal report.md
# Batch
bash ~/.claude/skills/pdf/scripts/md2pdf.sh --template report *.md
Troubleshooting
- weasyprint not found: Run
pip3 install --user weasyprint(on macOS with managed Python, add--break-system-packages) - pandoc not found: Run
brew install pandoc - Chinese characters garbled: Ensure CSS has CJK font fallback (
PingFang SC,Microsoft YaHei) - Tables overflowing: CSS should have
table { width: 100%; font-size: 10pt; } - Template not found: Check
ls ~/.claude/skills/pdf/templates/for available templates