Expand description
The Rust engine for markdown-contract, the twin of the TypeScript package
@osdlc/markdown-contract. The shared corpus in packages/ts/markdown-contract/corpus/
pins the two to the same findings for every YAML-expressible fixture: the same count
and ids in order, and the level, line and hint where a fixture records them
(tests/corpus.rs).
validate() runs every check in one pass: the projection, the structure plane, the
content plane (frontmatter schema; table, list, code and maxWords leaves), the
text constraints and the document rules. Contracts come from the builders
(Contract, section, rule and the rest) or the YAML loader
(load_contract); run_corpus routes documents to contracts by glob.
use markdown_contract::{load_contract, validate};
let contract = load_contract("\
mcVersion: 2
kind: contract
body:
sections:
- section: Context
")?;
let findings = validate("## Notes\n", &contract, "note.md");
assert_eq!(findings[0].id, "structure/section-missing");The core takes strings and does no I/O, so it builds for wasm32-unknown-unknown.
Reading files lives behind the native feature (on by default; build with
default-features = false for wasm32).
A text rule’s regex and a frontmatter string’s pattern use the regex crate’s
dialect, not JavaScript’s: no lookaround or backreferences, and \w, \d and \b
are Unicode-aware. The loader rejects a source the crate cannot compile. The README
lists the other differences from the TS package.
select picks part of a note the way an Obsidian link fragment does
(#Heading, #Parent#Child, #^block-id), as a byte range or as text;
DocTree has the same as methods, and every SectionNode and
BlockNode carries its byte range in DocTree::body.
This file is a barrel only: it re-exports, it holds no logic.
Modules§
- select
- Selecting part of a note the way an Obsidian link fragment does:
[[Note#Heading]],[[Note#Parent#Child]]and[[Note#^block-id]].
Structs§
- Code
Config - A
code(...)leaf’s content config — the TSCodeConfig. - Contract
- A compiled contract for one markdown class: frontmatter schema, body grammar, and doc-scoped rules.
- Corpus
Config - The directory → contract config: a flat ORDERED list of rules. Rule order is significant — a file is validated against the FIRST rule it matches.
- Corpus
Rule - One routing rule: the files that match
includeand notexcludeare checked againstcontract. - Ctx
- The rule author’s finding factory — the engine fills
pathand the id’s default level. - DocTree
- The projected document: the frontmatter block (when present), the verbatim body
after it, and the synthetic root whose
sectionsare the top-level body sections and whosenameis the leading-H1 title. - Edit
Range - A start–end source range for a
TextEdit. - Finding
- One validation finding — the unit of the interchange format.
- Finding
Spec - The input to
Ctx::finding— id and message required, level/pos/hint optional. - Fix
- The
fixslot on a finding: a description, optionally with a concrete edit. - Frontmatter
- The frontmatter block.
datais the parsed YAML in the JSON value shape the TSyamlpackage’stoJS()gives, orNonewhen the YAML does not parse.posis the opening---fence (line 1). The frontmatter plane finds the line of a key, and the error of YAML that does not parse, by readingraw. - Frontmatter
Spec - The frontmatter plane’s compiled schema — an object
Schemathe plane runs over the parsed frontmatter data (the TS contract’sfrontmatterZod object). - Frontmatter
Split - The result of
split_frontmatter. - GapSpec
- A
gap()window admitting unknown sections, optionally bounded. - Glob
Error - A glob set that failed to compile — a config error (exit-code-2 territory for the hosting layer).
- Leaf
Spec - A content leaf: the structural kind-gate (checked by the structure plane) plus the
typed
configthe content plane interprets. - Level
Opts - A level’s options; defaults mirror the TS engine (
order: "none",allowUnknown: true). - List
Config - A
list(...)leaf’s content config, the TSListConfig. - List
Item - One list item: flattened text, task-list checkbox state (when present), source position.
- OneOf
Spec - A
oneOfslot: exactly one of several headings must appear. - Registry
- The id → default-level registry, seeded with every plane’s defaults.
- RunOptions
- An optional global pre-filter, applied before rule matching (AND-narrowing): a file
is considered only if it matches at least one
includeglob (when any are given) and noexcludeglob. - RunOutcome
- The run outcome: aggregated findings (each already deterministically sorted within its file, stamped with its file path), the exit code, and the run counts.
- RunStats
- Per-run counts returned alongside the findings. Always satisfies
files_matched == matched_by_rule.iter().sum()andfiles_unmatched == files_scanned - files_matched. - Section
Node - A heading-delimited section: exact heading text, TRUE heading depth (a skipped level is preserved, not synthesized), heading position, nested subsections, heading-direct blocks (no hoisting), and section-level anchors.
- Section
Opts - Per-section options — the TS
SectionOpts. - Section
Seq - The body grammar of one level — the output of
sections. - Section
Spec - A declared section slot: the heading and its aliases, plus options.
- Source
Pos - A single source point. 1-based
line;col(1-based) rides along when known and is omitted from JSON when absent — matching the TSSourcePos. - Table
Config - A
table(...)leaf’s content config — the TSTableConfig. - Text
Edit - A machine-applicable repair an external tool could apply. Provisional — a
Finding.fixonly describes a remedy; this engine never edits documents. - Text
Match Spec - One match spec — the closed text-match vocabulary. Exactly
one of
pattern(a literal substring) orregex(a regex source) supplies the needle;normalize/ignore_casetune matching;min/maxbound the count;idpins identity;note/levelshape the finding. - Text
Rule Spec - The document-scoped options for
text_rule—requires/forbidslists, each a set of independent whole-document checks. - Vault
Ref - A recognized
[[wikilink]]or![[transclusion]]extracted from flattened text.
Enums§
- Block
Kind - The block kinds the structure plane’s kind-gate distinguishes.
- Block
Node - A flattened content block directly under a section heading.
- Const
Value - A literal value for
const(YAML scalars only). - Declarative
Error - A declarative document that could not be compiled into a contract / config.
- Every
Item - A list leaf’s per-item check — the checkbox gate, or a schema over each item’s text.
- Extra
Columns - Whether undeclared table columns are tolerated or reported (
content/table/column-extra). - Finding
Level - A finding’s severity. Each id has a default level in the registry; a rule or a text
constraint’s
level:can set another. - Leaf
Config - The content checks a leaf carries: what the TS builders put on
LeafSpec.config, with cell and item schemas compiled. - Native
RunError - What a directory run can fail on.
- Order
orderandallow_unknownare independent knobs over a level’s content model.- Schema
- One compiled schema node. Bounds are
f64because JSON Schema bounds are numbers. - Section
Content - A section’s content declaration: a single leaf, or named leaves bound by
^anchor. - Spec
- One element of a level’s ordered content model — the output of the builder functions.
- String
Format - The
formatnames, each replicating zod v4’s validator for that format. - Vault
RefKind - Whether a reference is a link or a transclusion.
Traits§
- DocRule
- A doc-scoped named rule, run once over the whole projected tree.
- Rule
- A node-scoped named rule, run against each declared, present section that carries it.
Functions§
- compile_
contract_ object - Build a
Contractfrom a{ description?, frontmatter?, body? }mapping with no envelope, as an inline config contract is written. AnmcVersionother than 2 and any other key are rejected. - doc_
rule - A doc-scoped named rule from a closure — the TS
docRule(id, fn). - extract_
vault_ refs - Every
[[wikilink]]and![[transclusion]]in already-flattened text, in document order. The alias is everything after the first|; the fragment is everything after the first#in what is left, so[[Note|alias#Part]]has the aliasalias#Partand no fragment. The text between the brackets cannot contain[. - forbids
- Forbid each listed phrase from appearing in the bound section’s subtree text — a
node-local
Rule. Each entry emits atext/forbidsfinding at the offending line for every hit (ortext/countat the heading when a positivemaxcap is exceeded). - gap
- An unbounded gap window admitting unknown sections.
- gap_
bounds - A bounded gap window —
gap({ min, max }). - load_
config - Compile a declarative YAML config (text) into a
CorpusConfig.resolverreads a referenced.yaml/.ymlcontract file’s text (the fs seam). - load_
config_ file - Read a YAML config file and compile it. Contract refs resolve relative to the
config file’s directory, which is made absolute without resolving symlinks, as
Node’s
path.resolvedoes. - load_
contract - Compile a declarative YAML contract (text) into a runtime
Contract. - load_
contract_ file - Read a
*.contract.yamlfile and compile it into aContract. - one_of
- One required slot with several interchangeable spellings —
oneOf([...]). - one_
of_ with - A
oneOfslot with options. - optional
- Mark a spec optional —
optional(section("Appendix")). - parse_
document - Parse raw markdown (frontmatter + body) into the positioned projection. Positions in
the returned tree are absolute document lines, matching the TS engine. The
frontmatter’s
datamirrors the TSyamlpackage’stoJS()value shape; it isNonewhen the YAML does not parse. - requires
- Require each listed phrase to be PRESENT in the bound section’s subtree text — a
node-local
Rulefor a section’srulesslot. Each entry emits its owntext/requiresfinding at the section heading when its phrase is absent (ortext/countwhen amin/maxbound is violated). - rule
- A per-node named rule from a closure — the TS
rule(id, fn). - run_
corpus - Run a config across a file set and aggregate findings.
- run_
corpus_ dir - Walk
rootand run the config over its files, reading only the files a rule routes. Invalid UTF-8 is replaced with U+FFFD, as Node’sutf8read does. - section
- A required section with a single exact heading —
section("Overview"). - section_
with - A section with options —
section("Summary", { anchor: "summary", … }). - sections
- A level’s ordered content model —
sections(opts, [ … ]). - split_
frontmatter - Pure, byte-exact frontmatter/body split — no YAML parse, no projection. Same
recognizer as the TS
splitFrontmatter: the opening---must be the very first line (after a byte-order mark, which is skipped), the block must be closed by a---line (else the whole doc is body), andbodybegins after exactly one line terminator (CRLF or LF) past the closing fence. - text_
rule - Attach required / forbidden phrase checks to the WHOLE document — a cross-plane
DocRulefor a contract’srulesslot. Arequiresmiss is document-level (no position); eachforbidshit anchors at the exact offending source line. - validate
- The string-in convenience: parse (frontmatter split + projection), then validate every plane in the TS orchestration order.
- validate_
tree - Validate a pre-parsed tree against a contract: outline scan, structure plane (with node-local rules), content plane (frontmatter schema + content leaves), doc-scoped rules, deterministic sort.
- walk_
dir - Every file under
root, as paths relative torootwith/separators. Directory entries are sorted by name (in UTF-16 order, as JS compares strings) before recursion, so the order matches the TSwalkSync..gitandnode_modulesare skipped.
Type Aliases§
- Contract
Resolver - Resolves a contract-file ref (a
.yaml/.ymlpath, possibly relative) to its YAML text.