Skip to content
PDF-magicPublic

Repository files navigation

PDF Compiler

A reusable Markdown-to-PDF renderer for polished, legal-style documents, with a browser configurator for presentation, metadata, validation, section structure, and output settings.

Install

python -m pip install -r requirements.txt

Web configurator

Emoji in paragraph text, section headings, the table of contents, and document titles render as inline color images using bundled Twemoji artwork. No emoji font or network connection is required. Artwork credits and licensing are in the emoji asset notes.

Run the web app:

python app.py

Then open http://127.0.0.1:5000.

The configurator accepts an uploaded Markdown file or pasted Markdown and lets you control the generated PDF without modifying the source text. Settings include:

  • output filename
  • PDF metadata: document title, author, subject, and keywords
  • optional previous PDF upload that reuses Title, Author, Subject, and Keywords when the corresponding metadata fields are blank
  • optional smart quotes in rendered text
  • section numbering: legal form such as I.B.3.a.i, decimal form such as 1.2.3.4.5, or no visible numbering
  • optional visible table of contents using the generated section labels and page locations
  • uploaded logo or text wordmark
  • logo treatment: preserve as uploaded, auto-trim empty padding, or auto-trim and optimize for monochrome printing
  • optional handwritten signature image rendered over a signing line by a standalone [[signature]] Markdown tag
  • first-page date and date format, including September 6, 2026, 4 May 2025, ISO, US numeric, or a custom strftime format
  • submission subtitle such as Submitted by email or Submitted via FedEx
  • optional Quote # reference rendered in the top-right of the first page
  • addressee text with an optional bordered letterhead box
  • separate first-page and remaining-page header text, with clickable Markdown links and inline bold/italic formatting
  • footer page-count styles: none, 1, Page 1, 1 of 5, or Page 1 of 5
  • optional subdued DRAFT | Ref: ... | Commit: ... footer watermark on every page, including footnote continuations
  • optional legal-style preflight validation; findings do not block PDF rendering
  • optional HTTP(S) URL validation and canonicalization checks

The Running header & footer step includes an opt-in draft watermark. Enter a draft reference and a commit SHA to identify the exact source revision in the PDF footer. Alternatively, supply a public GitHub repository (owner/repository) and optionally the relative source path; when the SHA field is blank, the compiler resolves the latest commit on the repository's default branch, or the most recent commit affecting that file. The commit is resolved when compiling, not continuously updated after download. GitHub lookup uses its unauthenticated public API; private repositories and rate-limited lookups require a manually pasted SHA. The compiler cannot infer a source commit from a file uploaded through the browser. This footer is disabled by default and is separate from the page-number style.

Section structure is always written into the PDF outline/bookmark metadata. Turning off the visible table of contents only removes the TOC pages, and choosing no visible section numbering only removes numbering from displayed section labels; neither setting removes the PDF section outline.

Table of contents placement

Put [[TOC]] on its own line where the visible table of contents should appear in the Markdown body:

Introductory text.

[[TOC]]

## First section

The TOC marker can also be written as a Markdown heading using [TOC] as the complete heading text. All six heading levels are supported, and the generated “Table of Contents” title uses the corresponding heading style:

# [TOC]

## First section

The same works with ## [TOC] through ###### [TOC]. Heading-form markers are insertion directives only: they are not numbered, added to the PDF outline, or listed inside the TOC itself.

A standalone TOC marker enables the visible TOC even when the configurator checkbox is off. When the checkbox is on, the marker overrides the default placement at the start of the document. Only the first standalone marker inserts the TOC; later standalone markers are ignored. Both [[TOC]] and heading-form markers inside fenced code blocks remain literal text, so documentation examples can safely show the syntax.

