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.0

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.0
File
qmdc-2.0.0-py3-none-win_arm64.whl Python 3 none Windows ARM64 Details
qmdc-2.0.0-py3-none-win_amd64.whl Python 3 none Windows x86-64 Details
qmdc-2.0.0-py3-none-musllinux_1_1_x86_64.whl Python 3 none Linux musl 1.1+ x86-64 Details
qmdc-2.0.0-py3-none-manylinux_2_28_aarch64.whl Python 3 none Linux glibc 2.28+ ARM64 Details
qmdc-2.0.0-py3-none-manylinux_2_17_x86_64.whl Python 3 none Linux glibc 2.17+ x86-64 Details
qmdc-2.0.0-py3-none-macosx_11_0_arm64.whl Python 3 none macOS 11.0+ ARM64 Details
qmdc-2.0.0-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.0-py3-none-win_arm64.whl

Download URL qmdc-2.0.0-py3-none-win_arm64.whl
Size 4.1 MB
Tags Python 3 Windows ARM64
SHA-256 checksum
How to use checksums
63dfbc4bd9b67739ed2b0cf2de94736b6eb80aafc11af6e26d233b4bc00b3f40
BLAKE2b-256 checksum
How to use checksums
967597cdf6d3241b55bb0718421299b7e04fb480c8202789ec9aee5f5a411f47
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.0-py3-none-win_amd64.whl

Download URL qmdc-2.0.0-py3-none-win_amd64.whl
Size 4.5 MB
Tags Python 3 Windows x86-64
SHA-256 checksum
How to use checksums
e95959a28e5d504e218a18bc5071436672d3d94e06d98c30489691e6b5802685
BLAKE2b-256 checksum
How to use checksums
d29095437855cfbb41265e989159ecf80e70944ae27855a4bc60d3520acca6f4
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.0-py3-none-musllinux_1_1_x86_64.whl

Download URL qmdc-2.0.0-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
f93d9be3f49d74b899b35c906d5c9b26fc52b1e566cbdae3ca54f65d149cef84
BLAKE2b-256 checksum
How to use checksums
aa8e421680488c91f816c4452a44b05a709173482ea76504b36b7b14b0cebd47
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.0-py3-none-manylinux_2_28_aarch64.whl

Download URL qmdc-2.0.0-py3-none-manylinux_2_28_aarch64.whl
Size 4.2 MB
Tags Linux glibc 2.28+ ARM64 Python 3
SHA-256 checksum
How to use checksums
152e4b533449cd192f5b4023f5fc833ca8116a508c03fe56d2de3039411e8408
BLAKE2b-256 checksum
How to use checksums
0d583c557caf40a169f01e04eaa6b21ec0a045e8af612f0c11938ef34a1e125a
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.0-py3-none-manylinux_2_17_x86_64.whl

Download URL qmdc-2.0.0-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
9f6d60ffea351143d19908f67e7b08f70cc138b029830fc9ffbcf0e31fb5bd32
BLAKE2b-256 checksum
How to use checksums
2b3dbe30a928927be5fa9909f5afa1605a9fc9e56bf986ee39b9693a17b6c606
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.0-py3-none-macosx_11_0_arm64.whl

Download URL qmdc-2.0.0-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
5a67814b478c4b68b457fd3854ec2751171492ec859ee10f468c3d137acc895f
BLAKE2b-256 checksum
How to use checksums
9320404639587018e9bad40390327ff4e1f58141ac10dfd0085253503501c5cb
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.0-py3-none-macosx_10_12_x86_64.whl

Download URL qmdc-2.0.0-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
063fe2270ff5ba7c2de6581d80b85611c3d412fb6b1966ede75050676c2d31ef
BLAKE2b-256 checksum
How to use checksums
ec8c8a5346c9b27b8736b8c7ff57055554220df57c7785dd2a8c698e859e3efa
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

2.0.1

7 release files

This release

2.0.0 This release

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