QMDC Parser (Python)
QMDC ↔ JSON parser for Markdown with lossless round-trip support.
Installation
cd qmdc-py
uv pip install -e .
CLI Usage
Parse (QMD.md → JSON)
# File → stdout
qmdc parse -i doc.qmd.md
# Stdin → stdout
echo "## Test [[test]]" | qmdc parse
# File → file
qmdc parse -i doc.qmd.md -o output.json
# Without metadata
qmdc parse -i doc.qmd.md --no-comments --no-syntax
# Compact JSON
qmdc parse -i doc.qmd.md --no-pretty
Rebuild (JSON → QMD.md)
# File → stdout
qmdc rebuild -i data.json
# Stdin → stdout
echo '[{"__id":"test","name":"Test"}]' | qmdc rebuild
# File → file
qmdc rebuild -i data.json -o doc.qmd.md
Formatting (parse → rebuild)
There is no separate lint command. Canonical formatting (like ruff/prettier)
is the lossless round-trip through parse → rebuild:
# Canonical formatting
qmdc parse -i doc.qmd.md | qmdc rebuild
Programmatic API
from qmdc import parse, rebuild
# Parse QMD.md → JSON
markdown = """
## User [[user]]
- name: Alice
- age: 30
"""
result = parse(markdown)
# [{"__id": "user", "__label": "User", "name": "Alice", "age": 30, ...}]
# Rebuild JSON → QMD.md
qmdc = rebuild(result)
# "## User [[user]]\n\n- name: Alice\n- age: 30\n"
Testing
# From the project root
make test
# Python tests only
make py-test
# pytest directly
cd qmdc-py
uv run pytest tests/ -v
Workspace (multi-file parsing)
QMDC Parser supports workspaces — a set of related QMD.md files with cross-file reference validation.
Workspace CLI
# Parse a workspace into JSON
qmdc workspace parse ./my-project -o workspace.json
# Validate a workspace
qmdc workspace validate ./my-project
# Rebuild files from JSON
qmdc workspace rebuild workspace.json -o ./output
Query (SQL queries against a workspace)
# SQL query against a workspace (loads all workspaces recursively)
qmdc query ./my-project "SELECT __id, __kind, __label FROM objects WHERE __kind = 'Service'"
# With JSON output
qmdc query ./my-project "SELECT * FROM objects LIMIT 10" --format json
# Query via a Query object (reference to a [[id:Query]] object in the workspace)
qmdc query ./my-project "#all_services"
# Count objects and edges
qmdc query ./my-project "SELECT COUNT(*) as total FROM objects"
qmdc query ./my-project "SELECT COUNT(*) as edges FROM edges"
The query command automatically:
- Recursively finds every QMDC workspace under the given folder
- Parses all files and loads objects into SQLite
- Extracts graph edges from references between objects
- Runs the SQL query against the database
Available tables:
objects— all objects with__id,__kind,__label,__file,__line,data(JSON)edges— all graph edges withsource_id,target_id,field_name
Workspace API
from qmdc import execute_query, parse_workspace, scan_workspace, workspace_to_json
# Scan files
files = scan_workspace("my-project")
# ['readme.qmd.md', 'api.qmd.md', 'tables.qmd.md']
# Parse the whole workspace; validation errors come with it
result = parse_workspace("my-project")
for error in result.errors:
print(error.type, error.file, error.line, error.message)
# broken_link api.qmd.md 4 Object 'no_such_object' not found
# SQL over the objects and the reference graph
tables = execute_query(workspace_to_json(result), "SELECT __id FROM objects WHERE __kind = 'Table'")
# tables.rows == [['users']]
refs = execute_query(workspace_to_json(result), "SELECT source_id, edge_type FROM edges")
# refs.rows == [['my_project::get_users', 'returns']]
See the format specification for the full spec.
Status
✅ Fully implemented:
- Tokenizer (markdown-it-py)
- Header parser (all variants:
[[id]],[[id:Kind]],[[:Kind]]) - Field parser (primitives: string, number, boolean, null)
- Nested objects (H1–H6)
- Arrays (YAML notation, Markdown lists, object arrays)
- Tables
- Comments (
__comments) - Syntax metadata (
__syntax) - Types metadata (
__types) - YAML multiline syntax (
|) - Rebuild (canonical form)
- YAML blocks
- JSON blocks
- Document title (H1 without
[[id]]) - Lossless round-trip (
__level,__has_explicit_id) - CLI:
parse,rebuild - Workspace: multi-file parsing with reference validation
License
AGPL-3.0-or-later © mikilabs
Metadata
Release files for qmdc 2.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| qmdc-2.0.1-py3-none-win_arm64.whl | Python 3 | none | Windows ARM64 | Details |
| qmdc-2.0.1-py3-none-win_amd64.whl | Python 3 | none | Windows x86-64 | Details |
| qmdc-2.0.1-py3-none-musllinux_1_1_x86_64.whl | Python 3 | none | Linux musl 1.1+ x86-64 | Details |
| qmdc-2.0.1-py3-none-manylinux_2_28_aarch64.whl | Python 3 | none | Linux glibc 2.28+ ARM64 | Details |
| qmdc-2.0.1-py3-none-manylinux_2_17_x86_64.whl | Python 3 | none | Linux glibc 2.17+ x86-64 | Details |
| qmdc-2.0.1-py3-none-macosx_11_0_arm64.whl | Python 3 | none | macOS 11.0+ ARM64 | Details |
| qmdc-2.0.1-py3-none-macosx_10_12_x86_64.whl | Python 3 | none | macOS 10.12+ x86-64 | Details |
Total release size: 31.2 MB
Release files / qmdc-2.0.1-py3-none-win_arm64.whl
| Download URL | qmdc-2.0.1-py3-none-win_arm64.whl |
|---|---|
| Size | 4.1 MB |
| Tags | Python 3 Windows ARM64 |
|
SHA-256 checksum How to use checksums |
31690a827b009a084835255e68955e5818c2f2dfd265316e98c21934bd5e9131
|
|
BLAKE2b-256 checksum How to use checksums |
e6f60e9e90298129658ee7ebed66aad2a76155efcea07652d0e129397031a14b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-win_amd64.whl
| Download URL | qmdc-2.0.1-py3-none-win_amd64.whl |
|---|---|
| Size | 4.5 MB |
| Tags | Python 3 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
32501675977d2663a9188ba5aa5dc82a976dacdcd7556839171080371463f8e9
|
|
BLAKE2b-256 checksum How to use checksums |
d1bc2b3588fadcc29f6ef993c771ecd7410ce359abae969ec7ceb37c8a803ced
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-musllinux_1_1_x86_64.whl
| Download URL | qmdc-2.0.1-py3-none-musllinux_1_1_x86_64.whl |
|---|---|
| Size | 4.6 MB |
| Tags | Linux musl 1.1+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
0ca8728be6a5ecebdf3cc84178749fd023d116e294687c28c1173942693f420c
|
|
BLAKE2b-256 checksum How to use checksums |
d502f6d91174d58d42f6c727649db481ea6ee7cc0bc843df23dbc7c724fd5441
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-manylinux_2_28_aarch64.whl
| Download URL | qmdc-2.0.1-py3-none-manylinux_2_28_aarch64.whl |
|---|---|
| Size | 4.3 MB |
| Tags | Linux glibc 2.28+ ARM64 Python 3 |
|
SHA-256 checksum How to use checksums |
f250dc3e9fac1aab11987d246adc9585e9bb3f81f57f9d793184f8a9ecceadf3
|
|
BLAKE2b-256 checksum How to use checksums |
4c840a9d4dcfa73bcaa7d1805deca7a0a9bec7b62ceb6eb902aa8d5fd55e38f5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-manylinux_2_17_x86_64.whl
| Download URL | qmdc-2.0.1-py3-none-manylinux_2_17_x86_64.whl |
|---|---|
| Size | 4.6 MB |
| Tags | Linux glibc 2.17+ x86-64 Python 3 |
|
SHA-256 checksum How to use checksums |
74b49304dbd6c30bd1f88107223c2dbc4fa397dac49574daf150ec877fdee547
|
|
BLAKE2b-256 checksum How to use checksums |
9c41bc83475c4f9b44df2dd82c0ef8304e09c1978db574bcbf5d82eb7465b97a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-macosx_11_0_arm64.whl
| Download URL | qmdc-2.0.1-py3-none-macosx_11_0_arm64.whl |
|---|---|
| Size | 4.4 MB |
| Tags | Python 3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
0c801dd2d6cafd567fe9698490a32bc74495efa58b2641a859f00614f4c321dc
|
|
BLAKE2b-256 checksum How to use checksums |
3dd4721c01a28bc13ce42fd0474dfca28845f5b0fd0d06be2304e06737b4183f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|
Release files / qmdc-2.0.1-py3-none-macosx_10_12_x86_64.whl
| Download URL | qmdc-2.0.1-py3-none-macosx_10_12_x86_64.whl |
|---|---|
| Size | 4.7 MB |
| Tags | Python 3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
61ed0de25145ff3fb36d83d36ce6e4b445977e47a1fd21faf6918afb2ef0527b
|
|
BLAKE2b-256 checksum How to use checksums |
964336b3a38f67212821eaeb139ae35353b00be2d25a9ff7f3509c877f97da8c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.10
|