BeautifulMD
Pixel-perfect Markdown to PDF — with full Mermaid diagram support and smart pagination.
Other Markdown-to-PDF tools parse your document as flat text, breaking Mermaid diagrams, custom styles, and anything that needs a real browser to render. BeautifulMD takes a different approach: it renders your Markdown in a headless Chromium instance — the same engine behind Chrome — and prints it to PDF exactly as it looks.
BeautifulMD started as a fork of SnapMD and focuses on print-quality pagination for long documents with many Mermaid diagrams. The original project is MIT licensed; see LICENSE.
BeautifulMD vs. SnapMD
BeautifulMD keeps SnapMD's core architecture — markdown-it, Mermaid, and headless Chromium printing — and concentrates on where the original output broke down in long, diagram-heavy documents.
| Area |
SnapMD |
BeautifulMD |
| Diagram width |
SVG keeps its natural width and can overflow the page |
Explicitly fitted to the printable width |
| Tall diagrams |
Can be clipped at the page edge or cut at an arbitrary point |
Shrunk to one page, or split into balanced viewBox slices |
| Page breaks |
A diagram that does not fit jumps to the next page, leaving a gap |
Capacity-aware layout starts a slice on the current page when possible |
| Final slice |
A tall diagram can end with a tiny, nearly empty page |
The final boundary is the end of the diagram; slices are balanced |
| Headings |
A heading can be stranded before a diagram |
An immediately preceding heading moves with the diagram |
| Tables |
Browser-default print pagination |
Compact print tables, repeated headers, safer row breaks |
| Diagnostics |
No layout report |
Per-diagram scale/slice information in the BeautifulMD output channel |
| Packaging |
puppeteer-core external |
Bundled into a self-contained VSIX |
What is intentionally unchanged:
- the same headless Chromium printing approach;
- the same live preview and paper-format settings;
- the same MIT license and the original copyright notice.
The main new component is the print-layout pass in src/pdf/printLayout.ts.
Why diagrams were clipped (and what changed)
Chromium prints a page at a time, but a Mermaid SVG is a single, unbreakable element. If a diagram is wider than the printable area it gets cut off on the right; if it is taller than the page it gets cut off at the bottom; and if it does not fit in the space left on the current page, Chromium moves the whole diagram to the next page and leaves a large blank area behind.
BeautifulMD now runs a print-layout pass before printing:
- every diagram is scaled to the printable width;
- a diagram that is too tall is scaled down to a single page when it stays readable;
- very tall diagrams are split across pages using SVG
viewBox slices, preferring gaps between nodes and adding a small overlap when it does not cost an extra page;
- a heading immediately before a diagram moves together with the diagram;
- a diagram that would leave a large hole on the current page is split to fill that space instead.

