Skip to main content

Parse Markdown model definitions into RDF, diagrams, and docs.

Project description


SPDX-FileCopyrightText: 2026 Arthit Suriyawongkul SPDX-FileType: DOCUMENTATION SPDX-License-Identifier: CC0-1.0

SpecMD

PyPI - Version GitHub License

Convert Markdown model definitions to RDF ontologies and specification documents.

Contents

Functionality

SpecMD reads and validates the complete model directory before generating output. It can then generate one or more of the following outputs:

Format Description
jsondump JSON dump of the parsed model
mkdocs MkDocs source files for website generation
plantuml PlantUML diagram source
rdf OWL+SHACL ontology and JSON-LD context
tex TeX source for printable specification
singlefile Single Markdown file (suitable for conversion to Word, PDF, etc.)
webpages Per-IRI web pages (not yet implemented)

Installation

pip install specmd

Prerequisites

All Python dependencies are installed automatically with pip install specmd. External tools required for specific formats:

Format External prerequisite
tex pandoc -- used to convert Markdown fragments to LaTeX
All others None

Usage

SpecMD uses subcommands:

specmd <command> [options]

Commands:
  generate (gen)   Generate output artefacts from a model directory
  validate         Validate a model directory or a single .md file
  migrate          Convert spec-parser format to SpecMD format
  export           Export a SpecMD model to another format

Validate

Check raw YAML syntax of every .md file, then fully parse the model:

specmd validate path/to/model

Validate a single file (raw YAML syntax check only):

specmd validate path/to/file.md

Use --strict to exit with a non-zero code when raw YAML issues are found (without --strict they are reported as warnings but do not fail the command):

specmd validate --strict path/to/model

The validator runs two passes on a directory:

  1. Raw YAML check — each ## Entries and ## Properties section is parsed with yaml.safe_load to catch characters and constructs that cause parse errors in strict YAML consumers (e.g. a value starting with [ or {, or a bare : inside a plain scalar).
  2. Full model parse — the complete model is loaded and cross-referenced, reporting semantic errors (unknown classes, missing metadata, etc.).

A summary line is always printed: N file(s) checked, M file(s) with issues.

Generate

Generate all output formats into subdirectories under ./out/:

specmd generate path/to/model --output ./out

Generate specific formats only:

specmd generate path/to/model --formats rdf,mkdocs --output ./out

Override the output directory for a single format:

specmd generate path/to/model --output ./out --rdf-dir ./ontology

Available formats: jsondump, mkdocs, plantuml, rdf, tex, singlefile, webpages.

Migrate

Convert a model written in the spec-parser format to SpecMD format:

specmd migrate path/to/old-model --output path/to/new-model

Export

Export a SpecMD model back to the spec-parser format:

specmd export path/to/model --output path/to/exported --format legacy

Common options

Option Commands Description
-o/--output DIR generate, migrate, export Output directory
-f/--force generate, migrate, export Overwrite existing output
--strict validate Exit non-zero on raw YAML warnings
-q/--quiet all Warnings and errors only
-v/--verbose all Debug output
-V/--version top-level Show version and exit

Full help:

specmd --help
specmd generate --help

Model configuration

An optional specmd.yml file at the model root controls parsing and generation.

Key settings:

license: CC0-1.0           # SPDX license ID for generated output
base-uri: https://example.org/rdf/terms/  # ontology base URI
namespace-order: [Core]    # namespace processing order

ontology:                  # OWL ontology metadata
  preferred-namespace-prefix: myns
  label: My Model Ontology
  creator: My Organisation
  license-uri: https://example.org/licenses/my-license/

vocabulary:                # vocabulary / relationship defaults
  default-from: Element    # default vocab entry source class
  default-to: Element      # default vocab entry target class
  default-relationship-class: Relationship

rdf:
  filename: my-model       # output filename (no extension)

See docs/format.md for the full reference.

spec-parser compatibility

A main.py compatibility shim is provided for existing CI/scripts that invoke the spdx/spec-parser CLI.

It accepts spec-parser's original command-line arguments, internally runs specmd migrate on the input, then specmd generate or specmd validate.

Drop-in from a workflow perspective: replacing spec-parser with specmd requires only a one-line change in CI (see below), and SpecMD accepts the original Markdown format as input via automatic migration.

Output will differ: the generated RDF/OWL/SHACL and MkDocs Markdown are not byte-for-byte identical to spec-parser output. SpecMD incorporates correctness fixes and improvements to the generated artefacts (see docs/design.md). Downstream consumers of the RDF or MkDocs output should expect and review these differences.

Simply replace python spec-parser/main.py with python specmd/main.py in existing workflows.

Or, in a GitHub workflow that checks out the repository, only the repository name needs to change - the checkout path, the pip install command, and every main.py option stay the same:

From:

      - uses: actions/checkout@6
        with:
          repository: spdx/spec-parser
          path: spec-parser
      - run: |
          pip install -r spec-parser/requirements.txt
          python3 spec-parser/main.py --force --generate-mkdocs --output-mkdocs spdx-spec/docs/model spdx-3-model/model

To:

      - uses: actions/checkout@6
        with:
          repository: bact/specmd  #changed
          path: spec-parser
      - run: |
          pip install -r spec-parser/requirements.txt
          python3 spec-parser/main.py --force --generate-mkdocs --output-mkdocs spdx-spec/docs/model spdx-3-model/model

Testing

Run the standard test suite:

pip install pytest
pytest

shacl2code compatibility test

tests/test_shacl2code.py verifies that SpecMD RDF output produces identical JSON schema to upstream spec-parser when both are fed through shacl2code. This test is skipped automatically when either dependency is absent, so it will not block a plain pytest run.

To run it, both tools must be reachable:

# 1. Install shacl2code
pip install shacl2code

# 2. Point PYTHONPATH at your spec-parser checkout
#    (spec-parser cannot be pip-installed)
PYTHONPATH=/path/to/spec-parser pytest tests/test_shacl2code.py -v

Example with a sibling checkout:

PYTHONPATH=../spec-parser pytest tests/test_shacl2code.py -v

Expected output:

tests/test_shacl2code.py::TestShacl2codeCompatibility::test_jsonschema_identical PASSED

Design notes

SpecMD is built on the design of spdx/spec-parser, targeting compatibility with existing workflows. The Markdown input format is nearly identical; key differences include standard YAML front matter, camelCase metadata keys, a structured vocabulary entry format, and structured deprecation fields.

The RDF/OWL/SHACL output makes a set of deliberate design decisions around JSON-LD context correctness, SHACL shape simplification, OWL version metadata, and abstract class disjointness. The generated output is not byte-for-byte identical to spec-parser output — existing SHACL validation results are preserved, but OWL reasoning consumers should review the differences before updating.

Full details: docs/design.md.

This project is not an official SPDX project.

Project details


Download files

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

Source Distribution

specmd-0.2.0.tar.gz (100.4 kB view details)

Uploaded Source

Built Distribution

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

specmd-0.2.0-py3-none-any.whl (65.6 kB view details)

Uploaded Python 3

File details

Details for the file specmd-0.2.0.tar.gz.

File metadata

  • Download URL: specmd-0.2.0.tar.gz
  • Upload date:
  • Size: 100.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for specmd-0.2.0.tar.gz
Algorithm Hash digest
SHA256 517af09b34f438059b1c30a01c255f400c035f8d2038cb183085721e6ca86d3e
MD5 91cd591c081a1ecc00329b135b834616
BLAKE2b-256 744afa34b11927f2781d67aa3c4ae8c620b97c4de8963a13e82e6431129c2335

See more details on using hashes here.

Provenance

The following attestation bundles were made for specmd-0.2.0.tar.gz:

Publisher: pypi-publish.yml on bact/specmd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file specmd-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: specmd-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 65.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for specmd-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 50cee123d252271ceffb533e8e743d6f61bab20b7da10aced64ca4f0c7383b5e
MD5 09812bd8af3584e6cd9323e14e2b5474
BLAKE2b-256 86d2e9a0aa8f8c103bc1c33921986bc92cfd4706a186c499f298e74012e42f15

See more details on using hashes here.

Provenance

The following attestation bundles were made for specmd-0.2.0-py3-none-any.whl:

Publisher: pypi-publish.yml on bact/specmd

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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