pymdtools
pymdtools is a Python library for inspecting, transforming and publishing
Markdown documents. Assemble reusable sections, edit links, normalize formatting,
generate HTML or PDF, and translate text through an injectable client.
Python 3.11–3.14 is tested in CI on Linux and Windows, with additional macOS checks. Core Markdown and HTML features work without a browser or PDF dependencies.
Installation
Install into your Python environment:
python -m pip install pymdtools
For PDF output, install the extra and the browser in the same environment:
python -m pip install "pymdtools[pdf]"
python -m playwright install chromium
On Linux, use python -m playwright install --with-deps chromium to install
browser system libraries as well. See the
installation guide
for virtual environments and source installations. The examples and developer
scripts below belong to the repository or source archive; they are not installed
as commands by the wheel.
First document
This example creates build/hello.md and build/hello.html, together with the
HTML layout's assets. Running it again replaces the generated files; Markdown
writes keep a dated backup by default.
from pathlib import Path
from pymdtools.mdfile import MarkdownContent
from pymdtools.mdtopdf import convert_md_to_html
output = Path("build")
output.mkdir(exist_ok=True)
document = MarkdownContent(
content="# Welcome\n\nProject: <!-- begin-var(project) --><!-- end-var -->\n"
)
document["project"] = "pymdtools"
document.process_tags()
document.write(output / "hello.md")
html_path = convert_md_to_html(output / "hello.md", layout="github")
print(html_path)
Open the HTML file in a browser. Keep its adjacent _pymdtools_assets/ directory
when copying or publishing the page. To also produce build/hello.pdf, after
installing PDF support:
from pymdtools.mdtopdf import convert_md_to_pdf
from pymdtools.options import PdfFeatures
from pymdtools.pdf_backend import PdfOptions
pdf_path = convert_md_to_pdf(
"build/hello.md",
options=PdfOptions(page_format="A4", timeout=60),
features=PdfFeatures(metadata={"title": "Welcome", "author": "Example team"}),
)
Choose a workflow
| Task | Public entry point | Guide |
|---|---|---|
| Edit documents, titles and variables | pymdtools.mdfile.MarkdownContent |
Documents |
| Resolve snippets and shared sections | pymdtools.instruction |
Directives |
| Find, rename and rebase links | pymdtools.mdcommon |
Links |
| Normalize Markdown | pymdtools.normalize |
Normalization |
| Generate HTML, PDF and overlays | pymdtools.mdtopdf |
Conversion |
| Convert HTML to Markdown | pymdtools.markdownify_integration |
HTML input |
| Translate text and Markdown | pymdtools.translate |
Translation |
| Read files, process trees and load templates | pymdtools.common, pymdtools.filetools |
File tools |
The example catalogue contains 25 focused scripts and one complete workflow, with local sample data and expected outputs. From a checkout, after installing the package:
python -m pip install -e .
python examples/run_all.py --list
python examples/run_all.py
python examples/22_report_pipeline.py
The default runner executes 23 scenarios with core dependencies. Results go to
examples/output/<example>/. Install .[pdf] and Chromium before using
--only-pdf for the three PDF scenarios, or --pdf for all 26.
Behavior to know
- Link inspection and edits use CommonMark source positions. Duplicate link occurrences are preserved, reference identifiers are case-insensitive, and images and code are excluded from ordinary link discovery.
- Normalization returns the input unchanged if the candidate changes CommonMark rendering or fails its idempotence check. Extensions used by other Markdown dialects need validation against representative documents.
MarkdownContent.process_tags()changes the in-memory buffer; callwrite()to save it.include-fileaccepts a filename, with directories supplied throughIncludeOptions(search_folders=...). Reference discovery scans each root only by default; setrefs_depth=-1explicitly for recursion.- HTML conversion uses an escaping Mistune renderer by default. The explicit
converter="markdown"alternative preserves raw HTML and needs trusted input. File inclusions also need trusted documents and deliberate search roots. - PDF rendering disables JavaScript and remote resources by default. Local
assets are confined to the HTML directory and permitted source asset root.
PdfOptions.timeoutlimits the Chromium worker lifetime, including startup; it does not cover separate Markdown conversion or PDF post-processing. - Translation uses the external MyMemory service unless a custom transport is supplied. The repository's translation examples run entirely offline.
See the options reference, troubleshooting guide and changelog for defaults, errors and migration details.
Development and documentation
From the repository root, create the locked development environment:
python -m pip install uv==0.12.19
uv sync --locked --group dev --group docs --extra pdf
uv run --no-sync pytest
uv run --no-sync python -m sphinx.cmd.build -W --keep-going -b html docs docs/_build/html
uv run --no-sync python -m sphinx.cmd.build -W --keep-going -b doctest docs docs/_build/doctest
Open docs/_build/html/index.html. Chromium is only required for the optional
PDF examples and integration test. See
CONTRIBUTING.md
for lint, types, VS Code, distributions and CI, and the
release guide
for versioning and publication. Maintainers can prepare versions and changelog
notes with scripts/release.py prepare patch; pushing the resulting version tag
automates validation, PyPI publication and the GitHub release.
The library lives in src/pymdtools.
Project links and licenses
Original Python code and sample data use the MIT license. Bundled layouts retain their own terms and attribution; the resource inventory records the terms of the bundled resources and the replacement of historical themes. Installed dependencies have separate licenses, including GPL/LGPL components; see the dependency inventory.
Metadata
Release files for pymdtools 3.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pymdtools-3.0.0.tar.gz | 968.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pymdtools-3.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 1.7 MB
Release files / pymdtools-3.0.0.tar.gz
| Download URL | pymdtools-3.0.0.tar.gz |
|---|---|
| Size | 968.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8daf12830a594af2963ba3e5f33b36b88de4fa1dc1ef6bb73e9feb24da597662
|
|
BLAKE2b-256 checksum How to use checksums |
7f8956bbc85a54426a53f30fdae9dbda9ad06eb445034c6d3c9a35546c99d2d8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / pymdtools-3.0.0-py3-none-any.whl
| Download URL | pymdtools-3.0.0-py3-none-any.whl |
|---|---|
| Size | 779.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8aa52ff4a189c3a298cc721654d9dd3c65a04f6f54ef8fd698234a37f0cecc8b
|
|
BLAKE2b-256 checksum How to use checksums |
8276b3f7dffc0555ec4cca3ca8d4f2f2800c07eac60b5b0dcf1d34da2099c448
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log