Markdown to pdf
Convert one or more Markdown files to clean, print-styled PDFs. Use when the user asks for "a PDF version of <doc>.md", "export this markdown to PDF", "make a PDF of this doc", "turn these notes into a PDF", or wants to share a local .md as a PDF. Handles the macOS wkhtmltopdf 0-page trap and preserves monospace/aligned blocks.From its SKILL.md
npx -y skills add bendyworks/claude-skills --skill markdown-to-pdfAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.6 KB, as published. Nobody here has run it
Markdown to PDF
Turn a local Markdown file into a shareable, print-styled PDF. The pipeline is md -> self-contained styled HTML -> PDF, because going through HTML gives consistent typography and keeps aligned/monospace blocks intact, and because the reliable PDF engine (a Chromium-family browser's headless print) takes HTML, not Markdown.
Fast path
Run the bundled driver; it does everything and verifies the result:
bash SKILL_DIR/md2pdf.sh INPUT.md [OUTPUT.pdf] [WORKDIR]
OUTPUT.pdfdefaults to the source path with a.pdfextension (PDF lands next to the source, which is what "give me a PDF of X.md" almost always means -- do NOT drop it in a temp dir).- Pass your session scratchpad as
WORKDIRso the intermediate HTML is kept out of the user's project; otherwise a temp dir is used. - For several files, loop over the driver; add a short
sleep 1between Chrome invocations (headless Chrome can trip over rapid back-to-back runs).
The driver converts md->HTML (kramdown, else pandoc, else python-markdown),
then tries PDF engines in order (Chrome/Chromium headless, then wkhtmltopdf
with page-count verification, then weasyprint), and exits non-zero if the
final PDF has 0 pages. SKILL_DIR is this skill's own directory.
Hard-won gotchas (the reason this skill exists)
- wkhtmltopdf silently emits 0-page PDFs on macOS (patched-Qt builds). It
returns success and writes a ~50KB file that opens blank --
file x.pdfsaysPDF document, version 1.4, 0 pages. ALWAYS verify page count; never trust a zero exit. The driver does this and discards a 0-page result. Prefer a Chromium-family browser's headless print, which is reliable here. - kramdown: use the default parser, not GFM.
Kramdown::Document.new(src, input: "GFM")raisesno parser to handle GFMunlesskramdown-parser-gfmis installed (it usually is not). The default parser handles headings, bold, lists, indented code blocks, and tables -- which covers ordinary docs. The bundledmd2html.rbalready does this (and falls back to redcarpet). - Keep the HTML self-contained. Inline all CSS; no web fonts, no remote
images. An external reference makes the PDF step attempt a network fetch
(wkhtmltopdf throws
HostNotFoundError; Chrome stalls).md2html.rbinlines everything. - Preserve aligned/monospace blocks. Space-aligned column blocks and code
fences must render as
<pre>withwhite-space: preand a monospace font, or the alignment collapses. The bundled CSS does this; it's the thing most sensitive to breakage, so eyeball those blocks after rendering.
Chrome headless invocation (manual fallback)
If you skip the driver:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--headless=new --disable-gpu --no-pdf-header-footer \
--print-to-pdf="OUT.pdf" "file://ABSOLUTE/PATH/TO/page.html"
Use an absolute file:// path. --headless=new is for modern Chrome; old
builds want plain --headless. --no-pdf-header-footer drops the default
date/URL chrome. On Linux use google-chrome/chromium; weasyprint or
pandoc --pdf-engine=weasyprint are good non-browser alternatives there.
Verify before reporting done
file OUT.pdf-> must sayN pageswith N > 0 (0 pages = failed render). Some Linux builds offile(1)omit the page count entirely -- fall back topdfinfo OUT.pdf, or at minimum a non-zero-size check.- A real multi-page PDF is tens of KB+; a couple-KB file is suspect.
- If
pdftoppm/poppler is installed you can rasterize a page to eyeball it; if not, confirm the corrected/critical sections made it in by grepping the intermediate HTML for a distinctive phrase, and tell the user you verified structurally (not visually) so they give the layout a glance -- monospace column alignment is the one thing worth a human look.
Styling / tweaks
Edit md2html.rb's CSS block: page size and margins are set on the PDF-engine
side (driver uses Letter + 16mm; Chrome uses the HTML's @page if present).
Common asks: force a page break before a section (page-break-before: always),
shrink a wide <pre> (drop its font-size), or add a title/date header (prepend
to the body). Keep everything inline and offline.