Markdown to PDF¶
Keep release notes, project briefs, and internal guides in Markdown. Add a print
stylesheet to give the PDF its own typography, page margins, tables, and code
treatment. This starter uses markdown-it-py to parse the content and Fullbleed
to lay out the resulting HTML and CSS.
Download the PDF Get the runnable project
The two-page brief is fictional. Its previews come from the actual PDF, rendered
with Fullbleed 2.5.10, markdown-it-py 4.2.0, and explicit Inter and IBM Plex
Mono fonts. Preview page 2.
Run the project¶
Extract the ZIP, open its
fullbleed-markdown-starter directory, and use Python 3.10 or newer in a virtual
environment:
python -m pip install -r requirements.txt
python render.py brief.md --out output --title "Release notes that travel"
Open output/document.pdf. The command also saves the HTML, stylesheet, glyph
report, and render.json. The JSON records input and asset hashes and the
current PNG preview paths. Preview directories include the PDF hash, so pages
from an older, longer document do not get mixed into the current preview set.
The Markdown parser is an optional dependency of this example. Installing
fullbleed alone does not install it. Rendering uses local fonts and images;
the example needs no browser, hosted PDF service, or system-font installation.
Use your content and design¶
Point the script at another UTF-8 Markdown file:
Relative input and output paths are relative to the current working directory.
The default font and stylesheet are found beside render.py.
Edit print.css, or copy it and pass a replacement with --css:
For example, these rules change page size, heading color, and table headers:
@page { size: Letter; margin: 0.75in; }
h1 { color: #243c69; font-size: 34pt; }
th { background: #243c69; color: #ffffff; }
The script uses static print CSS. It does not execute
JavaScript or code fences. Code is printed in the included monospace font,
without syntax highlighting. Use --no-preview when you only need the PDF.
Local images and fonts¶
Keep referenced images beneath the Markdown file's own directory:
PNG, JPEG, and SVG files are registered with the engine explicitly. The script rejects remote image URLs, absolute paths, missing files, and references that resolve outside that directory. URL-encoded spaces in filenames are supported. The saved HTML contains engine asset aliases; review the PDF or PNGs directly.
Body text uses Inter from the installed wheel. Code uses the bundled, unmodified
IBM Plex Mono font; its OFL license and pinned source hashes are included in the
ZIP. Supply another local TTF with --font and select its actual family in CSS:
The script stops before writing a new PDF if it finds missing glyphs. Check
glyph-report.json; a PDF from an earlier successful run may still exist in the
output directory. An empty glyph report does not prove that every CSS font name
selected the intended face. Inspect the previews when changing fonts, and see
font registration or the
Chinese-font example for broader character coverage.
Supported Markdown¶
The selected js-default parser preset supports paragraphs, headings, ordered
and unordered lists, emphasis, inline and fenced code, block quotes, links,
pipe tables, and strikethrough. Raw HTML is escaped. It does not add task lists,
footnotes, front matter, math rendering, or Mermaid execution, and is not a
claim of complete GitHub Markdown compatibility. The
parser documentation
describes its options.
The local example limits each Markdown or CSS file to 4,000,000 bytes and referenced images to 16 MiB combined. Hosting arbitrary uploads would also need application-specific process isolation, resource limits, and access controls.
Verify before sharing¶
Review every page after content or stylesheet changes, especially long code lines, wide tables, and page breaks. The downloadable project is exercised from an isolated directory on Windows and Linux. Its checks cover the actual ZIP, independent PDF text and previews, repeated output, edited content and CSS, local image handling, and input failures. Retained results are in verification.json; source and download hashes are in source.json.
This starter produces ordinary PDFs. For a document with accessibility or archival requirements, follow the separate accessibility workflow or print-output guide and validate that final artifact.
