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