Skip to content
nanadotamPublic

About

Convert Markdown files to beautiful PDFs — by Nana Amoako.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Latest commit

 

History

12 Commits

Folders and files

Repository files navigation

mdpdf-cli

Convert Markdown files to beautiful PDFs — locally, fast, no internet required.

**By Nana Amoako **


What it does

mdpdf turns your .md files into polished PDFs using headless Chrome — the same rendering engine that powers Notion, Linear, and the web. What you see in your Markdown preview is what you get in the PDF.

Four built-in themes, custom CSS support, watch mode, batch conversion, Mermaid/PlantUML diagram rendering, and a hard guard that rejects anything that isn't a Markdown file before conversion even starts.


Features

  • Four built-in themes — Apple, Notion, GitHub, Minimal (see Themes)
  • Custom CSS — bring your own stylesheet and fully override the look (see Custom CSS)
  • Mermaid & PlantUML diagrams — fenced code blocks render to inline SVG automatically (see Diagrams)
  • Live progress bar — read → render → generate → save, with a percentage at every stage (see Progress)
  • Zoom / print scale — --zoom 85 / --zoom 125, same idea as Notion's PDF export scale (see Zoom / print scale)
  • Watch mode — -w auto-converts on every save
  • Batch conversion — convert multiple .md files in one command
  • HTML export — --html outputs HTML instead of PDF, handy for previewing CSS changes
  • Configurable paper size & margins — -p A4|Letter|Legal, -m <mm>
  • Code syntax highlighting — any highlight.js theme via --highlight (see Highlight styles)
  • Flexible output location — same-directory default, or redirect with -o (see Output location)
  • File guard — only .md / .markdown are accepted, rejected before any conversion work starts (see File guard)
  • Auto-open — opens the finished PDF in Preview on macOS (disable with --no-open)

Installation

Requires Node.js ≥ 18

# Clone and install
git clone https://github.com/nanadotam/mdpdf-cli.git
cd mdpdf-cli
npm install
npm link          # makes `mdpdf` available globally in your terminal

Finder Quick Action (macOS)

Skip the terminal entirely — right-click any .md/.markdown file(s) in Finder and convert straight to PDF.

npm link                          # if you haven't already
./scripts/install-quick-action.sh

Then: right-click a Markdown file → Quick Actions → Convert to PDF. The PDF is saved next to the source file and opens in Preview automatically; a notification confirms success or failure. Non-Markdown files in a multi-select are silently skipped.


Usage

mdpdf <file.md> [more files...] [options]

Options

Flag Description Default
-o, --output <path> Output file or directory Same dir as source
-t, --theme <name> Built-in theme (see below) apple
-s, --style <file> Custom CSS file (overrides --theme) —
-p, --paper <size> Paper size: A4 · Letter · Legal A4
-m, --margins <mm> Margins in mm — one value or top,right,bottom,left 20
-z, --zoom <percent> Print scale, e.g. 85, 90, 125 — same idea as Notion's PDF export scale 100
-w, --watch Watch file for changes and auto-convert off
--no-open Don't open the PDF in Preview after conversion auto-opens
--html Output an HTML file instead of a PDF off
--highlight <style> Code syntax theme (github, atom-one-dark, monokai…) github
-V, --version Show version
-h, --help Show help

Themes

Name Feel
apple San Francisco (SF Pro) · Apple design language · Dark code blocks
notion Inter · Clean Notion-like spacing · Warm neutrals
github GitHub Markdown · Developer-friendly · Familiar
minimal Georgia serif body · Wide margins · Client-ready
mdpdf report.md -t notion
mdpdf report.md -t github
mdpdf report.md -t minimal

Examples

# Convert with default Apple theme — opens PDF automatically
mdpdf report.md

# Notion look, Letter paper
mdpdf report.md -t notion -p Letter

# Save to a specific directory
mdpdf report.md -o ./exports/

# Custom CSS — bring your own style
mdpdf report.md -s ./my-brand.css

# Watch mode — auto-converts on every save
mdpdf report.md -w

# Batch conversion — multiple files at once
mdpdf file1.md file2.md file3.md -o ./out/

# Dark code blocks with atom-one-dark highlight
mdpdf report.md --highlight atom-one-dark

# Tight margins for a dense layout
mdpdf report.md -m 12

