Lllm2doc
Reference · 7 min read · Updated April 2026

PDF export from markdown

A reference for how the PDF exporter works — what it does well, what it doesn’t do, and the markdown patterns that produce the cleanest print-ready output.

Key facts
  • Page size: A4 portrait, 15mm margins, 794px content width at 96 DPI.
  • Renderer stack: html2canvas with foreignObjectRendering: truejsPDF.
  • Page breaks: Content-aware. Slice boundaries computed from top/bottom of every block element (h1–h6, p, pre, blockquote, table, ul, ol, li, tr, img). Pages never cut mid-paragraph or mid-row.
  • Math: KaTeX rendered via SVG <foreignObject> (browser-native renderer). Fixes the fraction-bar-on-numerator strikethrough bug.
  • Code: highlight.js with GitHub-Light theme; 100+ languages auto-detected.
  • Images: Cross-origin <img> srcs pre-fetched and inlined as data URLs (CORS-permissive sources work; private hosts render as placeholders).
  • Theme: Always light. PDF is print-ready regardless of UI dark/light setting.
  • Privacy: Runs entirely in browser. No upload, no logging, no server hop.

What the PDF exporter handles

Built-in

A4 portrait, 15mm margins

Hard-coded in the exporter — matches the standard expected by most printers, copy shops, and print-on-demand services. Page width works out to 794px at 96 DPI internally.

Built-in

Smart page breaks

The exporter never cuts mid-paragraph or mid-table-row. Slice boundaries are computed from the top and bottom of every block element (h1–h6, p, pre, blockquote, hr, figure, table, ul, ol, li, tr, img, div), then snapped to the closest one within page-height range.

Built-in

KaTeX math via SVG foreignObject

Equations render via the browser's native renderer (SVG <foreignObject>) rather than html2canvas's CSS reimplementation. This fixes the fraction-bar-on-numerator strikethrough bug that plagued the previous PDF path.

Built-in

Syntax-highlighted code

Code blocks keep their syntax highlighting — the same highlight.js GitHub-Light theme used in the live preview. Language is auto-detected if no fence hint is provided, but explicit `​​​​​​​​​​​​​​​​​​​` language hints (​​​python, ​​​typescript) give the most reliable result.

Built-in

Images embedded inline

Cross-origin <img> tags are pre-fetched and inlined as data URLs before rasterization. CORS-permissive sources (most public CDNs) work; private hosts that don't return Access-Control-Allow-Origin render as broken-image placeholders.

Built-in

Forced light theme

PDF export always uses the light theme regardless of UI mode. Print-ready colors, clean backgrounds, no dark-mode contrast issues on paper.

Recently fixed

The fraction-bar-on-numerator bug

Earlier versions of the PDF export rasterized via html2canvas in its default mode, which doesn’t faithfully reimplement KaTeX’s vlist + pstrut + negative-top fraction layout. Result: the fraction bar drifted onto the numerator and rendered as a strikethrough through expressions like P(B|A) P(A) / P(B). The current exporter uses html2canvas’s foreignObjectRendering: true path, which delegates layout to the browser’s native SVG renderer. Fractions land where they should, every time.

What to know before exporting big docs

Big documents take time

PDF rasterization is CPU-bound on the client. A 50-page document with mixed code, images, and equations takes 5–15 seconds depending on machine. There's no progress bar — the export button just spins until done.

Page break aesthetics

Block elements stay intact; very long ones (a 60-line code block, an oversized image) just get the closest cut even if it's mid-element. There's no orphan/widow protection beyond the block-level slice logic.

Fonts are sans-serif by default

Body text uses the system stack (San Francisco / Segoe UI / Roboto). Code blocks use Courier New. There's no per-doc font picker — if you need custom typography, post-process in a tool that accepts PDF.

No headers or footers

The PDF exporter doesn't inject page numbers, document titles, or running headers. If you need them, open the file in a PDF editor (Preview on Mac, Acrobat, or open-source tools like PDF24) and add them post-export.

Math is rasterized, not vector

Equations render as part of the rasterized canvas, not native PDF math. That means they're crisp at the export resolution (2x by default) but won't reflow if you zoom past 200%. Acceptable for screen + standard print; not ideal for scientific journals that demand vector math.

Markdown patterns for cleaner PDF output

Use \dfrac for inline display fractions

Inline math with \frac shrinks to fit the line height. Switch to \dfrac when you want a full-size fraction inline — useful for keeping critical equations readable in body text.

Group code into smaller blocks

A 200-line code block forces a single-page slice. Split it into logical chunks (50 lines or less) to give the page-break logic somewhere to cut cleanly.

Heading hierarchy drives navigation

Open the PDF in a viewer that respects the document outline (Preview, Acrobat) — your H1/H2/H3 structure becomes a clickable table of contents. Worth shaping headings deliberately for long docs.

Pre-render images to specific sizes

Markdown's `![alt](url)` doesn't have width/height controls. If aspect ratio matters for layout, host pre-sized images or use HTML-input mode with explicit width attributes.

Run a PDF export

Paste any markdown, click PDF, watch a print-ready A4 file land on your desktop.

Open the converter