Skip to main content

PDFMarQ

PDF generation with a fluent API. Core is lean (reportlab + Pillow + svglib). Optional [md] extra adds full markdown-to-PDF rendering with banner headers, math, mermaid, syntax highlighting and more.

Philosophy

PDFMarQ wraps reportlab's stateful canvas into a fluent, cursor-based API. You describe document flow, not coordinates. Markdown rendering lives in a separate subpackage so the core stays installable without heavyweight dependencies.

  • Fluent over imperative: pdf.font("Helvetica", 12).text("Hi").enter().text("World") vs canvas.setFont() → canvas.drawString() → manual Y tracking
  • Cursor flows naturally: top-left origin, y grows down, enter() is a newline
  • One way per feature: pdf.table(), pdf.image(), pdf.svg(), pdf.link(), no overloaded call signatures
  • Markdown is optional: core → 3 deps, [md] adds the stack
  • Banner as contract: YAML frontmatter block becomes a styled banner with logo, status badge, version, dates, signature slot
  • Lean output: no headless Chrome, no web stack, no React SSR. Pure Python + native PDF primitives. Files stay small, rendering stays fast, fonts are embedded properly, and the output opens clean in every PDF reader

Trade-offs:

  • Cursor mutation is a state machine. Great for linear documents, awkward for complex grid layouts. For those, drop into raw reportlab via pdf._canvas.
  • Markdown rendering estimates heights analytically to decide page breaks. Good enough for 95% of content. Edge cases with math + wide tables may push onto the next page more aggressively than necessary.
  • Installing Python + a stack of deps is a barrier for non-technical users. If you're building a tool end-users will actually touch, put PDFMarQ behind a backend service (FastAPI endpoint, CLI wrapper, desktop app) rather than asking them to pip install anything.

Install

pip install pdfmarq      # core: reportlab, Pillow, svglib
pip install pdfmarq[md]  # + markdown rendering stack

Examples

from pdfmarq import PDF
# Fluent core API
with PDF("report.pdf") as pdf:
  pdf.font("Helvetica", 20, "Bold").text("Quarterly Report")
  pdf.enter().font(size=12, mode="Regular")
  pdf.text("Revenue up 23% year-over-year.")
  pdf.table(
    [["Q1", "120k"], ["Q2", "148k"], ["Q3", "172k"]],
    header=["Quarter", "Revenue"],
    sizes=[1, 2], aligns=["C", "R"],
  )
  pdf.image("chart.png", 180, 80)
  pdf.link("https://xaeian.com", 40, 5)
from pdfmarq.md import md_to_pdf, MarkdownStyle
# Markdown to PDF
style = MarkdownStyle(
  font_body="IBMPlexSans",
  font_head="Sora",
  page_number_label="Page", # "Page 1/5" in footer
)
md_to_pdf(open("doc.md").read(), "doc.pdf", style=style, font_dir="./fonts")

See example.py for an end-to-end CLI script. It covers a language preset, custom TTF fonts from ./fonts/, link_root for cross-document references, base_dir for relative images, and optional Ghostscript post-compression.

Markdown features

  • GitHub-flavored markdown (tables, fenced code, lists, strikethrough)
  • YAML frontmatter rendered as a styled banner (logo, status badge, version, sign block)
  • Page geometry, fonts, banner toggles and locale come from the caller's style=, never from the document (see md-guide)
  • Mini-banner on continuation pages with aspect-aware logo (width + height caps)
  • Page numbering Page N/M via deferred canvas rendering (configurable)
  • Built-in language presets (en|pl|de|fr|es|it|cs|sk) via lang_style(): covers banner, callouts, date format, page numbers
  • Skip-duplicate-title: drops # X when it matches frontmatter title
  • Auto-slugged headings with clickable [text](#anchor) internal links (unicode-aware, broken targets degrade to plain text)
  • Local-path links configurable via link_root + link_base (or per-doc YAML base:)
  • Syntax highlighting (Pygments)
  • Math formulas inline $x^2$ and block $$...$$, drawn as vectors (MathJax, matplotlib fallback)
  • Images sized from their own resolution, capped by image_max_h, centred
  • Images alone in a paragraph become a row of figures, wrapping into a grid beyond the text width
  • Mermaid diagrams via mermaid-cli (local) or mermaid.ink (network fallback), capped at a configurable max height
  • Footnotes, emoji shortcodes :rocket:, nested lists, blockquotes, GitHub callouts (> [!NOTE], > [!WARNING], …)
  • Zebra-striped tables (subtle, readability without noise)
  • Smart page breaks for paragraphs, tables, lists, and blockquotes (pre-measured, no orphans)
  • Basic inline HTML pass-through (<b>, <i>, <code>, <br>, <hr>)

Modules

Module Description Docs
pdfmarq Core PDF API (fluent cursor-based drawing) pdfmarq/readme.md
pdfmarq.md Markdown-to-PDF renderer (optional [md] extra) pdfmarq/md/readme.md

See also

Need .docx instead of PDF? Check DocMarQ, the sibling library with the same API shape and .docx output. Syntax highlighting is PDF-only, and math there covers a wider slice of LaTeX (DocMarQ emits native Word equations for the common subset). Everything else (banner, callouts, mermaid, lang presets) works the same in both.

Download files

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

Source Distribution

pdfmarq-0.5.2.tar.gz (142.3 kB view details)

Uploaded Source

Built Distribution

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

pdfmarq-0.5.2-py3-none-any.whl (133.4 kB view details)

Uploaded Python 3

File details

Details for the file pdfmarq-0.5.2.tar.gz.

File metadata

  • Download URL: pdfmarq-0.5.2.tar.gz
  • Upload date:
  • Size: 142.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pdfmarq-0.5.2.tar.gz
Algorithm Hash digest
SHA256 be52a5f77018e63baab32a80853a700b50b2c32687b5206ce7e8c675dca4607e
MD5 36652a72eaa7f5c9ce723a5982884d9d
BLAKE2b-256 8eb5da1dcd494bc1a1b847e19397969e76c8bd8b352367d9cf0a0de68514ed19

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdfmarq-0.5.2.tar.gz:

Publisher: publish.yml on Xaeian/PDFMarQ

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pdfmarq-0.5.2-py3-none-any.whl.

File metadata

  • Download URL: pdfmarq-0.5.2-py3-none-any.whl
  • Upload date:
  • Size: 133.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for pdfmarq-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2e64b3fc79d003c1e3db6cfae43b4b93f8a63b529c7a907beeaa8807444e540c
MD5 a427f33851d27f110f2563c1a93a087c
BLAKE2b-256 bf579350f2c76a66377512255958884d114a8d5a7337d3a32a11e9b9e0bd3a81

See more details on using hashes here.

Provenance

The following attestation bundles were made for pdfmarq-0.5.2-py3-none-any.whl:

Publisher: publish.yml on Xaeian/PDFMarQ

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.5.3

2 files

This release

0.5.2 This release

2 files

0.5.1

2 files

0.5.0

2 files

0.4.2

2 files

0.4.1

2 files

0.4.0

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.1

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page