@jasonbelmonti/markdown-engine
v3.0.0
Published
Deterministic Markdown parsing and validation engine package.
Maintainers
Readme
@jasonbelmonti/markdown-engine
Deterministic Markdown parsing and validation engine package for downstream profile and runtime work.
Package release state:
- package name:
@jasonbelmonti/markdown-engine - package metadata version:
3.0.0 - published npm versions before this release:
0.1.0,1.0.0,2.0.0 - npm release target:
3.0.0onlatest - website: https://jasonbelmonti.github.io/markdown-engine/
- release focus: Conditional V2 explicit validation-profile syntax while
retaining the existing
documentVersion: "1.0.0"rich IR contract as the default API and CLI document shape - maintainer documentation map: docs/README.md
- design reference: Markdown Engine 1.0 Rich IR design
Scope
@jasonbelmonti/markdown-engine owns the deterministic engine boundary:
- parse GFM Markdown and YAML frontmatter
- normalize parser output into engine-owned IR
- validate deterministic declarative rules
- emit structured diagnostics
- serialize public results with stable JSON key ordering
Out of scope for this package: profile compiler behavior, runtime lenses, MCP transport, agent adapters, semantic or LLM evaluation, arbitrary rule plugins, network services, persistence, and raw parser AST as a public contract.
Public API
The package root exports:
parse(markdown, options?)normalize(parsed, options?)validate(document, config?, options?)serialize(result, options?)documentQueriesvalidateAnnotations(document, annotations)parseValidationProfile(input, options?)validateWithProfile(document, profile, options?)
Example:
import {
normalize,
parse,
serialize,
validate,
} from "@jasonbelmonti/markdown-engine";
const markdown = `---
title: Mission Brief
owner: docs
---
# Mission Brief
\`\`\`ts
const ready = true;
\`\`\`
`;
const parseResult = parse(markdown, { path: "mission.md" });
const normalizeResult = normalize(parseResult.parsed);
const validationResult = validate(normalizeResult.document, {
rules: {
"frontmatter.required": { fields: ["title", "owner"] },
"headings.required": { headings: ["Mission Brief"] },
"codeFences.languages": {
allowed: ["ts"],
requireLanguage: true,
},
},
});
console.log(validationResult.valid);
console.log(serialize(validationResult, { pretty: true }));Package 3.0 keeps the serialized document contract at
documentVersion: "1.0.0" and makes that rich IR path the default for
normalize(parsed). Callers may still pass
normalize(parsed, { documentVersion: "1.0.0" }) explicitly. That path adds
deterministic targets, structural views, source slices, query helpers, and
caller-owned annotation target validation. The retained 0.1.0-compatible
document path remains selectable as documentVersion: "0.0.0" and
serialization gates can require it with compatibilityMode: "legacy-0.1".
CLI
The package includes a minimal local CLI for experimenting with one Markdown
file at a time. The default command runs parse and normalization, then writes
the normalized result as pretty JSON. The validate subcommand runs one
declarative validation profile against one Markdown file and writes pretty JSON.
From the repository or package root after building, run:
npm run build
node dist/cli/index.js --file fixtures/declarative-validation/examples/operational-spec/pass.mdThe package binary accepts --file or --path as aliases for a single file.
For an npm install in the current project, point at the bundled examples through
node_modules/@jasonbelmonti/markdown-engine:
markdown-engine --path node_modules/@jasonbelmonti/markdown-engine/fixtures/declarative-validation/examples/operational-spec/pass.mdBy default, CLI output uses the 1.0 rich IR contract:
{
"document": {
"version": "1.0.0",
"target": { "kind": "node", "nodeType": "document" },
"sections": []
}
}Use --document-version 0.0.0 when a caller still needs the legacy
0.1.0-compatible document shape without rich derived views:
markdown-engine --document-version 0.0.0 --file node_modules/@jasonbelmonti/markdown-engine/fixtures/declarative-validation/examples/operational-spec/pass.mdThe selector accepts spaced or assignment-form syntax, such as
--document-version 0.0.0 or --document-version=0.0.0. Supported selector
values are 1.0.0 and 0.0.0. Missing, invalid, or repeated
--document-version selectors exit with code 2 and usage text; an empty
assignment-form selector is treated as missing. Directory traversal is not
supported by this CLI slice.
Declarative validation uses the 1.0 document contract and does not accept
--document-version:
markdown-engine validate --file node_modules/@jasonbelmonti/markdown-engine/fixtures/declarative-validation/examples/operational-spec/pass.md --profile node_modules/@jasonbelmonti/markdown-engine/fixtures/declarative-validation/examples/operational-spec/profile.yaml--format json is accepted for validation, is the default, and is the only
supported format. The validation command reads and checks the profile before
reading the Markdown file. Profile parse/config/compile failures exit with code
1 and emit JSON with stage: "profile", empty ruleResults, no profile,
and no evidence. Markdown read errors and usage errors exit with code 2.
Successful validation exits with code 0; validation or normalization error
diagnostics exit with code 1. Validation JSON includes profile,
ruleResults, diagnostics, and evidence.
Declarative validation compatibility is syntax-versioned. Existing v1 profiles remain on the v1 result and evidence shape by keeping:
syntaxVersion: markdown-engine.validation@v1Conditional V2 behavior is selected only by an explicit v2 profile:
syntaxVersion: markdown-engine.validation@v2
rules:
- id: release.docs
anyOf:
- label: release-section
select:
target: section
title: Release
assert:
exists: true
- label: changelog-link
select:
target: link
text: changelog
assert:
exists: trueCLI validation output uses profile.syntaxVersion as the v1/v2 discriminator.
V1 rule results keep the existing flat ruleId, passed, and diagnostics
fields. V2 rule results add status and evaluation; v2 profile metadata adds
evaluatedRuleCount and skippedRuleCount when the profile explicitly opts into
markdown-engine.validation@v2.
Reader-facing declarative validation examples live under
fixtures/declarative-validation/examples/**. From the repository or package
root after building, run one passing and one intentionally failing example with:
node dist/cli/index.js validate --file fixtures/declarative-validation/examples/operational-spec/pass.md --profile fixtures/declarative-validation/examples/operational-spec/profile.yaml
node dist/cli/index.js validate --file fixtures/declarative-validation/examples/operational-spec/fail.md --profile fixtures/declarative-validation/examples/operational-spec/profile.yamlThe passing example exits 0; the failing example exits 1 and prints JSON
diagnostics for review.
Package 3.0 keeps the 2.0 API normalization default: callers that invoke
normalize(parsed) receive the rich IR 1.0.0 document shape. Consumers that
still need the legacy 0.0.0 shape should consume the rich IR fields
(target, sections, textSpans, tables, lists, and links) or pin
normalize(parsed, { documentVersion: "0.0.0" }) until they are ready. The CLI
continues to default to the rich IR document contract and keeps
--document-version 0.0.0 for explicit legacy output.
Package and contract references:
- Consumer website
- Maintainer documentation map
- Public API contract
- Declarative validation contract
- Frontmatter contract
- Markdown Engine 1.0 Rich IR design
- Testing and snapshot operations
- Changelog
- Security policy
Validation
Run focused contract documentation gates from the repository root:
npm run docs:rich-ir-contract
npm run docs:declarative-validation-contract
npm run audit:declarative-validation-boundaryRun full release-readiness and publication dry-run gates only when preparing a release, tag, package artifact, or publication decision:
npm run release:verify
npm pack --dry-run
npm publish --dry-run --access publicThe full maintainer and evidence index lives in docs/README.md. The focused contract documentation gates currently check these evidence records:
- Rich IR contract documentation gate
- Declarative validation contract review
- Declarative validation boundary audit
Snapshot baseline updates are operational changes, not routine test-output
cleanup. Use the testing and snapshot operations guide before
updating files under snapshots/**.