# Top/bottom 20mm, left/right 30mm
mdpdf report.md -m 20,30

# Output HTML instead (useful for debugging your CSS)
mdpdf report.md --html

# Convert without auto-opening Preview
mdpdf report.md --no-open

File guard

mdpdf only accepts .md and .markdown files. Anything else is rejected immediately — before any conversion starts.

$ mdpdf notes.txt
  ✗ Not a Markdown file: notes.txt [.txt]
  → mdpdf only accepts .md or .markdown files.

$ mdpdf invoice.pdf
  ✗ Not a Markdown file: invoice.pdf [.pdf]
  → mdpdf only accepts .md or .markdown files.

Custom CSS

Pass any CSS file with -s to fully control the output:

mdpdf report.md -s ./brand.css

Use --html first to preview your styles in a browser before committing to PDF:

mdpdf report.md -s ./brand.css --html --no-open
open report.html

Local images and fonts in custom CSS

mdpdf renders through headless Chrome (via md-to-pdf/Puppeteer), and that sandboxed instance cannot load file:// resources — neither background-image: url("file:///…") nor @font-face { src: url("file:///…") } will render, and <img src="file:///…"> in the Markdown itself shows a broken-image icon. This fails silently: no error, the asset just doesn't appear in the output.

The fix is to inline the asset as a base64 data: URI instead:

# image
python3 -c "
import base64
with open('pattern.png','rb') as f:
    print(base64.b64encode(f.read()).decode())
" > pattern.b64

# font
python3 -c "
import base64
with open('MyFont.ttf','rb') as f:
    print(base64.b64encode(f.read()).decode())
" > font.b64
@font-face {
  font-family: "My Font";
  src: url("data:font/ttf;base64,AAEA...") format("truetype");
}

.header {
  background-image: url("data:image/png;base64,iVBORw0...");
}

This bloats the CSS file (a 250 KB PNG becomes ~330 KB of base64), but it's the only reliable way to ship local images/fonts with a custom -s theme — worth it for something like a subtle header/background pattern. Example worked in production: a navy header band with a low-opacity pattern texture, built with filter: invert(1) brightness(1.7); opacity: 0.16; mix-blend-mode: screen; on a ::before pseudo-element so the pattern reads as a faint texture rather than a loud watermark, plus a background-size: cover; background-repeat: no-repeat; variant to use the full source image unstitched instead of a repeating tile.


Diagrams

Fenced code blocks written in Mermaid or PlantUML are rendered to inline SVG before the PDF is generated:

```mermaid
flowchart TD
  A[Request] --> B{Valid?}
  B -->|Yes| C[Process]
  B -->|No| D[Reject]
```

```plantuml
@startuml
Alice -> Bob: hello
@enduml
```
  • Mermaid renders locally via headless Chrome — no internet required.
  • PlantUML is rendered remotely through Kroki — requires internet access. puml is accepted as an alias for plantuml.

If a diagram fails to render (bad syntax, no network for PlantUML), mdpdf prints a warning and leaves the rest of the document intact.


Progress

Every conversion shows a live progress bar through the read → diagram-render → generate → save pipeline:

  █████████████████░░░░░░░░░  62%  Generating PDF

In non-interactive shells (CI, piped output) it falls back to plain [N%] message lines instead of redrawing in place.


Zoom / print scale

--zoom maps directly to the PDF's print scale — the same control Notion's "Export to PDF" dialog exposes. Values below 100 shrink content (more page per sheet, smaller text); values above 100 enlarge it. Accepts 10–200:

mdpdf report.md --zoom 85    # or -z 85 — a common preference for dense docs
mdpdf report.md --zoom 125   # zoom in for readability

Output location

By default, the PDF lands in the same directory as your Markdown file with the same name:

docs/VENUE_OWNER_ANALYSIS.md  →  docs/VENUE_OWNER_ANALYSIS.pdf

Use -o to redirect:

mdpdf docs/report.md -o ./exports/          # → exports/report.pdf
mdpdf docs/report.md -o ./exports/final.pdf # → exports/final.pdf

Highlight styles

Pass any highlight.js theme name to --highlight:

github (default)   atom-one-dark   monokai   dracula
vs2015             night-owl       nord      gruvbox-dark

License

MIT © Nana Amoako

About

Convert Markdown files to beautiful PDFs — by Nana Amoako.

Resources

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages