A small Python tool that turns Markdown files into PDFs optimized for the Supernote A5X e‑ink tablet.
- Python 69.4%
- CSS 22.8%
- Lua 4.6%
- JavaScript 3.2%
| examples | ||
| md2pdf | ||
| tests | ||
| .gitignore | ||
| .pre-commit-config.yaml | ||
| LICENSE | ||
| math2svg.lua | ||
| md2pdf.py | ||
| package-lock.json | ||
| package.json | ||
| pyproject.toml | ||
| README.md | ||
| supernote-high-contrast.css | ||
| supernote-reading.css | ||
| supernote.css | ||
| tex2svg.mjs | ||
| uv.lock | ||
Markdown → PDF for Supernote A5X
A small Python tool that turns Markdown into PDFs optimized for the Supernote A5X e‑ink tablet.
Features
- Supernote-friendly layout: A5 page size by default, dense but readable typography
- Math support: LaTeX math (
$...$,$$...$$) rendered to SVG using MathJax (via Pandoc Lua filter) - Clean grayscale theme: E‑ink optimized CSS (
supernote.css) - Navigation: PDF outline/bookmarks from headings, optional visible TOC
- Batch mode: Convert a whole directory of
.mdfiles in one go
Requirements
- Pandoc
- Python 3.10+ with
uv - Node.js (used only to run
tex2svg.mjswithmathjax-fullfor TeX → SVG)
Install
git clone <this-repo-url>
cd md2pdf
# Create virtual environment and install Python deps
uv venv
source .venv/bin/activate # Linux/macOS
uv sync # installs md2pdf and runtime deps
# Install MathJax-full locally for the SVG renderer
npm install mathjax-full
Basic usage
# Single file → PDF (output defaults to input.pdf)
uv run md2pdf input.md
# Explicit output file
uv run md2pdf input.md output.pdf
# Batch convert all .md files in a directory
uv run md2pdf examples/
uv run md2pdf examples/ output/
Key options:
--page-size {A5,A4}– paper size (default: A5)--css PATH– custom CSS file (default:supernote.cssin project root)--profile {dense,reading}– layout profile: dense (default) or slightly larger reading layout--high-contrast– use a higher-contrast grayscale palette for e‑ink--toc/--toc-depth N– visible table of contents on first page--hr-pagebreak– treat---as a page break instead of a horizontal rule--h2-pagebreak– insert a page break before##headings so they start at the top of a page--force– overwrite existing PDFs instead of auto‑suffixing(1),(2), …
Math
- Inline math:
$i$ - Display math:
$$\int_a^b f(x)\,dx = F(b) - F(a)$$
Under the hood:
- Pandoc parses Markdown + LaTeX math.
- A Lua filter (
math2svg.lua) pipes each formula throughnode tex2svg.mjs(MathJax-full). - The resulting SVG is inlined into the HTML that WeasyPrint turns into PDF.
This gives fully static, high‑quality math rendering with no LaTeX installation and no JavaScript at PDF time.
Customizing the look
- Edit
supernote.cssto tweak:- Font families / sizes
- Margins and spacing
- Code block and table styles
- TOC styling
- Use
supernote-reading.cssas a reference for a slightly more relaxed reading layout. - Use
--page-size A4if you want standard A4 instead of A5.
Development workflow
-
Create and activate the virtual environment:
uv venv source .venv/bin/activate -
Sync dependencies (including dev tools):
uv sync --extra dev -
Run formatting and linting:
uv run ruff check . uv run ruff format . -
Run tests:
uv run pytest
Project layout
md2pdf/
md2pdf.py # Main CLI script
supernote.css # E‑ink optimized stylesheet
math2svg.lua # Pandoc Lua filter (TeX → SVG via MathJax)
tex2svg.mjs # Node helper using mathjax-full (MathJax, ESM)
pyproject.toml # Python project config
examples/ # Sample Markdown files
output/ # Generated PDFs (gitignored)
Troubleshooting
- Math missing or broken
- Check Pandoc:
pandoc --version - Check Node:
node --version - Check MathJax:
ls node_modules/mathjax-full - Run with
--keep-htmland open the HTML to confirm you see inline<svg>for equations.
- Check Pandoc:
- PDF generation fails
- Ensure
weasyprintis installed in the venv (viauv pip install -e .oruv pip sync) - Read the error output printed by
md2pdf.py
- Ensure
License
MIT, see LICENSE.