The preflight validator reports line and column locations for required legal-style italics such as _See_, _See, e.g.,_, _Id._, _Ibid._, _supra_, _infra_, _available at_, and _note_ 4. These checks are case-insensitive. It also checks HTTP(S) URLs for valid structure and resolvable public hostnames, rejecting malformed, nonexistent, localhost, and private-network targets. HTTP URLs must use HTTPS when the same public host can complete a valid TLS connection; HTTP remains allowed when HTTPS is unavailable. Root URLs omit the trailing slash (https://example.com, not https://example.com/), while trailing slashes on non-root paths remain allowed. Validation is read-only and does not rewrite Markdown.

The web configurator renders the entire supplied Markdown document. Remove any drafting notes or email instructions from the input before rendering. The rendered PDF opens inline in a new tab so the configurator remains available for another render.

Signature sections

Keep the sign-off language, signer name, title, and any other designation in the Markdown itself. Put [[signature]] on its own line only where the handwritten signature should appear:

In good faith,

[[signature]]

John Wooten

Chief Compliance Officer

Upload a signature image in the web configurator or pass --signature path/to/signature.png on the command line. The compiler trims white or transparent padding, places the handwriting over a short signing line, and renders just the blank line when no image is supplied. The tag is recognized only on its own line outside fenced code blocks, so examples can safely show [[signature]] inside a code fence.

Footnote number references

Markdown footnote keys can be reused as stable references to the final rendered note number. A normal footnote citation assigns the number:

The first proposition.[^ref-a]

Elsewhere in the document, {{ref-a}} is replaced with that note number as plain text:

_See supra note_ {{ref-a}}.

If ref-a is ultimately note 7, the rendered text reads See supra note 7. The compiler determines numbers from real [^key] citations before rendering, so {{key}} does not create a footnote or change numbering and can safely appear before or after the citation. An unknown {{key}} is left visible rather than being assigned a number.

Command line

Render a Markdown file directly:

python pdf_compiler.py path/to/document.md

The default output is the source path with a .pdf suffix.

Useful options:

--output PATH          choose the output PDF
--logo PATH            add an image logo to the first page
--signature PATH       add a handwritten image for [[signature]] tags
--wordmark TEXT        use a text wordmark when no logo is supplied
--title TEXT           set PDF title metadata
--author TEXT          set PDF author metadata
--start-heading TEXT   compile only content after an exact Markdown heading
--smart-quotes         use typographic quotes in rendered text

For example:

python pdf_compiler.py comment.md \
  --output comment.pdf \
  --logo imgs/logo.png \
  --signature imgs/signature.png \
  --title "Comment Letter" \
  --author "WhyDRS" \
  --start-heading "Letter" \
  --smart-quotes

The additional presentation controls for subject/keywords metadata, visible TOC, section-numbering style, letterhead, running headers, footer page counts, and document preflight are provided by the web configurator and ConfiguredPdfRenderer.

Formatting and document behavior

The compiler supports:

  • US Letter output with Times typography
  • hierarchical section numbering for nested Markdown headings, including legal and decimal styles
  • PDF outline/bookmark entries for sections regardless of visible TOC settings
  • an optional visible table of contents with hierarchical indentation and page numbers
  • configurable Markdown footnote placement: bottom of the referenced page, a single endnote list, or document-end endnotes grouped by the H1 where each note is first cited
  • {{key}} interpolation for stable references to final Markdown footnote numbers
  • basic bold, italic, inline code, links, block quotes with optional per-block hex colors, sourced quotation blocks, GitHub-flavored admonition blockquotes, lists, rules, and local images
  • standalone [[signature]] sections with an optional handwritten image over a signing line
  • optional first-page logo or text wordmark
  • configurable PDF metadata
  • configurable first-page letterhead date, submission subtitle, and top-right Quote # reference
  • optional drag-and-drop first-page letterhead canvas: move, resize, align, or hide existing header, logo/wordmark, visible title, quote number, date, subtitle, and addressee; add up to 12 labeled custom text fields. Keyboard arrows nudge focused fields (Shift for larger steps). Turning the editor off retains the original fixed letterhead layout. The PDF renderer reserves space below the lowest visible field.
  • optional boxed addressee block
  • separate first-page and later-page headers
  • selectable footer page-count formats using the final PDF page count
  • optional logo cleanup for padded assets and monochrome printing
  • optional smart-quote rendering without changing the Markdown source
  • read-only legal-style and HTTP(S) URL validation before PDF generation

GitHub-flavored admonition blockquotes

The compiler recognizes GitHub-style blockquote markers for NOTE, TIP, IMPORTANT, WARNING, and CAUTION:

> [!NOTE]
> This text uses the NOTE style slot.

The marker selects a blockquote style and is not printed as a label. In the web configurator's Style page, each category has an independent optional header, accent color, and left indent. Optional headers are centered in Times small caps, with lowercase letters rendered as reduced capitals. Category colors can be cleared to inherit the ordinary blockquote accent, and the existing blockquote corner-radius setting applies to both ordinary quotes and admonitions.

Per-blockquote hex colors

A blockquote can override its configured accent color with a six-digit hex directive. The directive is metadata and is not printed:

> [!COLOR #7C3AED]
> This blockquote uses #7C3AED.

For sourced quotations and GitHub-flavored admonitions, put the color directive immediately after the block type marker:

> [!QUOTE]
> [!COLOR #2563EB]
> The quotation body uses the custom color.
> [!SOURCE] Example source

> [!WARNING]
> [!COLOR #B42318]
> This warning uses the custom color.

Only full six-digit colors such as #2E732E are treated as directives. Invalid or abbreviated values remain ordinary quoted text. A per-block color overrides the quote accent and any background that was derived from that accent; an explicitly configured separate blockquote background remains unchanged.

Sourced quotation blocks

Use a QUOTE marker and a final SOURCE line to keep the quotation text and its attribution distinct in the document source. SRC is accepted as a shorter alias for SOURCE.

> [!QUOTE]
> The important thing is not to stop questioning.
> [!SOURCE] Albert Einstein

The equivalent shorthand is > [!SRC] Albert Einstein.

Neither marker is printed. The source renders beneath the quotation, right-aligned and prefixed with an em dash. Inline Markdown, links, and footnote references remain available in both the quotation and its source.

To preserve footnotes from the quoted source, define them inside the quotation. Their labels are rendered exactly as written, so numbering may be independent and discontinuous without affecting the document's ordinary footnote sequence:

> [!QUOTE]
> First quoted passage.[^4] Later quoted passage.[^17]
> [^4]: The source's original fourth footnote.
> [^17]: The source's original seventeenth footnote.
> [!SOURCE] Author, *Work*

Quote-local footnotes render inside the quotation after its text and before the right-aligned source attribution. A footnote whose definition is outside the quotation remains an ordinary document footnote.

The rendering engine, presentation settings, and validation layer are kept separate so document generation does not alter source content.

Professional filing style

Select Professional filing in the Typography preset selector for a restrained presentation inspired by the reference SEC comment letter. It uses one-inch side margins, 12 pt Times body text with 1.5 line spacing, justified paragraphs with first-line indents, compact headings, 10.5 pt footnotes, plain inset quotations, and page numbers positioned inside the bottom margin. Letters without footnotes use the full printable page instead of reserving a note area.

Choosing a preset fills the existing typography and quotation controls and the additional page, paragraph, heading, and footnote controls. It adds no hidden rendering rules: margins, alignment, indents, spacing, heading behavior, quotation decoration, footnote reserve and alignment, and footer position all remain individually editable. Expand the grouped settings on the Typography page to adjust numeric values. Classic restores the default values. Letterhead, metadata, numbering, and footnote placement remain independently configurable.

The same option is available on the command line:

python pdf_compiler.py comment.md --render-style professional --output comment.pdf

The professional CLI style includes Page 1 of N footers. In Python, pass TypographySettings.for_style("professional", body_font_size=12.5) to FirstPagePdfRenderer to select the preset with optional overrides.

Export and import configurations

Use Export config at the top of the configurator to download pdf-compiler-config.json. Use Import config to restore that file, including the selected render style, custom typography, section and footnote settings, metadata, letterhead text and preset, headers, footer options, colors, and licensing settings. Custom values are restored after the typography preset is applied. Configurations also preserve first-page field positions, widths, alignments, visibility, custom labeled fields, and whether the layout editor is enabled.

Configurations contain settings only. Markdown text and uploaded Markdown, logos, signatures, and previous PDFs are excluded; importing preserves the document and uploads already in the form. Keep custom assets alongside your configuration when moving it to another browser or computer. Invalid or unsupported configuration files are rejected before changing any settings.

First-page letterhead editor

Enable Customize positions on the first page in Letterhead to arrange the existing header, logo or wordmark, title, reference, date, submission subtitle, and addressee. Select a field to change its visibility, alignment, width, and horizontal or vertical position; you can also drag it or use arrow keys (Shift for larger movements). Add up to 12 custom labeled text fields. Existing text inputs remain the source of field content.

The editor uses the current page margins and reserves room above the body for visible fields. A positioned addressee appears once. Disabling the editor restores the fixed letterhead layout, while configuration export preserves your custom arrangement for later reuse. This integrates the editor from:

#37

Contributors

Languages