Skip to main content

Markdown-to-PDF rendering with FPDF2 and configurable TTF fonts.

Project description

simpdf

simpdf is a small Python library for rendering Markdown into PDF with fpdf2, while keeping font handling explicit so Cyrillic and other non-Latin text work reliably with external TTF fonts.

The library is centered on a MarkdownPdfRenderer class. You give it a directory with TTF files, describe the font face to register, and then render Markdown into PDF bytes or directly into a file.

Features

  • Uses fpdf2 as the PDF backend
  • Supports external TTF fonts and Cyrillic-friendly fonts such as DejaVu Sans
  • Provides a helper to download DejaVu Sans fonts into a target directory
  • Class-first API with optional convenience helpers
  • Minimal CLI for rendering Markdown and downloading DejaVu fonts
  • Supports these Markdown elements in v1:
    • headings
    • paragraphs
    • bold and italic text
    • inline code
    • ordered and unordered lists
    • tables
    • blockquotes
    • fenced code blocks
    • thematic breaks
    • clickable links

Installation

pip install simpdf

For development and tests:

pip install -e .[dev]

Quick Start

from simpdf import FontFace, MarkdownPdfRenderer

renderer = MarkdownPdfRenderer(
    font_directory="fonts",
    font_face=FontFace.dejavu_sans(),
)

markdown_text = """
# Example

Привет, мир.

- one
- two
"""

pdf_bytes = renderer.render_to_bytes(markdown_text)

with open("output.pdf", "wb") as handle:
    handle.write(pdf_bytes)

Downloading DejaVu Fonts

The library does not bundle fonts inside the wheel. Use the download helper to populate your own font directory.

from simpdf import download_dejavu_fonts

downloaded = download_dejavu_fonts("fonts")
print([path.name for path in downloaded])

The helper downloads the DejaVu font files from this public GitHub repository layout:

  • https://github.com/shwars/simpdf/raw/refs/heads/main/fonts/DejaVuSans.ttf
  • other font files use the same URL pattern

Using Custom Fonts

You can use any TTF family as long as you provide at least a regular face. Bold, italic, and bold-italic are optional; if omitted, the regular face is reused.

from simpdf import FontFace, MarkdownPdfRenderer

renderer = MarkdownPdfRenderer(
    font_directory="my-fonts",
    font_face=FontFace(
        family="NotoSansCustom",
        regular="NotoSans-Regular.ttf",
        bold="NotoSans-Bold.ttf",
        italic="NotoSans-Italic.ttf",
        bold_italic="NotoSans-BoldItalic.ttf",
    ),
)

Font file values may be file names relative to font_directory or absolute paths.

Formatting Options

Formatting is configured with a plain nested dictionary. Any omitted value falls back to the library defaults.

Example:

from simpdf import FontFace, MarkdownPdfRenderer

renderer = MarkdownPdfRenderer(
    font_directory="fonts",
    font_face=FontFace.dejavu_sans(),
    formatting_options={
        "text": {"font_size": 11},
        "headings": {
            "sizes": {1: 26, 2: 20, 3: 16},
        },
        "lists": {"indent": 9},
        "table": {"heading_font_size": 13},
    },
)

Supported option groups:

  • page: page size, orientation, and margins
  • text: base font size, line height multiplier, text color
  • headings: per-level sizes and spacing
  • paragraph: paragraph spacing
  • lists: indent, bullet symbol, list spacing
  • blockquote: indent, bar styling, text color
  • table: font sizes, padding, minimum column width, spacing
  • code_block: font size, padding, colors, spacing
  • inline_code: inline code text color
  • links: link color and underline toggle
  • thematic_break: rule color, width, spacing

Convenience Helpers

If you prefer a functional call site, simpdf also exports:

  • render_markdown_to_pdf_bytes(...)
  • render_markdown_to_pdf_file(...)

These helpers internally construct MarkdownPdfRenderer.

CLI Usage

Render Markdown into PDF:

simpdf render input.md output.pdf \
  --fonts-dir ./fonts \
  --family-name DejaVuSans \
  --font-regular DejaVuSans.ttf \
  --font-bold DejaVuSans-Bold.ttf \
  --font-italic DejaVuSans-Oblique.ttf \
  --font-bold-italic DejaVuSans-BoldOblique.ttf

Download DejaVu fonts:

simpdf download-dejavu ./fonts

If you want custom formatting from the CLI, pass a JSON file with --options-file.

Examples

See examples/basic_render.py, examples/custom_font_and_style.py, and examples/rich_markdown.py.

Tests

The repo now contains a pytest suite that covers:

  • font config validation
  • DejaVu download helper behavior
  • markdown token flattening and table extraction
  • PDF rendering with Cyrillic content
  • formatting overrides
  • CLI render and download flows

Run tests with:

pytest

Compatibility Note

For older code that imported simpdf.pdfgen, a small compatibility wrapper is still present. The recommended API is the class-based renderer from simpdf.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

simpdf-0.1.0.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

simpdf-0.1.0-py3-none-any.whl (14.4 kB view details)

Uploaded Python 3

File details

Details for the file simpdf-0.1.0.tar.gz.

File metadata

  • Download URL: simpdf-0.1.0.tar.gz
  • Upload date:
  • Size: 17.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for simpdf-0.1.0.tar.gz
Algorithm Hash digest
SHA256 60971f3fc655ece933752dd982ef5055b4e2c93f268051bec0dcfe74bfc478d4
MD5 507602c08cb4335088697746f9d98989
BLAKE2b-256 91af07cb87f2c5a12998376bc6e4c82a0baf392a5b17474380a097aa93134140

See more details on using hashes here.

File details

Details for the file simpdf-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: simpdf-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.0

File hashes

Hashes for simpdf-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 53fb9880319e1f094c0cd90ee90b7a80434a3c060e39892680b03f19a92bee27
MD5 77c8015dbb4e5e49451e948a42f9d32b
BLAKE2b-256 2aeeb24e8dfb1f4fba388b69a71f0b50af36217f9f87c3fde35dd340c608fd7c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page