Markdown To PDF

pymdtools.mdtopdf contains the Markdown to HTML/PDF conversion pipeline. Markdown is rendered to HTML, injected into a packaged layout, converted to PDF with pdfkit and wkhtmltopdf, then optionally post-processed with metadata, backgrounds, and watermarks.

Pipeline

The high-level path is:

  • convert_md_to_html renders Markdown into a layout-backed HTML file.

  • convert_html_to_pdf renders that HTML file through wkhtmltopdf.

  • pdf_features applies metadata and overlay PDFs.

  • convert_md_to_pdf orchestrates the complete flow.

Common Usage

from pymdtools.mdtopdf import convert_md_to_pdf

pdf_path = convert_md_to_pdf("README.md")

The external wkhtmltopdf executable must be available on PATH or in one of the additional legacy Windows locations scanned by find_wk_html_to_pdf.

Security

The default converter is the escaping Mistune renderer. The explicit converter="markdown" compatibility mode preserves raw HTML and must only be used with trusted Markdown. Titles and metadata variables are HTML-escaped before layout insertion, and layout assets are never allowed to overwrite a different existing file.

wkhtmltopdf is a legacy external renderer. Keep it isolated from untrusted HTML and network resources, and prefer a maintained rendering backend for new server-side deployments.

Public API

pymdtools.mdtopdf

Markdown to HTML/PDF conversion helpers.

This module coordinates the conversion pipeline used by pymdtools:

  • Markdown text is rendered to HTML with either Python-Markdown or Mistune.

  • The HTML fragment is inserted into a packaged layout template.

  • pdfkit and the external wkhtmltopdf executable render the final PDF.

  • Optional PDF post-processing can apply metadata, backgrounds, and watermarks.

The module deliberately keeps external integrations at the edge:

  • Markdown rendering is delegated to markdown or pymdtools.mistune_integration.

  • File and path validation is delegated to pymdtools.common.

  • PDF reading/writing prefers maintained pypdf and supports PyPDF2 3.x as a compatibility fallback.

  • pdfkit is imported dynamically because it does not ship type stubs.

The public API is intentionally compatible with the historical module names: convert_md_to_html, convert_html_to_pdf, pdf_features and convert_md_to_pdf remain the main entry points.

pymdtools.mdtopdf.check_odd_pages(filename: str | PathLike[str] | Path) Path

Ensure that a PDF has an even number of pages.

If the PDF has an odd page count, a backup is created and one blank page is appended to the original file.

Parameters:

filename – PDF file to inspect and possibly modify.

Returns:

Normalized PDF path.

pymdtools.mdtopdf.convert_html_to_pdf(filename: str | PathLike[str] | Path, filename_ext: str = '.html', **kwargs: Any) Path

Convert an HTML file to a PDF file next to it.

Parameters:
  • filename – HTML file to convert.

  • filename_ext – Expected HTML extension.

  • **kwargs – Optional options. title customizes the PDF header text.

Returns:

Generated PDF file path.

pymdtools.mdtopdf.convert_md_to_html(filename: str | PathLike[str] | Path, layout: str = 'jasonm23-swiss', filename_ext: str = '.md', encoding: str = 'utf-8', path_dest: str | PathLike[str] | Path | None = None, converter: str | None = None) Path

Convert a Markdown file to an HTML file using a packaged layout.

Parameters:
  • filename – Markdown file to convert.

  • layout – Layout folder name under pymdtools/layouts.

  • filename_ext – Expected Markdown extension.

  • encoding – Encoding used for the generated HTML file.

  • path_dest – Destination folder. Defaults to the Markdown file folder.

  • converter – Markdown renderer name. Unknown names fall back to the escaping Mistune renderer.

Returns:

Generated HTML file path.

Raises:
  • ValueError – If the Markdown file is empty or a layout asset path is invalid.

  • FileNotFoundError – If the source file, layout, or asset is missing.

pymdtools.mdtopdf.convert_md_to_pdf(filename: str | PathLike[str] | Path, filename_ext: str = '.md', **kwargs: Any) Path

Convert a Markdown file to PDF.

The conversion is performed in a temporary folder, then the generated PDF is copied next to the source Markdown file and post-processed with pdf_features().

Parameters:
  • filename – Markdown file to convert.

  • filename_ext – Expected Markdown extension.

  • **kwargs – Options forwarded to pdf_features().

Returns:

Generated PDF path.

pymdtools.mdtopdf.converter_md_to_html_markdown(text: str) str

Convert Markdown text to HTML with Python-Markdown.

Parameters:

text – Markdown text.

Returns:

HTML fragment.

pymdtools.mdtopdf.converter_md_to_html_mistune(text: str) str

Convert Markdown text to HTML with Mistune.

Parameters:

text – Markdown text.

Returns:

HTML fragment.

pymdtools.mdtopdf.find_wk_html_to_pdf() Path

Locate the platform’s wkhtmltopdf executable.

Returns:

Normalized executable path.

Raises:

FileNotFoundError – If no executable is found in the known locations.

pymdtools.mdtopdf.get_md_to_html_converter(converter_name: str | None) Callable[[str], str]

Return a Markdown-to-HTML converter by name.

Unknown names fall back to the escaping Mistune converter. The classic Python-Markdown converter remains available explicitly as "markdown" for trusted input that intentionally contains raw HTML.

Parameters:

converter_name – Converter name, usually "markdown" or "mistune".

Returns:

Converter function.

pymdtools.mdtopdf.pdf_features(filename: str | PathLike[str] | Path, filename_ext: str = '.pdf', **kwargs: Any) Path

Apply PDF metadata, backgrounds, and watermarks in-place.

Supported overlay arguments:

  • pdf_background or background_pdf

  • pdf_background_first_page or background_first_page_pdf

  • pdf_watermark or watermark_pdf

Parameters:
  • filename – PDF file to update.

  • filename_ext – Expected PDF extension.

  • **kwargs – Feature options. metadata accepts a mapping of metadata keys without leading slash.

Returns:

Updated PDF file path.