The example used for the screenshot is in examples/pagination-demo.md; the generated result is examples/pagination-demo.pdf.
Features
Export to PDF
Convert any Markdown file to a clean, print-ready PDF in one click. Headings, code blocks, tables, images, links — everything renders faithfully.
- Open any
.md file → Cmd+Shift+P → BeautifulMD: Export to PDF
- Or click the PDF icon in the editor title bar
- Or right-click in the editor →
BeautifulMD: Export to PDF
- Wide diagrams are fitted to the printable width instead of being clipped.
- Tall diagrams are scaled down to one page while staying above a configurable readability floor.
- Extremely tall diagrams are paginated. Page breaks prefer gaps between flowchart nodes, and a small overlap is used where possible so a node cut at a boundary is still visible on both pages.
- No more huge blank areas: if a diagram would leave a lot of the page unused, the first slice starts on the current page and the rest continues on following pages.
- Headings stay with their diagrams, so you never get a section title stranded at the bottom of a page.
graph LR
A[Markdown] --> B[HTML + Mermaid.js]
B --> C[Headless Chrome]
C --> D[Layout pass]
D --> E[Pixel-perfect PDF]
Print typography
- Tables repeat their header row across pages and never split a row.
- Long code lines wrap instead of running off the page.
- Widows and orphans are minimised.
- Relative images keep working (
).
Live Preview
Preview your rendered Markdown in a side panel — with Mermaid diagrams — before exporting.
- Cmd+Shift+P →
BeautifulMD: Preview Markdown
- Edits update the preview in real time (~300ms debounce)
- Click Export to PDF directly from the preview toolbar
Requirements
BeautifulMD requires a Chromium-based browser installed on your system. Any of these will work:
BeautifulMD auto-detects your browser. If detection fails, set the path manually (see Settings below).
Mermaid.js is loaded from a CDN when the document is rendered, so an internet connection is required for Mermaid diagrams (see the FAQ).
Commands
| Command |
Description |
BeautifulMD: Export to PDF |
Export the current Markdown file to PDF |
BeautifulMD: Preview Markdown |
Open a live-rendered preview panel |
Both commands are available via:
- Command Palette (Cmd+Shift+P / Ctrl+Shift+P)
- Editor title bar icons (when a
.md file is open)
- Right-click context menu in the editor
Settings
| Setting |
Default |
Description |
beautifulmd.chromePath |
"" (auto-detect) |
Absolute path to a Chrome/Chromium executable |
beautifulmd.pdfFormat |
"A4" |
Paper size: A4, Letter, Legal, A3, A5, Tabloid |
beautifulmd.printBackground |
true |
Include background colors and images in PDF export |
beautifulmd.mermaidTimeout |
15000 |
Max time (ms) to wait for Mermaid diagrams to render |
beautifulmd.mermaidPagination |
"auto" |
How diagrams are fitted to pages (see below) |
beautifulmd.mermaidMinScale |
0.55 |
Smallest scale auto will shrink a diagram to before splitting it instead |
| Mode |
Behaviour |
auto (recommended) |
Fit to width, shrink tall diagrams to one page when they stay above mermaidMinScale, otherwise split at node boundaries. Also splits when a diagram would leave more than ~35% of a page blank. |
fit-page |
Always shrink each diagram to fit on a single page. Very tall diagrams can become small, but they are never clipped or split. |
split |
Never shrink for height; split diagrams at page boundaries. Keeps the largest text size. |
off |
Legacy behaviour. Only fit to width; tall diagrams may be clipped. |
Example: taller diagrams, a little smaller
{
"beautifulmd.mermaidPagination": "fit-page",
"beautifulmd.mermaidMinScale": 0.45
}
How It Works
┌─────────────┐ ┌──────────────┐ ┌────────────────┐ ┌──────────────┐ ┌─────────┐
│ Markdown │──>│ markdown-it │──>│ Headless │──>│ Print │──>│ PDF │
│ (.md file) │ │ + Mermaid │ │ Chromium │ │ layout pass │ │ file │
└─────────────┘ └──────────────┘ └────────────────┘ └──────────────┘ └─────────┘
Parse & render Load as a real Fit, shrink,
to full HTML web page split diagrams
- Parse — markdown-it converts your Markdown to HTML, with a custom plugin that transforms
```mermaid blocks into <div class="mermaid"> elements.
- Render — A headless Chromium instance loads the HTML as a real web page, fetching Mermaid.js from CDN to render diagrams as SVGs.
- Lay out — Before printing, BeautifulMD measures each SVG against the printable page. It sets explicit dimensions, keeps diagrams off page boundaries, and converts a too-tall diagram into page-sized
viewBox slices.
- Print — Chromium's built-in PDF printer captures the laid-out page. Run
BeautifulMD: Export to PDF again and open the BeautifulMD output channel (or choose Show Details after exporting) to see per-diagram scale and split information.
FAQ
My diagram is split across two pages. Can I keep it on one page?
Yes. Set:
{
"beautifulmd.mermaidPagination": "fit-page"
}
The diagram will be shrunk to a single page. If it still looks too large, lower beautifulmd.mermaidMinScale and use auto — BeautifulMD will shrink it more before deciding to split.
My diagram became smaller than I expected
In auto mode a diagram is scaled to the available width and, when needed, to the page height. This is what prevents clipping. If you prefer larger text and do not mind pagination, use "beautifulmd.mermaidPagination": "split". You can also increase beautifulmd.mermaidMinScale; diagrams that would need to be smaller will be split instead.
Mermaid diagrams aren't rendering in my PDF
Mermaid.js is loaded from a CDN at render time. Ensure you have an internet connection. If diagrams still fail, try increasing the timeout:
{
"beautifulmd.mermaidTimeout": 30000
}
If Mermaid fails to load, the diagram source is shown in a readable code block instead of disappearing.
"Could not find a Chrome/Chromium installation"
BeautifulMD needs a Chromium-based browser. Either:
- Install Google Chrome
- Set the path manually:
"beautifulmd.chromePath": "/path/to/chrome"
- Set the
CHROME_PATH environment variable
Can I use this offline?
PDF export works offline for standard Markdown. However, Mermaid diagrams require an internet connection since Mermaid.js is loaded from a CDN. If the CDN is unreachable, the export still succeeds and the Mermaid source is shown in a readable code block.
Development
pnpm install
pnpm run compile # production webpack bundle
./node_modules/.bin/tsc -p . --outDir out # compile the test harness output
node tools/render-pdf.js --debug # render examples/pagination-demo.md
node tools/test-bundle.js # drive the real bundle through a vscode shim
node tools/verify-pdf.js examples/pagination-demo.pdf
npm run package:vsix # build inside dist/ and package the VSIX
tools/render-pdf.js accepts --format=A4|Letter|A5|A3, --pagination=auto|fit-page|split|off, --safety=<px> and --debug. tools/verify-pdf.js requires pdfinfo and pdftotext (poppler-utils).
See CONTRIBUTING.md for the full workflow.
Release Notes
0.2.0
- Renamed to BeautifulMD; commands and settings now use the
beautifulmd.* namespace.
- Balanced multi-page diagram slices; no more tiny final slices and almost-empty tail pages.
- Capacity-aware diagram scaling for
auto, so a split diagram fills the pages it uses.
- Compact print tables to reduce page spills.
- Extra allowance for the first slice of a split, avoiding page pushes caused by Chromium's printed-text metrics.
- Verified against a 9-diagram, 450-line document: 23 pages before the final layout tuning, 19 pages after, with no page gap above ~18% except the final table page.
0.1.0
- Smart Mermaid pagination: fit-to-width sizing, readable shrink-to-page, and node-aware multi-page splitting — no more clipped diagrams.
- No more large blank areas before tall diagrams; page breaks are chosen against the remaining page space.
- Headings move with their diagrams, avoiding orphaned section titles.
- New
beautifulmd.mermaidPagination and beautifulmd.mermaidMinScale settings.
- Better print typography: repeated table headers, safer row breaks, wrapped code, widow/orphan control.
- Preview diagrams are responsive and re-render correctly after edits.
- Export diagnostics in the BeautifulMD output channel (
Show Details after exporting).
- Development fixtures, a bundle-level smoke test and a PDF verification script.
0.0.1
- Initial release
- Export Markdown to PDF with Mermaid diagram support
- Live preview panel with real-time updates
- Cross-platform Chrome/Chromium/Edge/Brave auto-detection
- Configurable paper format, margins, and background printing
License and attribution
BeautifulMD is released under the MIT License.
It is a fork of SnapMD:
- Original work: Copyright (c) 2026 besingamkb
- Modifications and BeautifulMD branding: Copyright (c) 2026 MaoWei-Weng
The original MIT copyright and permission notice is retained in LICENSE.
See NOTICE.md for the attribution statement. The SnapMD name is used
only to describe the origin of this project; BeautifulMD is not affiliated with or
endorsed by the original author.