Skip to main content

Convert local Markdown files to PDF via headless Chromium (CJK-friendly, mermaid + math + code highlighting).

Project description

md2pdf

Convert local Markdown files to PDF via headless Chromium — the same engine your editor preview uses, so what you see is what you get.

Built to fix the things other converters get wrong:

  • Chinese / CJK text renders correctly (UTF-8 + BOM handling, CJK font stack) — no mojibake.
  • Tables don't get sliced across pages; the header row repeats on each page.
  • Images don't break — relative paths resolve against the source file, or can be embedded as data URIs.
  • mermaid diagrams, LaTeX math (KaTeX), and syntax-highlighted code (Pygments) all render.
  • Full control over styling via CSS themes and a TOML config file, plus page headers/footers and page numbers.

Install

Requires Python 3.12+. The package is published on PyPI as markdown-to-pdf; the command and import package are both md2pdf.

As a user

# with uv (installs the `md2pdf` command globally, isolated)
uv tool install markdown-to-pdf
uv tool run --from markdown-to-pdf playwright install chromium   # one-time browser download

# or with pip
pip install markdown-to-pdf
playwright install chromium                                      # one-time browser download

Why the extra browser step? md2pdf renders through headless Chromium (via Playwright). Chromium is not a pip dependency — it's a ~120 MB browser binary downloaded once into a shared cache (~/.cache/ms-playwright). If you skip it, md2pdf prints the exact command to run.

From source (development)

uv sync
uv run playwright install chromium

Usage

# Simplest: PDF written next to the input
uv run md2pdf report.md

# Choose output path
uv run md2pdf report.md -o out/report.pdf

# Common options
uv run md2pdf report.md --page-size Letter --margin 1.5cm --code-style monokai --toc
uv run md2pdf report.md --css custom.css --no-mermaid

md2pdf <file> is shorthand for md2pdf convert <file>.

Config file

Scaffold a starter config and theme:

uv run md2pdf init

This writes md2pdf.toml and theme.css. md2pdf auto-loads md2pdf.toml from the current directory (override with -c path/to/config.toml). CLI flags override the config file, which overrides built-in defaults.

[output]
page_size = "A4"
margin = { top = "2cm", bottom = "2cm", left = "1.8cm", right = "1.8cm" }

[theme]
css = ["theme.css"]
code_style = "default"           # any Pygments style
# font_family = '"Noto Sans CJK TC", "Microsoft JhengHei", sans-serif'

[features]
math = true
mermaid = true
toc = false
embed_images = false             # inline images for a self-contained PDF

[footer]
enabled = true
template = '<span class="pageNumber"></span> / <span class="totalPages"></span>'

[header]
enabled = false
template = '<span class="title"></span>'

Header/footer templates may use these Chromium placeholders: pageNumber, totalPages, title, date, url.

How it works

.md ──▶ markdown-it-py (+ Pygments, dollarmath) ──▶ self-contained HTML
     ──▶ Chromium (KaTeX + mermaid render, fonts load) ──▶ page.pdf() ──▶ .pdf

All assets (theme CSS, Pygments CSS, KaTeX with fonts, mermaid) are inlined, so conversion works fully offline and reproducibly.

Development

uv run pytest                 # full suite (the end-to-end test launches Chromium)
uv run pytest -m "not slow"   # skip the browser-based end-to-end test

Troubleshooting

  • Chromium is not installed for Playwright — run playwright install chromium (or uv tool run --from markdown-to-pdf playwright install chromium for a uv-tool install).
  • Images show as broken — md2pdf resolves relative image paths against the Markdown file's directory; make sure the paths are correct relative to the .md file. Remote http(s) images are fetched at render time.

License

MIT

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

md_to_pdf_cli-0.1.0.tar.gz (1.1 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

md_to_pdf_cli-0.1.0-py3-none-any.whl (1.1 MB view details)

Uploaded Python 3

File details

Details for the file md_to_pdf_cli-0.1.0.tar.gz.

File metadata

  • Download URL: md_to_pdf_cli-0.1.0.tar.gz
  • Upload date:
  • Size: 1.1 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for md_to_pdf_cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 72e8e36c92ebe55ce4c73d5bb2a91b74a36008f556b61e19a7474a258f04c35d
MD5 9e2f6406e96180be700a80ab4cad907d
BLAKE2b-256 cdb35e3a6069694e146adf3186c093b96e6e395b442891683e80376c6bc2f970

See more details on using hashes here.

File details

Details for the file md_to_pdf_cli-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: md_to_pdf_cli-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 1.1 MB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.11 {"installer":{"name":"uv","version":"0.10.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for md_to_pdf_cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5e27fa94ce57982f2dd4c9723443838f036a90ed85d80d18a315cc73d8082c0a
MD5 73dde6c5498f05f072f465cb4d5e9257
BLAKE2b-256 65a8c3b3f57c762997fa962e1900ff392e9fab7b6caf19138cf5ee64306a32da

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page