Markdown to PDF Converter
Paste any Markdown — CommonMark or GitHub-Flavored — pick page size, orientation, and margin, and save it as a PDF in your browser. No signup, no upload, the file never leaves your device. Text stays selectable in the output, not flattened to an image.
How it works
A PDF made from Markdown can be produced two ways: by rendering the HTML to a canvas and stitching the canvas into a PDF (the html2canvas + jsPDF approach), or by handing the rendered HTML to the browser's own print engine via window.print(). The first approach turns every glyph into pixels — the PDF prints fuzzily, the text is unsearchable, and accessibility breaks. The second approach uses the same Blink, Gecko, or WebKit code path that powers Print Preview in the browser's File menu, so the output is a real, text-selectable PDF. This tool uses the second approach.
The pipeline has three stages, each implemented as a pure function in lib/data/markdown-to-pdf.ts:
- Parse. The Markdown is run through marked 14.x with
async: falsefor a synchronous string return. GFM extensions (tables, strikethrough, task lists) are on by default per the GitHub-Flavored Markdown spec; the user can switch back to strict CommonMark with a chip toggle. - Cross-check. Two independent counters — one regex pass over the raw Markdown (skipping fenced code blocks), one walk of the marked lexer's token tree — count headings and code blocks. If they disagree, a
tokenCountConsistent: falseflag surfaces the discrepancy in the stats grid above. Validation errors (empty input, over the 5.0 MB ceiling) produce a specific message, not a silent zero. - Wrap. The rendered HTML is wrapped in a full HTML5 skeleton with a
@pagerule (CSS Paged Media Level 3, §3) that fixes the chosen page size, orientation, and margin. A short print-tuned stylesheet sits inline: serif-free body type, monospace code blocks with a light grey fill, table borders, andpage-break-after: avoidon every heading so a heading never orphans at the bottom of a page. - Render and print. The built document is set as the iframe's
srcdocattribute. The sandbox isallow-modals allow-same-origin— scripts stay disabled but the print dialog can open (HTML Living Standard §4.8.5). The “Download as PDF” button callsiframe.contentWindow.print(), scoped to the iframe so only the document — not the surrounding induwara.lk page — appears in the printed PDF.
5 page sizes are supported — A4, A3, A5, US Letter, US Legal — each in portrait or landscape, with three margin presets from narrow (10 mm) to wide (25 mm). All width and height values are expressed in millimetres so the @page rule needs only one unit. US sizes are converted from inches at 25.4 mm per inch (per ANSI/ASME Y14.1).
Worked examples
Frequently asked questions
Sources & references
- CommonMark Specification 0.31.2 — the canonical Markdown grammar
- GitHub-Flavored Markdown Spec — tables, strikethrough, task lists, autolinks
- marked 14.x — the Markdown parser used by this tool (MIT licensed)
- W3C — CSS Paged Media Module Level 3 (@page rule, size and margin descriptors)
- HTML Living Standard — the iframe element and sandbox token semantics
- HTML Living Standard — Window.print()
- ISO 216 — A-series paper sizes (A4, A3, A5)
- ANSI/ASME Y14.1 — US paper sizes (Letter, Legal)
The Markdown→HTML pipeline was cross-checked against the above standards on 2026-05-11. The page is reviewed whenever the CommonMark spec, GFM spec, or marked publish a new release that touches the supported feature set.
Related tools
Comments & feedback
Spotted a bug or want an improvement? Tell us — our team reviews every comment, and good ideas get built. Comments are public and anonymous.
Found a bug, edge case, or want to suggest an improvement?
Email me at [email protected] — most fixes ship within 24 hours.