Convert Markdown content into beautifully formatted PDF documents using md2pdf (WeasyPrint engine) with a bundled professional CSS stylesheet.
Before first use, install the required dependencies:
# macOS system dependencies for WeasyPrint
brew install cairo pango gdk-pixbuf libffi
# Python package
pip install md2pdf
On Ubuntu/Debian:
sudo apt install libpango-1.0-0 libpangocairo-1.0-0 libgdk-pixbuf2.0-0 libffi-dev shared-mime-info
pip install md2pdf
Verify installation:
python -c "from md2pdf.core import md2pdf; print('md2pdf ready')"
The simplest way — use the bundled conversion script:
python @scripts/convert.py input.md output.pdf
The script automatically uses the bundled CSS stylesheet at @assets/markdown.css for professional formatting. If no output path is given, it defaults to the input filename with .pdf extension.
For more control, call md2pdf directly in Python:
from pathlib import Path
from md2pdf.core import md2pdf
# From a Markdown file
md2pdf(
pdf=Path("output.pdf"),
md=Path("input.md"),
css=Path("@assets/markdown.css"),
base_url=Path("."), # resolves relative image paths
)
# From a Markdown string
md2pdf(
pdf=Path("output.pdf"),
raw="# Hello\n\nThis is **bold** text.",
css=Path("@assets/markdown.css"),
)
The @assets/markdown.css provides:
Pass your own CSS file to override or extend the default styles:
python @scripts/convert.py input.md output.pdf --css my-styles.css
Or via Python API:
md2pdf(pdf=Path("output.pdf"), md=Path("input.md"), css=Path("my-styles.css"))
Change page size to Letter:
@page { size: letter; }
Add a header with document title:
@page {
@top-center {
content: "My Document";
font-size: 8pt;
color: #999;
}
}
Add "Page X of Y" footer:
@page {
@bottom-center {
content: counter(page) " / " counter(pages);
font-size: 9pt;
color: #888;
}
}
Change body font:
body { font-family: "Merriweather", Georgia, serif; }
Disable URL display in print:
a[href^="http"]:after { content: none; }
Use --title to inject a title heading when the Markdown content doesn't start with one:
python @scripts/convert.py report.md --title "Q4 Engineering Report"
Images with relative paths require base_url to resolve correctly. The conversion script sets this automatically to the Markdown file's parent directory. When using the Python API directly:
md2pdf(
pdf=Path("output.pdf"),
md=Path("docs/report.md"),
css=Path("@assets/markdown.css"),
base_url=Path("docs/"), # images in docs/ will resolve correctly
)
The conversion script enables these extensions by default:
tables — GFM table syntaxpymdownx.superfences — Nested code blocks with syntax highlightingpymdownx.betterem — Improved emphasis handlingpymdownx.magiclink — Auto-link URLs and issue referencesfootnotes — [^1] style footnotessmarty — Smart quotes, dashes, ellipses| Problem | Solution | |
|---|---|---|
| --------- | ---------- | |
ImportError: No module named 'md2pdf' | Run pip install md2pdf | |
OSError: cannot load library 'pango' | Install system deps: brew install cairo pango gdk-pixbuf libffi (macOS) | |
| Chinese characters show as squares | Ensure Chinese fonts are installed: brew install font-noto-serif-cjk font-noto-sans-cjk (or install via system font manager) | |
| Images not appearing | Set base_url to the directory containing the images | |
| PDF is blank | Check that the Markdown file has content and is UTF-8 encoded | |
SyntaxError: invalid syntax on `str \ | None` | Requires Python 3.10+. Use python3.10 or later |
| File | Purpose |
|---|---|
| ------ | --------- |
@assets/markdown.css | Professional PDF stylesheet (A4, Chinese fonts, syntax highlighting, page layout) |
@scripts/convert.py | CLI converter script with bundled CSS, title injection, and error handling |
共 1 个版本