Skip to main content

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

Project description

md-to-pdf-cli

Convert local Markdown files to PDF using headless Chromium

Install

Requires Python 3.12+.

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

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

Chromium is not a pip dependency — it's a browser binary Playwright downloads once into a shared cache. If it's missing, md2pdf tells you the exact command to run.

Quick start

md2pdf report.md                 # writes report.pdf next to the input
md2pdf report.md -o out/doc.pdf  # choose the output path

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

Usage

md2pdf <input.md> [OPTIONS]
Option What it does
-o, --output PATH Output PDF path (default: same name as input).
-c, --config PATH Use a specific md2pdf.toml (default: auto-load from current dir).
--page-size NAME A4, Letter, Legal, …
--margin SIZE Margin on all sides, e.g. 2cm.
--landscape / --portrait Page orientation.
--css FILE Extra CSS file, applied after the theme (repeatable).
--code-style NAME Pygments highlight style, e.g. monokai.
--font STACK CSS font-family stack.
--toc / --no-toc Generate a table of contents page.
--math / --no-math LaTeX math rendering.
--mermaid / --no-mermaid mermaid diagram rendering.
--embed-images / --no-embed-images Inline local images as data URIs.
--header HTML, --footer HTML Page header/footer (see Headers & page numbers).

Run md2pdf --help for the full list.

What it renders, and how to use it

Write standard Markdown — these capabilities work out of the box.

Code blocks

Fenced code blocks are highlighted server-side with Pygments. Just tag the language:

```python
def greet(name): return f"Hello, {name}"
```

Pick the colour scheme with --code-style monokai (any Pygments style name).

Math

Inline $...$ and block $$...$$ LaTeX are typeset with KaTeX:

Euler's identity is $e^{i\pi} + 1 = 0$.

$$
\int_{-\infty}^{\infty} e^{-x^2}\,dx = \sqrt{\pi}
$$

Diagrams

A ```mermaid fence is rendered to a vector diagram:

```mermaid
flowchart LR
    A[Markdown] --> B[md2pdf] --> C[(PDF)]
```

Tables

GFM tables are supported. Long tables that span pages are not sliced mid-row, and the header row repeats at the top of each page.

Images

Relative image paths are resolved against the Markdown file's location, so ![](../figures/plot.png) works regardless of where you run the command. Remote http(s) images are fetched at render time. Use --embed-images to inline local images into a fully self-contained PDF.

Chinese / CJK

CJK text renders correctly (UTF-8 with BOM handling and a CJK-first font stack). On Linux, install CJK fonts first — see Troubleshooting.

Table of contents & bookmarks

--toc adds a contents page built from your headings. The PDF also gets an outline (bookmarks) from the heading structure automatically.

Headers, footers & page numbers

Enabled via the config file (below). Templates may use Chromium's placeholders: pageNumber, totalPages, title, date, url. A centered "page / total" footer is on by default.

Configuration

Scaffold a config and a starter theme:

md2pdf init        # writes md2pdf.toml and theme.css

md2pdf auto-loads md2pdf.toml from the current directory. Precedence: CLI flags > config file > defaults.

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

[theme]
css = ["theme.css"]              # extra CSS, applied after the default theme
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

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

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

Custom styling: anything in your theme.css (or --css) overrides the built-in theme, including the --md2pdf-* CSS variables it defines.

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 into the HTML, so conversion is offline and reproducible. md2pdf waits for math and diagrams to finish rendering before printing, so nothing comes out half-drawn.

Troubleshooting

  • Chromium is not installed for Playwright — run playwright install chromium (or uv tool run --from md-to-pdf-cli playwright install chromium for a uv-tool install).
  • Chinese/CJK text shows as boxes (tofu) on Linux — install CJK fonts, e.g. sudo apt install fonts-noto-cjk on Debian/Ubuntu. Windows and macOS already ship with CJK fonts.
  • Chromium fails to launch on a headless Linux server — install its system libraries: playwright install-deps chromium (needs root).

Development

uv sync
uv run playwright install chromium
uv run pytest                 # full suite (the end-to-end test launches Chromium)
uv run pytest -m "not slow"   # skip the browser-based test
uv run ruff check . && uv run ruff format --check .

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.1.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.1-py3-none-any.whl (1.1 MB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: md_to_pdf_cli-0.1.1.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.1.tar.gz
Algorithm Hash digest
SHA256 7e14e042f50060a538474a0837ed2f112ec0690e668280353e4f3b84dff94759
MD5 6570214955ecd11a57161146eaa65862
BLAKE2b-256 0521496879f81e99959d9d4cb3a72422b1058f1866109721d70753fc7535e775

See more details on using hashes here.

File details

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

File metadata

  • Download URL: md_to_pdf_cli-0.1.1-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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 5ed910b8ee05ec0ae44812d716d6ecca862468020b8de1a44d98468c0f26bb1b
MD5 c347f2f63f6bc5b757c04812d778ce7e
BLAKE2b-256 9d5e14e3c2200eee0cecf9639bf25fa635fc50482e3a0b3d505194d049fe3e15

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