Skip to main content

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 with source_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)

Table of built distributions (wheels) for qmdc 2.0.1
File
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

Release history Release notifications | RSS feed

This release

2.0.1 This release

7 release files

2.0.0

7 release files

1.0.6

7 release files

1.0.5

7 release files

1.0.3

7 release files

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