mf2dom
Microformats2 (mf2) parser and deterministic renderer powered by JustHTML.
mf2dom focuses on:
- Correct mf2 parsing (validated against the official
microformats-testssuite) - 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) -> dicthtmlcan be a string/bytes, ajusthtml.JustHTMLinstance, or a JustHTML root node.base_urlcontrols resolution of relative URLs (preferred).urlis a deprecated alias.
mf2dom.parse_async(...)isparse(...)viaasyncio.to_thread(...).mf2dom.render(doc) -> strrenders 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
mf2domif you need deterministic rendering, stable round-trips, and a smaller/no-network runtime surface (useful for normalization, caching, and “canonical mf2 HTML” fixtures). - Choose
mf2pyif you need URL fetching, microformats1 compatibility, metaformats support, or wider Python version support.
Testing & correctness
- Official parsing fixtures:
tests/test_official_microformats_suite.pyruns the upstreammicroformats-testsJSON fixtures. - Coverage gate:
pyproject.tomlenforces 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)
| 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)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| 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.