Skip to main content

QMDC parser — convert QMD.md to a queryable object graph (JSON) and back

Project description

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.parser 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.workspace import (
    scan_workspace,
    parse_workspace,
    validate_workspace,
    query_workspace,
    get_refs_to,
)

# Scan files
files = scan_workspace("/path/to/workspace")
# ['readme.qmd.md', 'users.qmd.md', 'database/tables.qmd.md']

# Parse the whole workspace
result = parse_workspace("/path/to/workspace")
# WorkspaceResult with objects, index, errors

# Query objects
tables = query_workspace(result, kind="Table")
users = query_workspace(result, object_id="users")

# Find references to an object
refs = get_refs_to(result, "database/tables.qmd.md#users")
# [("api.qmd.md", "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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

qmdc-1.0.5-py3-none-win_arm64.whl (4.1 MB view details)

Uploaded Python 3Windows ARM64

qmdc-1.0.5-py3-none-win_amd64.whl (4.5 MB view details)

Uploaded Python 3Windows x86-64

qmdc-1.0.5-py3-none-musllinux_1_1_x86_64.whl (4.6 MB view details)

Uploaded Python 3musllinux: musl 1.1+ x86-64

qmdc-1.0.5-py3-none-manylinux_2_28_aarch64.whl (4.3 MB view details)

Uploaded Python 3manylinux: glibc 2.28+ ARM64

qmdc-1.0.5-py3-none-manylinux_2_17_x86_64.whl (4.6 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

qmdc-1.0.5-py3-none-macosx_11_0_arm64.whl (4.4 MB view details)

Uploaded Python 3macOS 11.0+ ARM64

qmdc-1.0.5-py3-none-macosx_10_12_x86_64.whl (4.8 MB view details)

Uploaded Python 3macOS 10.12+ x86-64

File details

Details for the file qmdc-1.0.5-py3-none-win_arm64.whl.

File metadata

  • Download URL: qmdc-1.0.5-py3-none-win_arm64.whl
  • Upload date:
  • Size: 4.1 MB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for qmdc-1.0.5-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 42364a8c65fb65ec8b5639ebd6702e8fc3fd4be35f057f07e8c505192bbff068
MD5 589fa7c9a372b3f5ad10d776c0a0a37e
BLAKE2b-256 2c17751acb52a83dddbccc3a046ebc4ffc2d78937a64aafdf35fa5b42ff48ec3

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-win_amd64.whl.

File metadata

  • Download URL: qmdc-1.0.5-py3-none-win_amd64.whl
  • Upload date:
  • Size: 4.5 MB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for qmdc-1.0.5-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 c7b2348a9f15313abd28f5c8d61782130835c1c01ee8f8d85139dced4d860c86
MD5 3cd84358830ee5cb60b41960f3ba95cc
BLAKE2b-256 60ffe27681f97f899e0f0753ffa230a061f72f11bd17649cecb62f5d0678d772

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-musllinux_1_1_x86_64.whl.

File metadata

  • Download URL: qmdc-1.0.5-py3-none-musllinux_1_1_x86_64.whl
  • Upload date:
  • Size: 4.6 MB
  • Tags: Python 3, musllinux: musl 1.1+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for qmdc-1.0.5-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 055f9bc1757003719b8f53ada2c67e3278c1801d8d8f006fab8461e830cf8522
MD5 e9344f1a3dab67dfe6a7c0ce68640463
BLAKE2b-256 bd9e95a35626ae3298d8296db7d97e1105c181b6bbac497582d38104ab8a8f38

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for qmdc-1.0.5-py3-none-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 f404258daebf62a4a1697a2f93367f5ec07fc72d61a854cf1ead367ef1fb41fe
MD5 f99f15100eb13072f46cc5b0fc622fb6
BLAKE2b-256 5b3e1e0e88715694572d65d6a7da34570574615a19e2c9162dd8c8bb05871e5f

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-manylinux_2_17_x86_64.whl.

File metadata

  • Download URL: qmdc-1.0.5-py3-none-manylinux_2_17_x86_64.whl
  • Upload date:
  • Size: 4.6 MB
  • Tags: Python 3, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for qmdc-1.0.5-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e97353b15071bcadf024003234643ca727f022c2544df0d9dd5298f047dbd935
MD5 19f0778d72ec4e76f1a0bed3de2471c1
BLAKE2b-256 ae8ad3a2133722d83753b402d320be30f19905aefd7010bb22b5805d9ce1a52a

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-macosx_11_0_arm64.whl.

File metadata

  • Download URL: qmdc-1.0.5-py3-none-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 4.4 MB
  • Tags: Python 3, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.10

File hashes

Hashes for qmdc-1.0.5-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a1125d434c9ee01bba36865b152c2e2cfe727b08e4ecb4e76120b9a121d9aba3
MD5 0dac8e06f5723138a73a6cf3f0a3bf6b
BLAKE2b-256 067e96fb2ba4f6f655465659ad9a77230c5721ff9e8c2079771430529faa95fe

See more details on using hashes here.

File details

Details for the file qmdc-1.0.5-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for qmdc-1.0.5-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 2682d0945a992ed30b70b2d8d5aef4aed1df358062d8c85817d58fa9c74e1fa7
MD5 90d45542e29827e74f096d0f45e2161a
BLAKE2b-256 5dc2b2504644691d743db5ee0de4466c4023da8b3b1d8a3f0a076a9a20ac6a59

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page