Skip to main content

mf2dom

Microformats2 (mf2) parser and deterministic renderer powered by JustHTML.

mf2dom focuses on:

  • Correct mf2 parsing (validated against the official microformats-tests suite)
  • Deterministic HTML rendering and stable round-trips (HTML -> mf2 -> HTML)
  • A small runtime surface area (no network I/O, no BeautifulSoup)

Installation

pip install mf2dom

Requires Python 3.11+.

Quickstart

Parse mf2 JSON from HTML:

import mf2dom

html = '<a class="h-card u-url p-name" href="/me">Alice</a>'
doc = mf2dom.parse(html, base_url="https://example.com/")
print(doc["items"])

The parsed document is a dict with items, rels, and rel-urls keys (mf2 JSON shape).

Render mf2 JSON back into canonical HTML:

html2 = mf2dom.render(doc)

Async parsing (offloads to a thread):

doc = await mf2dom.parse_async(html, base_url="https://example.com/")

API

  • mf2dom.parse(html, *, base_url=None, url=None) -> dict
    • html can be a string/bytes, a justhtml.JustHTML instance, or a JustHTML root node.
    • base_url controls resolution of relative URLs (preferred). url is a deprecated alias.
  • mf2dom.parse_async(...) is parse(...) via asyncio.to_thread(...).
  • mf2dom.render(doc) -> str renders a deterministic HTML representation of an mf2 document.

JavaScript/TypeScript Renderer

A TypeScript implementation of the renderer is available in src/mf2dom-ts/ for client-side rendering (e.g., with sql-wasm.js).

Installation

cd src/mf2dom-ts
npm install
npm run build

Usage

ES Module:

import { render, renderItemElement, renderItems } from './dist/mf2dom.esm.js';

// Render full document to HTML string
const html = render(mf2Document);

// Render to DOM element (most efficient for client-side)
const main = render(mf2Document, { asElement: true });
document.body.appendChild(main);

// Render single item
const card = renderItemElement(hCard);

// Batch render with DocumentFragment (efficient for lists)
const fragment = renderItems(entries);
container.appendChild(fragment);

Browser script tag:

<script src="dist/mf2dom.min.js"></script>
<script>
  const html = mf2dom.render(doc);
  // or
  const el = mf2dom.render(doc, { asElement: true });
</script>

Build Output

File Size Use Case
dist/mf2dom.esm.js 5.2kb ES modules (bundlers, modern browsers)
dist/mf2dom.cjs 5.7kb CommonJS (Node.js)
dist/mf2dom.min.js 5.7kb Browser <script> tag

Why mf2dom vs mf2py?

Both libraries parse microformats, but they optimize for different use cases:

  • Choose mf2dom if you need deterministic rendering, stable round-trips, and a smaller/no-network runtime surface (useful for normalization, caching, and “canonical mf2 HTML” fixtures).
  • Choose mf2py if you need URL fetching, microformats1 compatibility, metaformats support, or wider Python version support.

Testing & correctness

  • Official parsing fixtures: tests/test_official_microformats_suite.py runs the upstream microformats-tests JSON fixtures.
  • Coverage gate: pyproject.toml enforces 100% branch coverage.

To run the official fixture suite locally, check out microformats-tests as a sibling directory:

git clone https://github.com/microformats/microformats-tests ../microformats-tests

Development (uv)

uv sync --group dev
uv run pytest
uv run coverage run -m pytest && uv run coverage report
uv run pre-commit install

License

AGPL 3

Metadata

Release files for mf2dom 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for mf2dom 0.2.1
File Size Uploaded Provenance Actions
mf2dom-0.2.1.tar.gz 15.0 MB Without provenance Details for mf2dom-0.2.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for mf2dom 0.2.1
File Interpreter ABI Platform Actions
mf2dom-0.2.1-py3-none-any.whl Python 3 none any Details for mf2dom-0.2.1-py3-none-any.whl

Total release size: 15.1 MB

Release files / mf2dom-0.2.1.tar.gz

Download URL mf2dom-0.2.1.tar.gz
Size 15.0 MB
Tags Source
SHA-256 checksum
How to use checksums
2c2d73f244db88fcbabe42319879824bbc6e502a28cf618432735282ee6e4b98
BLAKE2b-256 checksum
How to use checksums
f08249eaebfb10842d711bd6a3a034a89dd8fd11f946721524c152312dc48278
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Release files / mf2dom-0.2.1-py3-none-any.whl

Download URL mf2dom-0.2.1-py3-none-any.whl
Size 36.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
c3f3565e9d9a5f094ab9617f78aa9fd357cffd438c229616963fd689812c2da2
BLAKE2b-256 checksum
How to use checksums
c38ea9f78a8356a0ac1b6bc46c81a3b3aaae03689f8e125cebaa51ec06a814c6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.9

Security for mf2dom 0.2.1

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.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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