Weave markdown files into beautifully formatted PDFs and EPUBs
Project description
mdweaver
Weave markdown files into beautifully formatted PDFs and EPUBs.
mdweaver is a command-line tool that converts your Markdown documentation into professional-looking PDF and EPUB files. It handles syntax highlighting, recursive file discovery, common rendering issues, and sensible default exclusions automatically.
Features
- Multiple Formats: Generate PDF, EPUB, or both simultaneously.
- Recursive Processing: Convert a single file or an entire directory of documentation.
- Default Exclusions: Skips common “noise” directories by default:
.git,.venv/venv,node_modules,__pycache__,.pytest_cache,output
- Syntax Highlighting: Includes Pygments support (Monokai theme) for code blocks.
- Smart Preprocessing: Automatically fixes common Markdown issues like:
- Escaping generic type parameters (e.g.,
Result<T, E>). - Correcting list spacing for proper rendering.
- Escaping generic type parameters (e.g.,
- Customization:
- Add watermarks to PDFs (e.g.,
"DRAFT"). - Add branded page headers (e.g.,
"belderbos.dev · Python · Rust · AI"). - Override the default styles with a custom CSS file.
- Set custom document titles and author metadata.
- Exclude additional paths via glob patterns.
- Add watermarks to PDFs (e.g.,
- Clean Typography: Uses optimized CSS for print (A4) and e-reader layouts.
Prerequisites
For PDF generation, mdweaver relies on WeasyPrint, which requires system libraries (Pango, Cairo, etc.) to be installed. EPUB generation works without these dependencies.
macOS:
brew install pango
Linux (Debian/Ubuntu):
sudo apt install libpango-1.0-0 libpangoft2-1.0-0
See the WeasyPrint documentation for other platforms: https://doc.courtbouillon.org/weasyprint/stable/first_steps.html
Installation
This project is managed with uv.
# Install dependencies
uv sync
Or using pip:
pip install mdweaver
macOS (Homebrew / Apple Silicon) – WeasyPrint dylib lookup
If import weasyprint fails with a libgobject-2.0-0 / gobject missing error on macOS, install the native deps with Homebrew and expose Homebrew’s lib directory to the dynamic loader:
brew install glib pango cairo gdk-pixbuf libffi
export DYLD_FALLBACK_LIBRARY_PATH="$(brew --prefix)/lib:${DYLD_FALLBACK_LIBRARY_PATH}"
uv run python -c "import weasyprint; print(weasyprint.__version__)"
You can add the export DYLD_FALLBACK_LIBRARY_PATH=... line to your shell config (typically ~/.zshrc on macOS; or ~/.bashrc) to make it persistent across sessions.
CLI Usage
The basic syntax is mdweaver <input> [options].
Examples
Convert a single file:
mdweaver document.md
Convert a directory (recursively), with defaults excluded:
mdweaver ./docs
Exclude additional paths (repeatable):
mdweaver ./docs --exclude "**/dist/**" --exclude "**/build/**"
Generate EPUB with metadata:
mdweaver ./content -f epub -t "My Book" -a "Author Name"
Generate PDF with a watermark:
mdweaver ./content -f pdf -w "DRAFT" -o ./build
Generate PDF with a branded page header:
mdweaver document.md --header "belderbos.dev · Python · Rust · AI"
Generate PDF with custom CSS:
mdweaver document.md --css my-theme.css
Generate both formats:
mdweaver ./content -f both
Options
input: Markdown file or directory to process.-o, --output: Output directory (default:./output).-f, --format: Output format:pdf,epub, orboth(default:pdf).-t, --title: Document title (default: derived from filename/path).-a, --author: Author name (for EPUB metadata).-w, --watermark: Watermark text to display diagonally across PDF pages.--css: Path to a custom CSS file to use instead of the default styles.--header: Text to display in the page header on every PDF page.--exclude: Glob pattern to exclude (repeatable), e.g.--exclude "**/dist/**".
Default excludes
When scanning directories recursively, mdweaver excludes these patterns by default:
**/.git/****/.venv/****/venv/****/node_modules/****/__pycache__/****/.pytest_cache/****/output/**
You can add more exclusions using --exclude.
Project Structure
mdweaver/
├── src/mdweaver/
│ ├── __init__.py
│ └── generate_pdf.py # Core logic
├── tests/
│ ├── conftest.py
│ └── test_mdweaver.py
├── pyproject.toml # Dependencies and metadata
└── README.md
Development
Running Tests
uv run pytest
Note: You might see a skipped test for PDF generation if the system dependencies (WeasyPrint libs) are not installed.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mdweaver-0.3.0.tar.gz.
File metadata
- Download URL: mdweaver-0.3.0.tar.gz
- Upload date:
- Size: 7.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0a51920a8b18840c12d2b0376427415964c25ecdc70889985b90da089903ae60
|
|
| MD5 |
45f6b4c3be9a9703e62535f5664e6073
|
|
| BLAKE2b-256 |
d41100ee32d109d6d1bd36c445355be2ef6d22d34611920adced15b779fd8c51
|
Provenance
The following attestation bundles were made for mdweaver-0.3.0.tar.gz:
Publisher:
release.yml on bbelderbos/mdweaver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mdweaver-0.3.0.tar.gz -
Subject digest:
0a51920a8b18840c12d2b0376427415964c25ecdc70889985b90da089903ae60 - Sigstore transparency entry: 1965391801
- Sigstore integration time:
-
Permalink:
bbelderbos/mdweaver@227826f9e2f578087b3a3e7f2fe55649f77f9ea5 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/bbelderbos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@227826f9e2f578087b3a3e7f2fe55649f77f9ea5 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mdweaver-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mdweaver-0.3.0-py3-none-any.whl
- Upload date:
- Size: 9.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
50a9fe3198c6b94bbb34639aef8250ab7b7bf6aa69b958e585bce894dc820196
|
|
| MD5 |
a6ed8b1526d4a581c071606923092152
|
|
| BLAKE2b-256 |
1acf274716f1fe458443761db6f90249aa8a41a27fce2b46ca64f5241508b44f
|
Provenance
The following attestation bundles were made for mdweaver-0.3.0-py3-none-any.whl:
Publisher:
release.yml on bbelderbos/mdweaver
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mdweaver-0.3.0-py3-none-any.whl -
Subject digest:
50a9fe3198c6b94bbb34639aef8250ab7b7bf6aa69b958e585bce894dc820196 - Sigstore transparency entry: 1965391974
- Sigstore integration time:
-
Permalink:
bbelderbos/mdweaver@227826f9e2f578087b3a3e7f2fe55649f77f9ea5 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/bbelderbos
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@227826f9e2f578087b3a3e7f2fe55649f77f9ea5 -
Trigger Event:
push
-
Statement type: