@jasonbelmonti/markdown-engine 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +24 -1
- package/README.md +75 -26
- package/SECURITY.md +5 -3
- package/dist/api/annotation-source-range.d.ts +7 -0
- package/dist/api/annotation-source-range.d.ts.map +1 -0
- package/dist/api/annotation-source-range.js +103 -0
- package/dist/api/annotation-source-range.js.map +1 -0
- package/dist/api/annotation-target-candidate.d.ts +10 -0
- package/dist/api/annotation-target-candidate.d.ts.map +1 -0
- package/dist/api/annotation-target-candidate.js +14 -0
- package/dist/api/annotation-target-candidate.js.map +1 -0
- package/dist/api/annotation-target-cloning.d.ts +5 -0
- package/dist/api/annotation-target-cloning.d.ts.map +1 -0
- package/dist/api/annotation-target-cloning.js +122 -0
- package/dist/api/annotation-target-cloning.js.map +1 -0
- package/dist/api/annotation-target-diagnostics.d.ts +8 -0
- package/dist/api/annotation-target-diagnostics.d.ts.map +1 -0
- package/dist/api/annotation-target-diagnostics.js +57 -0
- package/dist/api/annotation-target-diagnostics.js.map +1 -0
- package/dist/api/annotation-target-validation.d.ts +2 -2
- package/dist/api/annotation-target-validation.d.ts.map +1 -1
- package/dist/api/annotation-target-validation.js +5 -272
- package/dist/api/annotation-target-validation.js.map +1 -1
- package/dist/api/contracts.d.ts +2 -1
- package/dist/api/contracts.d.ts.map +1 -1
- package/dist/api/contracts.js +1 -0
- package/dist/api/contracts.js.map +1 -1
- package/dist/api/declarative-validation.d.ts +13 -0
- package/dist/api/declarative-validation.d.ts.map +1 -0
- package/dist/api/declarative-validation.js +63 -0
- package/dist/api/declarative-validation.js.map +1 -0
- package/dist/api/document-queries.d.ts.map +1 -1
- package/dist/api/document-queries.js +74 -3
- package/dist/api/document-queries.js.map +1 -1
- package/dist/api/document.d.ts +44 -0
- package/dist/api/document.d.ts.map +1 -1
- package/dist/api/engine-node-attributes.d.ts +15 -0
- package/dist/api/engine-node-attributes.d.ts.map +1 -0
- package/dist/api/engine-node-attributes.js +99 -0
- package/dist/api/engine-node-attributes.js.map +1 -0
- package/dist/api/normalize.d.ts.map +1 -1
- package/dist/api/normalize.js +22 -1
- package/dist/api/normalize.js.map +1 -1
- package/dist/api/serialize.js +2 -14
- package/dist/api/serialize.js.map +1 -1
- package/dist/cli/args.d.ts +6 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +33 -25
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/declarative-validation.d.ts +18 -0
- package/dist/cli/declarative-validation.d.ts.map +1 -0
- package/dist/cli/declarative-validation.js +131 -0
- package/dist/cli/declarative-validation.js.map +1 -0
- package/dist/cli/files.d.ts +1 -0
- package/dist/cli/files.d.ts.map +1 -1
- package/dist/cli/files.js +3 -0
- package/dist/cli/files.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +18 -3
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/validate-args.d.ts +18 -0
- package/dist/cli/validate-args.d.ts.map +1 -0
- package/dist/cli/validate-args.js +131 -0
- package/dist/cli/validate-args.js.map +1 -0
- package/dist/declarative-validation/assertions/context.d.ts +8 -0
- package/dist/declarative-validation/assertions/context.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/context.js +2 -0
- package/dist/declarative-validation/assertions/context.js.map +1 -0
- package/dist/declarative-validation/assertions/diagnostics.d.ts +22 -0
- package/dist/declarative-validation/assertions/diagnostics.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/diagnostics.js +71 -0
- package/dist/declarative-validation/assertions/diagnostics.js.map +1 -0
- package/dist/declarative-validation/assertions/document-text-offsets.d.ts +3 -0
- package/dist/declarative-validation/assertions/document-text-offsets.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/document-text-offsets.js +32 -0
- package/dist/declarative-validation/assertions/document-text-offsets.js.map +1 -0
- package/dist/declarative-validation/assertions/evaluator.d.ts +5 -0
- package/dist/declarative-validation/assertions/evaluator.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/evaluator.js +46 -0
- package/dist/declarative-validation/assertions/evaluator.js.map +1 -0
- package/dist/declarative-validation/assertions/exists.d.ts +4 -0
- package/dist/declarative-validation/assertions/exists.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/exists.js +8 -0
- package/dist/declarative-validation/assertions/exists.js.map +1 -0
- package/dist/declarative-validation/assertions/frontmatter-required.d.ts +9 -0
- package/dist/declarative-validation/assertions/frontmatter-required.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/frontmatter-required.js +15 -0
- package/dist/declarative-validation/assertions/frontmatter-required.js.map +1 -0
- package/dist/declarative-validation/assertions/id-targets.d.ts +29 -0
- package/dist/declarative-validation/assertions/id-targets.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/id-targets.js +428 -0
- package/dist/declarative-validation/assertions/id-targets.js.map +1 -0
- package/dist/declarative-validation/assertions/id-tokens.d.ts +15 -0
- package/dist/declarative-validation/assertions/id-tokens.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/id-tokens.js +27 -0
- package/dist/declarative-validation/assertions/id-tokens.js.map +1 -0
- package/dist/declarative-validation/assertions/ids.d.ts +9 -0
- package/dist/declarative-validation/assertions/ids.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/ids.js +42 -0
- package/dist/declarative-validation/assertions/ids.js.map +1 -0
- package/dist/declarative-validation/assertions/index.d.ts +3 -0
- package/dist/declarative-validation/assertions/index.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/index.js +3 -0
- package/dist/declarative-validation/assertions/index.js.map +1 -0
- package/dist/declarative-validation/assertions/literal-text.d.ts +2 -0
- package/dist/declarative-validation/assertions/literal-text.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/literal-text.js +14 -0
- package/dist/declarative-validation/assertions/literal-text.js.map +1 -0
- package/dist/declarative-validation/assertions/normalized-source-ranges.d.ts +3 -0
- package/dist/declarative-validation/assertions/normalized-source-ranges.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/normalized-source-ranges.js +105 -0
- package/dist/declarative-validation/assertions/normalized-source-ranges.js.map +1 -0
- package/dist/declarative-validation/assertions/ordering.d.ts +6 -0
- package/dist/declarative-validation/assertions/ordering.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/ordering.js +71 -0
- package/dist/declarative-validation/assertions/ordering.js.map +1 -0
- package/dist/declarative-validation/assertions/references.d.ts +9 -0
- package/dist/declarative-validation/assertions/references.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/references.js +354 -0
- package/dist/declarative-validation/assertions/references.js.map +1 -0
- package/dist/declarative-validation/assertions/sections-required.d.ts +9 -0
- package/dist/declarative-validation/assertions/sections-required.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/sections-required.js +49 -0
- package/dist/declarative-validation/assertions/sections-required.js.map +1 -0
- package/dist/declarative-validation/assertions/table-columns-required.d.ts +9 -0
- package/dist/declarative-validation/assertions/table-columns-required.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/table-columns-required.js +31 -0
- package/dist/declarative-validation/assertions/table-columns-required.js.map +1 -0
- package/dist/declarative-validation/assertions/text-length.d.ts +9 -0
- package/dist/declarative-validation/assertions/text-length.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/text-length.js +40 -0
- package/dist/declarative-validation/assertions/text-length.js.map +1 -0
- package/dist/declarative-validation/assertions/text-occurrence-count.d.ts +9 -0
- package/dist/declarative-validation/assertions/text-occurrence-count.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/text-occurrence-count.js +22 -0
- package/dist/declarative-validation/assertions/text-occurrence-count.js.map +1 -0
- package/dist/declarative-validation/assertions/text.d.ts +9 -0
- package/dist/declarative-validation/assertions/text.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/text.js +32 -0
- package/dist/declarative-validation/assertions/text.js.map +1 -0
- package/dist/declarative-validation/compiler/assertion-builders.d.ts +6 -0
- package/dist/declarative-validation/compiler/assertion-builders.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/assertion-builders.js +199 -0
- package/dist/declarative-validation/compiler/assertion-builders.js.map +1 -0
- package/dist/declarative-validation/compiler/assertion-shapes.d.ts +18 -0
- package/dist/declarative-validation/compiler/assertion-shapes.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/assertion-shapes.js +129 -0
- package/dist/declarative-validation/compiler/assertion-shapes.js.map +1 -0
- package/dist/declarative-validation/compiler/assertions.d.ts +5 -0
- package/dist/declarative-validation/compiler/assertions.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/assertions.js +25 -0
- package/dist/declarative-validation/compiler/assertions.js.map +1 -0
- package/dist/declarative-validation/compiler/compatibility.d.ts +4 -0
- package/dist/declarative-validation/compiler/compatibility.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/compatibility.js +28 -0
- package/dist/declarative-validation/compiler/compatibility.js.map +1 -0
- package/dist/declarative-validation/compiler/diagnostics.d.ts +3 -0
- package/dist/declarative-validation/compiler/diagnostics.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/diagnostics.js +9 -0
- package/dist/declarative-validation/compiler/diagnostics.js.map +1 -0
- package/dist/declarative-validation/compiler/index.d.ts +5 -0
- package/dist/declarative-validation/compiler/index.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/index.js +164 -0
- package/dist/declarative-validation/compiler/index.js.map +1 -0
- package/dist/declarative-validation/compiler/plan.d.ts +58 -0
- package/dist/declarative-validation/compiler/plan.d.ts.map +1 -0
- package/dist/declarative-validation/compiler/plan.js +2 -0
- package/dist/declarative-validation/compiler/plan.js.map +1 -0
- package/dist/declarative-validation/diagnostics/index.d.ts +7 -0
- package/dist/declarative-validation/diagnostics/index.d.ts.map +1 -0
- package/dist/declarative-validation/diagnostics/index.js +2 -0
- package/dist/declarative-validation/diagnostics/index.js.map +1 -0
- package/dist/declarative-validation/diagnostics/profile-config-diagnostics.d.ts +11 -0
- package/dist/declarative-validation/diagnostics/profile-config-diagnostics.d.ts.map +1 -0
- package/dist/declarative-validation/diagnostics/profile-config-diagnostics.js +45 -0
- package/dist/declarative-validation/diagnostics/profile-config-diagnostics.js.map +1 -0
- package/dist/declarative-validation/evidence/index.d.ts +14 -0
- package/dist/declarative-validation/evidence/index.d.ts.map +1 -0
- package/dist/declarative-validation/evidence/index.js +38 -0
- package/dist/declarative-validation/evidence/index.js.map +1 -0
- package/dist/declarative-validation/profile/assertion-schema.d.ts +4 -0
- package/dist/declarative-validation/profile/assertion-schema.d.ts.map +1 -0
- package/dist/declarative-validation/profile/assertion-schema.js +285 -0
- package/dist/declarative-validation/profile/assertion-schema.js.map +1 -0
- package/dist/declarative-validation/profile/data-closure.d.ts +6 -0
- package/dist/declarative-validation/profile/data-closure.d.ts.map +1 -0
- package/dist/declarative-validation/profile/data-closure.js +167 -0
- package/dist/declarative-validation/profile/data-closure.js.map +1 -0
- package/dist/declarative-validation/profile/direct-profile-diagnostics.d.ts +5 -0
- package/dist/declarative-validation/profile/direct-profile-diagnostics.d.ts.map +1 -0
- package/dist/declarative-validation/profile/direct-profile-diagnostics.js +73 -0
- package/dist/declarative-validation/profile/direct-profile-diagnostics.js.map +1 -0
- package/dist/declarative-validation/profile/index.d.ts +113 -0
- package/dist/declarative-validation/profile/index.d.ts.map +1 -0
- package/dist/declarative-validation/profile/index.js +2 -0
- package/dist/declarative-validation/profile/index.js.map +1 -0
- package/dist/declarative-validation/profile/materialization.d.ts +9 -0
- package/dist/declarative-validation/profile/materialization.d.ts.map +1 -0
- package/dist/declarative-validation/profile/materialization.js +109 -0
- package/dist/declarative-validation/profile/materialization.js.map +1 -0
- package/dist/declarative-validation/profile/parse.d.ts +3 -0
- package/dist/declarative-validation/profile/parse.d.ts.map +1 -0
- package/dist/declarative-validation/profile/parse.js +89 -0
- package/dist/declarative-validation/profile/parse.js.map +1 -0
- package/dist/declarative-validation/profile/schema-values.d.ts +14 -0
- package/dist/declarative-validation/profile/schema-values.d.ts.map +1 -0
- package/dist/declarative-validation/profile/schema-values.js +81 -0
- package/dist/declarative-validation/profile/schema-values.js.map +1 -0
- package/dist/declarative-validation/profile/schema.d.ts +9 -0
- package/dist/declarative-validation/profile/schema.d.ts.map +1 -0
- package/dist/declarative-validation/profile/schema.js +98 -0
- package/dist/declarative-validation/profile/schema.js.map +1 -0
- package/dist/declarative-validation/profile/selector-schema.d.ts +4 -0
- package/dist/declarative-validation/profile/selector-schema.d.ts.map +1 -0
- package/dist/declarative-validation/profile/selector-schema.js +145 -0
- package/dist/declarative-validation/profile/selector-schema.js.map +1 -0
- package/dist/declarative-validation/results/index.d.ts +26 -0
- package/dist/declarative-validation/results/index.d.ts.map +1 -0
- package/dist/declarative-validation/results/index.js +2 -0
- package/dist/declarative-validation/results/index.js.map +1 -0
- package/dist/declarative-validation/selectors/index.d.ts +57 -0
- package/dist/declarative-validation/selectors/index.d.ts.map +1 -0
- package/dist/declarative-validation/selectors/index.js +149 -0
- package/dist/declarative-validation/selectors/index.js.map +1 -0
- package/dist/declarative-validation/selectors/source.d.ts +8 -0
- package/dist/declarative-validation/selectors/source.d.ts.map +1 -0
- package/dist/declarative-validation/selectors/source.js +57 -0
- package/dist/declarative-validation/selectors/source.js.map +1 -0
- package/dist/declarative-validation/selectors/table-targets.d.ts +13 -0
- package/dist/declarative-validation/selectors/table-targets.d.ts.map +1 -0
- package/dist/declarative-validation/selectors/table-targets.js +106 -0
- package/dist/declarative-validation/selectors/table-targets.js.map +1 -0
- package/dist/declarative-validation/selectors/table-text.d.ts +4 -0
- package/dist/declarative-validation/selectors/table-text.d.ts.map +1 -0
- package/dist/declarative-validation/selectors/table-text.js +16 -0
- package/dist/declarative-validation/selectors/table-text.js.map +1 -0
- package/dist/{ir → internal}/document-node-walk.d.ts +5 -0
- package/dist/internal/document-node-walk.d.ts.map +1 -0
- package/dist/internal/document-node-walk.js +36 -0
- package/dist/internal/document-node-walk.js.map +1 -0
- package/dist/internal/stable-json.d.ts +3 -0
- package/dist/internal/stable-json.d.ts.map +1 -0
- package/dist/internal/stable-json.js +17 -0
- package/dist/internal/stable-json.js.map +1 -0
- package/dist/ir/document-derived-views.d.ts.map +1 -1
- package/dist/ir/document-derived-views.js +2 -0
- package/dist/ir/document-derived-views.js.map +1 -1
- package/dist/ir/document-link-reference-views.d.ts +3 -0
- package/dist/ir/document-link-reference-views.d.ts.map +1 -0
- package/dist/ir/document-link-reference-views.js +150 -0
- package/dist/ir/document-link-reference-views.js.map +1 -0
- package/dist/ir/document-link-views.d.ts.map +1 -1
- package/dist/ir/document-link-views.js +7 -8
- package/dist/ir/document-link-views.js.map +1 -1
- package/dist/ir/document-list-views.d.ts.map +1 -1
- package/dist/ir/document-list-views.js +14 -13
- package/dist/ir/document-list-views.js.map +1 -1
- package/dist/ir/document-sections.d.ts.map +1 -1
- package/dist/ir/document-sections.js +2 -4
- package/dist/ir/document-sections.js.map +1 -1
- package/dist/ir/document-table-views.js +1 -1
- package/dist/ir/document-table-views.js.map +1 -1
- package/dist/ir/document-text-spans.js +1 -1
- package/dist/ir/document-text-spans.js.map +1 -1
- package/dist/ir/document.d.ts +2 -3
- package/dist/ir/document.d.ts.map +1 -1
- package/dist/ir/document.js +1 -1
- package/dist/ir/document.js.map +1 -1
- package/dist/ir/index.d.ts +1 -0
- package/dist/ir/index.d.ts.map +1 -1
- package/dist/ir/normalization-input.d.ts +12 -0
- package/dist/ir/normalization-input.d.ts.map +1 -0
- package/dist/ir/normalization-input.js +2 -0
- package/dist/ir/normalization-input.js.map +1 -0
- package/dist/rules/code-fence-languages.d.ts.map +1 -1
- package/dist/rules/code-fence-languages.js +4 -6
- package/dist/rules/code-fence-languages.js.map +1 -1
- package/dist/rules/document-query.d.ts +0 -2
- package/dist/rules/document-query.d.ts.map +1 -1
- package/dist/rules/document-query.js +1 -17
- package/dist/rules/document-query.js.map +1 -1
- package/dist/rules/index.d.ts +2 -6
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +3 -37
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/links-allowed-schemes.d.ts.map +1 -1
- package/dist/rules/links-allowed-schemes.js +3 -2
- package/dist/rules/links-allowed-schemes.js.map +1 -1
- package/dist/rules/registry.d.ts +12 -0
- package/dist/rules/registry.d.ts.map +1 -0
- package/dist/rules/registry.js +61 -0
- package/dist/rules/registry.js.map +1 -0
- package/docs/contracts/api.md +661 -0
- package/docs/contracts/declarative-validation.md +559 -0
- package/docs/contracts/frontmatter.md +122 -0
- package/fixtures/declarative-validation/examples/operational-spec/fail.md +32 -0
- package/fixtures/declarative-validation/examples/operational-spec/pass.md +34 -0
- package/fixtures/declarative-validation/examples/operational-spec/profile.yaml +131 -0
- package/fixtures/declarative-validation/examples/release-checklist/fail.md +22 -0
- package/fixtures/declarative-validation/examples/release-checklist/pass.md +22 -0
- package/fixtures/declarative-validation/examples/release-checklist/profile.yaml +96 -0
- package/fixtures/declarative-validation/examples/requirements-traceability/fail.md +27 -0
- package/fixtures/declarative-validation/examples/requirements-traceability/pass.md +27 -0
- package/fixtures/declarative-validation/examples/requirements-traceability/profile.yaml +119 -0
- package/package.json +21 -6
- package/dist/ir/document-node-walk.d.ts.map +0 -1
- package/dist/ir/document-node-walk.js +0 -16
- package/dist/ir/document-node-walk.js.map +0 -1
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
# Public API Contract
|
|
2
|
+
|
|
3
|
+
Status: package 2.0.0, document contract 1.0.0
|
|
4
|
+
Last updated: 2026-05-13
|
|
5
|
+
|
|
6
|
+
This document defines the public `@jasonbelmonti/markdown-engine` package
|
|
7
|
+
contract for the `2.0.0` package release. The serialized rich IR document
|
|
8
|
+
contract remains `documentVersion: "1.0.0"`. The stable public surface is the
|
|
9
|
+
package export from `@jasonbelmonti/markdown-engine`, not internal adapter
|
|
10
|
+
modules or raw parser output. The 1.0 rich IR design is tracked in
|
|
11
|
+
`docs/design/markdown-engine-1.0-rich-ir-operational-design-spec.md`.
|
|
12
|
+
|
|
13
|
+
## Exported Surface
|
|
14
|
+
|
|
15
|
+
The package root exports the API functions, helpers, and types from `src/api/**`:
|
|
16
|
+
|
|
17
|
+
- `parse(markdown, options?)`
|
|
18
|
+
- `normalize(parsed, options?)`
|
|
19
|
+
- `validate(document, config?, options?)`
|
|
20
|
+
- `serialize(result, options?)`
|
|
21
|
+
- `documentQueries`
|
|
22
|
+
- `validateAnnotations(document, annotations)`
|
|
23
|
+
- `parseValidationProfile(input, options?)`
|
|
24
|
+
- `validateWithProfile(document, profile, options?)`
|
|
25
|
+
|
|
26
|
+
The package root also exports the public result, document, diagnostic, config,
|
|
27
|
+
and function types declared in `src/api/**`.
|
|
28
|
+
|
|
29
|
+
The following implementation details are internal and are not stable public
|
|
30
|
+
contracts:
|
|
31
|
+
|
|
32
|
+
- raw mdast/unified parser AST nodes
|
|
33
|
+
- raw parser `position` fields
|
|
34
|
+
- raw `yaml` parser documents, CST, tokens, warnings, and errors
|
|
35
|
+
- internal parser, frontmatter, config-loader, IR-normalizer, and rule-registry
|
|
36
|
+
modules
|
|
37
|
+
|
|
38
|
+
## `parse`
|
|
39
|
+
|
|
40
|
+
Signature:
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
parse(markdown: string, options?: ParseOptions): ParseResult
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
`ParseOptions.path` is optional. When present, the path is copied into the
|
|
47
|
+
parsed result and normalized engine document.
|
|
48
|
+
|
|
49
|
+
`ParseResult` contains:
|
|
50
|
+
|
|
51
|
+
- `parsed`: the engine-owned parsed Markdown value
|
|
52
|
+
- `diagnostics`: all parse/frontmatter diagnostics produced by parsing
|
|
53
|
+
|
|
54
|
+
`ParsedMarkdown` contains:
|
|
55
|
+
|
|
56
|
+
- `markdown`: the original input string
|
|
57
|
+
- `body`: Markdown body content after frontmatter extraction
|
|
58
|
+
- `path`: optional caller-supplied path
|
|
59
|
+
- `frontmatter`: JSON-safe parsed YAML value when frontmatter is present
|
|
60
|
+
- `document`: an engine-owned `EngineDocument`
|
|
61
|
+
- `diagnostics`: parse/frontmatter diagnostics
|
|
62
|
+
|
|
63
|
+
Absent frontmatter omits `frontmatter`. Empty frontmatter produces `{}`.
|
|
64
|
+
Frontmatter YAML behavior is defined by `docs/contracts/frontmatter.md`.
|
|
65
|
+
|
|
66
|
+
## `normalize`
|
|
67
|
+
|
|
68
|
+
Signature:
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
normalize(parsed: ParsedMarkdown, options?: NormalizeOptions): NormalizeResult
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
`NormalizeOptions.documentVersion` selects the document contract version.
|
|
75
|
+
Package 2.0 defaults omitted `documentVersion` to the rich IR
|
|
76
|
+
`"1.0.0"` contract. The retained `0.1.0`-compatible path is `"0.0.0"` and must
|
|
77
|
+
be requested explicitly.
|
|
78
|
+
|
|
79
|
+
`NormalizeOptions.preserveSourceLocations` defaults to `true`. When set to
|
|
80
|
+
`false`, source ranges and source slices are omitted from the normalized
|
|
81
|
+
document, but deterministic node target IDs are still generated for the 1.0
|
|
82
|
+
path.
|
|
83
|
+
|
|
84
|
+
`NormalizeResult` contains:
|
|
85
|
+
|
|
86
|
+
- `document`: a cloned and normalized `EngineDocument`
|
|
87
|
+
- `diagnostics`: cloned diagnostics from the parsed input
|
|
88
|
+
|
|
89
|
+
Normalization sorts object attribute keys, clones public values, preserves
|
|
90
|
+
frontmatter when present, and does not expose raw parser AST data.
|
|
91
|
+
|
|
92
|
+
## `validate`
|
|
93
|
+
|
|
94
|
+
Signature:
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
validate(
|
|
98
|
+
document: EngineDocument,
|
|
99
|
+
config?: ValidationConfig,
|
|
100
|
+
options?: ValidateOptions,
|
|
101
|
+
): ValidationResult
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
`ValidationConfig` is YAML-friendly and currently supports a `rules` object.
|
|
105
|
+
The supported deterministic rule families in this contract slice are:
|
|
106
|
+
|
|
107
|
+
- `codeFences.languages`
|
|
108
|
+
- `frontmatter.required`
|
|
109
|
+
- `headings.required`
|
|
110
|
+
- `links.allowedSchemes`
|
|
111
|
+
- `rawHtml.policy`
|
|
112
|
+
|
|
113
|
+
`ValidateOptions.path` is accepted as a public option for API symmetry and
|
|
114
|
+
future diagnostics, but the current implementation does not emit additional
|
|
115
|
+
path-derived result fields from validation.
|
|
116
|
+
|
|
117
|
+
`codeFences.languages` configuration shape:
|
|
118
|
+
|
|
119
|
+
```yaml
|
|
120
|
+
rules:
|
|
121
|
+
codeFences.languages:
|
|
122
|
+
allowed:
|
|
123
|
+
- ts
|
|
124
|
+
- bash
|
|
125
|
+
requireLanguage: true
|
|
126
|
+
severity: error
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`allowed` is optional when `requireLanguage` is `true`; when present it must be
|
|
130
|
+
a non-empty array of non-empty strings. `requireLanguage` is optional and
|
|
131
|
+
defaults to `false`. At least one of `allowed` or `requireLanguage` must be
|
|
132
|
+
configured. `severity` is optional and defaults to `error`; allowed values are
|
|
133
|
+
`error`, `warning`, and `info`.
|
|
134
|
+
|
|
135
|
+
`frontmatter.required` configuration shape:
|
|
136
|
+
|
|
137
|
+
```yaml
|
|
138
|
+
rules:
|
|
139
|
+
frontmatter.required:
|
|
140
|
+
fields:
|
|
141
|
+
- title
|
|
142
|
+
- owner
|
|
143
|
+
severity: error
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`fields` must be a non-empty array of non-empty strings. `severity` is optional
|
|
147
|
+
and defaults to `error`; allowed values are `error`, `warning`, and `info`.
|
|
148
|
+
|
|
149
|
+
`headings.required` configuration shape:
|
|
150
|
+
|
|
151
|
+
```yaml
|
|
152
|
+
rules:
|
|
153
|
+
headings.required:
|
|
154
|
+
headings:
|
|
155
|
+
- Objective
|
|
156
|
+
- Success Criteria
|
|
157
|
+
severity: error
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`headings` must be a non-empty array of non-empty strings. The rule checks
|
|
161
|
+
normalized heading text. `severity` is optional and defaults to `error`;
|
|
162
|
+
allowed values are `error`, `warning`, and `info`.
|
|
163
|
+
|
|
164
|
+
`links.allowedSchemes` configuration shape:
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
rules:
|
|
168
|
+
links.allowedSchemes:
|
|
169
|
+
schemes:
|
|
170
|
+
- https
|
|
171
|
+
- mailto
|
|
172
|
+
severity: error
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
`schemes` must be a non-empty array of non-empty strings. URL schemes are
|
|
176
|
+
compared case-insensitively. Relative URLs without a scheme do not produce
|
|
177
|
+
diagnostics. `severity` is optional and defaults to `error`; allowed values are
|
|
178
|
+
`error`, `warning`, and `info`.
|
|
179
|
+
|
|
180
|
+
`rawHtml.policy` configuration shape:
|
|
181
|
+
|
|
182
|
+
```yaml
|
|
183
|
+
rules:
|
|
184
|
+
rawHtml.policy:
|
|
185
|
+
policy: deny
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
`policy` must be `allow`, `warn`, or `deny`. `allow` emits no diagnostics.
|
|
189
|
+
`warn` emits warning diagnostics for raw HTML nodes and does not make the
|
|
190
|
+
validation result invalid. `deny` emits error diagnostics for raw HTML nodes.
|
|
191
|
+
The package still treats raw HTML as inert data; it does not execute, render,
|
|
192
|
+
sanitize, fetch, or evaluate HTML.
|
|
193
|
+
|
|
194
|
+
Unsupported rules produce `config.rule.unsupported` diagnostics. Invalid config
|
|
195
|
+
shape produces config diagnostics. Unsupported rules are not inferred,
|
|
196
|
+
executed, or delegated to semantic evaluation.
|
|
197
|
+
|
|
198
|
+
`ValidationResult` contains:
|
|
199
|
+
|
|
200
|
+
- `valid`: `false` when any error-severity diagnostic exists
|
|
201
|
+
- `diagnostics`: top-level validation diagnostics
|
|
202
|
+
- `ruleResults`: per-rule deterministic results
|
|
203
|
+
|
|
204
|
+
Each `ValidationRuleResult` contains `ruleId`, `passed`, and `diagnostics`.
|
|
205
|
+
`passed` is `false` when the rule emits diagnostics, including warning or info
|
|
206
|
+
diagnostics. `valid` is controlled by error-severity diagnostics only.
|
|
207
|
+
|
|
208
|
+
## Declarative Validation
|
|
209
|
+
|
|
210
|
+
The complete declarative validation syntax, CLI, diagnostic, evidence, and
|
|
211
|
+
boundary contract is defined in `docs/contracts/declarative-validation.md`.
|
|
212
|
+
|
|
213
|
+
Signatures:
|
|
214
|
+
|
|
215
|
+
```ts
|
|
216
|
+
parseValidationProfile(
|
|
217
|
+
input: string | JsonSafeValue,
|
|
218
|
+
options?: DeclarativeProfileParseOptions,
|
|
219
|
+
): DeclarativeProfileParseResult
|
|
220
|
+
|
|
221
|
+
validateWithProfile(
|
|
222
|
+
document: EngineDocument,
|
|
223
|
+
profile: ValidationProfile,
|
|
224
|
+
options?: DeclarativeValidationOptions,
|
|
225
|
+
): DeclarativeValidationResult
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
`parseValidationProfile` accepts YAML text or JSON-safe profile objects. The
|
|
229
|
+
top-level profile keys are `syntaxVersion`, `documentVersion`, and `rules`.
|
|
230
|
+
`syntaxVersion` must be `"markdown-engine.validation@v1"`.
|
|
231
|
+
`documentVersion` is optional; when provided it must be `"0.0.0"` or
|
|
232
|
+
`"1.0.0"`. The parser preserves omission and does not inject a default into
|
|
233
|
+
the parsed profile.
|
|
234
|
+
|
|
235
|
+
`validateWithProfile` resolves an omitted profile `documentVersion` to the
|
|
236
|
+
supplied normalized `EngineDocument.version`. The returned
|
|
237
|
+
`DeclarativeValidationResult.profile.documentVersion` records that resolved
|
|
238
|
+
version. If an explicit profile `documentVersion` does not match
|
|
239
|
+
`document.version`, validation emits `profile.config.documentVersionMismatch`,
|
|
240
|
+
returns no rule results, and does not evaluate rules.
|
|
241
|
+
|
|
242
|
+
When `DeclarativeValidationOptions.includeEvidence` is `true`, the result
|
|
243
|
+
contains deterministic evidence. `inputHash` hashes the canonical supplied
|
|
244
|
+
`EngineDocument` without top-level `document.path`. `profileHash` hashes the
|
|
245
|
+
resolved profile after applying the `documentVersion` and rule `severity`
|
|
246
|
+
defaults, so an omitted `documentVersion` and an explicit matching
|
|
247
|
+
`documentVersion` produce the same profile hash for the same document version
|
|
248
|
+
and rules.
|
|
249
|
+
|
|
250
|
+
## `serialize`
|
|
251
|
+
|
|
252
|
+
Signature:
|
|
253
|
+
|
|
254
|
+
```ts
|
|
255
|
+
serialize(
|
|
256
|
+
result:
|
|
257
|
+
| ParseResult
|
|
258
|
+
| NormalizeResult
|
|
259
|
+
| ValidationResult
|
|
260
|
+
| DeclarativeValidationResult
|
|
261
|
+
| EngineDocument
|
|
262
|
+
| AnnotationValidationResult,
|
|
263
|
+
options?: SerializeOptions,
|
|
264
|
+
): string
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
`SerializeOptions.pretty` controls two-space JSON formatting. Serialization
|
|
268
|
+
normalizes plain object key order, recursively normalizes arrays and objects,
|
|
269
|
+
and omits `undefined` properties.
|
|
270
|
+
|
|
271
|
+
`SerializeOptions.compatibilityMode` is optional. When provided, it verifies
|
|
272
|
+
document-bearing public results before serialization:
|
|
273
|
+
|
|
274
|
+
- `compatibilityMode: "default"` expects document version `"1.0.0"`.
|
|
275
|
+
- `compatibilityMode: "legacy-0.1"` expects document version `"0.0.0"`.
|
|
276
|
+
|
|
277
|
+
Mismatched document-bearing results throw `EngineCompatibilityError` with code
|
|
278
|
+
`engine.compatibility.versionMismatch`, `requestedMode`, `expectedVersion`, and
|
|
279
|
+
`actualVersion`. Results that do not contain an `EngineDocument`, such as the
|
|
280
|
+
current `ValidationResult`, are not rejected by the compatibility check.
|
|
281
|
+
|
|
282
|
+
The serializer is intended for stable JSON review evidence and downstream
|
|
283
|
+
contract checks. It does not accept arbitrary class instances as a public data
|
|
284
|
+
model.
|
|
285
|
+
|
|
286
|
+
## Document Contract
|
|
287
|
+
|
|
288
|
+
`EngineDocument` contains:
|
|
289
|
+
|
|
290
|
+
- `kind`: currently `"markdown-document"`
|
|
291
|
+
- `version`: currently `"0.0.0"`
|
|
292
|
+
- `path`: optional caller-supplied path
|
|
293
|
+
- `frontmatter`: JSON-safe parsed frontmatter value when present
|
|
294
|
+
- `children`: normalized `EngineNode[]`
|
|
295
|
+
- `sourceRange`: optional source range
|
|
296
|
+
|
|
297
|
+
`EngineNode` contains:
|
|
298
|
+
|
|
299
|
+
- `type`: engine-owned node type string
|
|
300
|
+
- `text`: optional text content
|
|
301
|
+
- `attributes`: optional JSON-safe attributes
|
|
302
|
+
- `sourceRange`: optional source range
|
|
303
|
+
- `children`: optional child nodes
|
|
304
|
+
|
|
305
|
+
Node type coverage remains limited to the current parser/IR implementation and
|
|
306
|
+
will expand through implementation work packages. Code nodes may include a
|
|
307
|
+
`kind` attribute of `fenced` or `indented`; `codeFences.*` rules apply only to
|
|
308
|
+
code nodes with `kind: "fenced"`. Raw parser node objects are not public.
|
|
309
|
+
|
|
310
|
+
## 1.0 Contract
|
|
311
|
+
|
|
312
|
+
The final 1.0 document contract is selected by default in package 2.0, remains
|
|
313
|
+
available explicitly as `documentVersion: "1.0.0"`, and is checked with
|
|
314
|
+
`compatibilityMode: "default"`.
|
|
315
|
+
|
|
316
|
+
Callers select the 1.0 contract with either `normalize(parsed)` or an explicit
|
|
317
|
+
selector:
|
|
318
|
+
|
|
319
|
+
```ts
|
|
320
|
+
const parsed = parse(markdown, { path: "mission.md" });
|
|
321
|
+
const document = normalize(parsed.parsed, {
|
|
322
|
+
documentVersion: "1.0.0",
|
|
323
|
+
}).document;
|
|
324
|
+
|
|
325
|
+
const sections = documentQueries.sections(document);
|
|
326
|
+
const serialized = serialize(document, { compatibilityMode: "default" });
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
The retained `0.1.0`-compatible path remains explicit:
|
|
330
|
+
|
|
331
|
+
```ts
|
|
332
|
+
const legacyDocument = normalize(parsed.parsed, {
|
|
333
|
+
documentVersion: "0.0.0",
|
|
334
|
+
}).document;
|
|
335
|
+
|
|
336
|
+
const serializedLegacy = serialize(legacyDocument, {
|
|
337
|
+
compatibilityMode: "legacy-0.1",
|
|
338
|
+
});
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 1.0 Document Fields
|
|
342
|
+
|
|
343
|
+
When callers normalize with `documentVersion: "1.0.0"`, the document
|
|
344
|
+
includes deterministic derived structural views:
|
|
345
|
+
|
|
346
|
+
- `kind`: `"markdown-document"`.
|
|
347
|
+
- `version`: `"1.0.0"`.
|
|
348
|
+
- `path`: optional caller-supplied path from parse or normalized document input.
|
|
349
|
+
- `frontmatter`: JSON-safe parsed frontmatter value when present.
|
|
350
|
+
- `target`: the document-level `EngineNodeTarget`.
|
|
351
|
+
- `children`: normalized `EngineNode[]`; each node has `target` in the 1.0
|
|
352
|
+
path.
|
|
353
|
+
- `sourceRange`: optional document source range when source locations are
|
|
354
|
+
preserved.
|
|
355
|
+
- `compatibility`: `{ mode: "default", reason: "1.0 document contract" }`.
|
|
356
|
+
- `sections`: heading-derived `EngineSection[]`.
|
|
357
|
+
- `textSpans`: text-bearing `EngineTextSpan[]`.
|
|
358
|
+
- `tables`: `EngineTable[]` with flattened table-cell coordinates.
|
|
359
|
+
- `lists`: `EngineList[]` with list item coordinates.
|
|
360
|
+
- `links`: `EngineLink[]`.
|
|
361
|
+
- `linkReferences`: `EngineLinkReference[]`.
|
|
362
|
+
- `annotations`: optional caller-owned annotations if a caller attaches a
|
|
363
|
+
validated annotation result to the document.
|
|
364
|
+
|
|
365
|
+
`EngineNode` keeps the `0.1.0` fields `type`, optional `text`, optional
|
|
366
|
+
`attributes`, optional `sourceRange`, and optional `children`. In the 1.0
|
|
367
|
+
path it may also include:
|
|
368
|
+
|
|
369
|
+
- `target`: deterministic `EngineNodeTarget`.
|
|
370
|
+
- `source`: `{ range, text }` when source locations are preserved and parser
|
|
371
|
+
offsets are usable.
|
|
372
|
+
|
|
373
|
+
### Target Contract And Stability Limits
|
|
374
|
+
|
|
375
|
+
`EngineNodeTarget` contains:
|
|
376
|
+
|
|
377
|
+
- `kind`: currently `"node"`.
|
|
378
|
+
- `id`: deterministic target ID, such as `node:1.1:link` or
|
|
379
|
+
`section:node:0:heading`.
|
|
380
|
+
- `path`: optional zero-based structural path through `children`.
|
|
381
|
+
- `nodeType`: optional engine-owned node type, such as `"document"`,
|
|
382
|
+
`"heading"`, `"paragraph"`, `"link"`, or `"section"`.
|
|
383
|
+
- `sourceRange`: optional cloned source range when source locations are
|
|
384
|
+
preserved.
|
|
385
|
+
|
|
386
|
+
Compatibility-first target taxonomy decision: the serialized
|
|
387
|
+
`EngineNodeTarget` shape remains unchanged for the 1.0 release lane. Its
|
|
388
|
+
`kind` field is still `"node"` for document, ordinary node, and section
|
|
389
|
+
addresses, so callers must not treat `target.kind` as the semantic target
|
|
390
|
+
category. Runtime target category is resolved by the documented query helpers:
|
|
391
|
+
|
|
392
|
+
- `document`: the document-level `document.target`. It identifies the whole
|
|
393
|
+
normalized document, is not returned by `documentQueries.nodes`, and does not
|
|
394
|
+
currently produce a source slice because normalized documents do not retain
|
|
395
|
+
the complete source text.
|
|
396
|
+
- `node`: an actual recursive `EngineNode.target` in `document.children`.
|
|
397
|
+
`documentQueries.nodes(document, { targetId })` only resolves this category.
|
|
398
|
+
- `section`: an `EngineSection.target` derived from an owning heading target.
|
|
399
|
+
It is resolved through `documentQueries.sections`; `sourceSlice` returns the
|
|
400
|
+
owning heading source slice when available.
|
|
401
|
+
|
|
402
|
+
Target IDs are deterministic for identical Markdown input, parser behavior,
|
|
403
|
+
normalization options, package version, and runtime version. They are not a
|
|
404
|
+
promise of stability across arbitrary content edits, parser upgrades, or final
|
|
405
|
+
1.0 contract promotion. They do not expose raw mdast nodes or raw parser
|
|
406
|
+
position objects.
|
|
407
|
+
|
|
408
|
+
`SourceRange` contains `start` and `end` positions. Each position has `line`,
|
|
409
|
+
`column`, and optional `offset`. Source slices are produced only when both
|
|
410
|
+
offsets are present, integers, ordered, non-negative, and contained by the
|
|
411
|
+
document source text.
|
|
412
|
+
|
|
413
|
+
### Structural Views
|
|
414
|
+
|
|
415
|
+
`sections` contains heading-derived `EngineSection` records:
|
|
416
|
+
|
|
417
|
+
- `target`: section target whose ID is derived from the heading target.
|
|
418
|
+
- `headingTarget`: target for the owning heading node.
|
|
419
|
+
- `parentSection`: optional parent section target.
|
|
420
|
+
- `depth`: heading depth.
|
|
421
|
+
- `title`: normalized heading text.
|
|
422
|
+
- `bodyTargets`: node targets owned by the section body.
|
|
423
|
+
- `childSections`: child section targets.
|
|
424
|
+
|
|
425
|
+
`textSpans` contains `EngineTextSpan` records with `target`, `text`, and
|
|
426
|
+
optional `sourceRange`.
|
|
427
|
+
|
|
428
|
+
`tables` contains `EngineTable` records with `target` and flattened `cells`.
|
|
429
|
+
Each `EngineTableCell` exposes `target`, normalized `text`, zero-based
|
|
430
|
+
`rowIndex`, zero-based `columnIndex`, `header`, and optional `sourceRange`. The
|
|
431
|
+
GFM header row is row index `0`; body rows continue at `1`, `2`, and so on.
|
|
432
|
+
|
|
433
|
+
`lists` contains `EngineList` records with `target`, `ordered`, optional
|
|
434
|
+
`start`, and `items`. Each `EngineListItem` exposes `target`, zero-based
|
|
435
|
+
`itemIndex` within its immediate list container, zero-based `depth`, optional
|
|
436
|
+
`checked`, and optional `sourceRange`.
|
|
437
|
+
|
|
438
|
+
`links` contains `EngineLink` records with `target`, `url`, normalized `text`,
|
|
439
|
+
optional `title`, and optional `sourceRange`. It remains scoped to inline
|
|
440
|
+
Markdown links.
|
|
441
|
+
|
|
442
|
+
`linkReferences` contains additive `EngineLinkReference` records for public,
|
|
443
|
+
source-located URL and reference extraction. Records use preorder depth-first
|
|
444
|
+
document order for node-backed constructs and include:
|
|
445
|
+
|
|
446
|
+
- `target`: target for the Markdown construct location.
|
|
447
|
+
- `kind`: one of `"link"`, `"image"`, `"definition"`, `"linkReference"`, or
|
|
448
|
+
`"imageReference"`.
|
|
449
|
+
- `url`: direct URL for inline links, images, and definitions; resolved
|
|
450
|
+
definition URL for reference usages when a matching definition is known.
|
|
451
|
+
- `title`: direct or resolved optional title when available.
|
|
452
|
+
- `text`: user-visible text for links and link reference usages when available.
|
|
453
|
+
- `alt`: user-visible alt text for images and image reference usages when
|
|
454
|
+
available.
|
|
455
|
+
- `label`: Markdown label for definitions and reference usages when available.
|
|
456
|
+
- `identifier`: normalized Markdown identifier for definitions and reference
|
|
457
|
+
usages when available.
|
|
458
|
+
- `referenceType`: reference usage type, such as `"full"`, `"collapsed"`, or
|
|
459
|
+
`"shortcut"`, when available.
|
|
460
|
+
- `definitionTarget`: target of the matched link definition for resolved
|
|
461
|
+
reference usages.
|
|
462
|
+
- `sourceRange`: optional construct source range.
|
|
463
|
+
|
|
464
|
+
Reference usages and definitions are represented as separate records. Reference
|
|
465
|
+
usage records are joined to the first matching definition target and URL when
|
|
466
|
+
the parsed Markdown structure provides a match. The view only reports Markdown
|
|
467
|
+
constructs present in the normalized engine node tree; reference syntax that the
|
|
468
|
+
parser treats as plain text is not reported.
|
|
469
|
+
|
|
470
|
+
### Query Helpers
|
|
471
|
+
|
|
472
|
+
`documentQueries` exposes deterministic helper methods over this public IR:
|
|
473
|
+
|
|
474
|
+
- `nodes(document, query?)` filters recursive nodes by node type or target ID.
|
|
475
|
+
Recursive node-backed helper results use preorder depth-first document order:
|
|
476
|
+
each node appears before its descendants, and descendants are exhausted before
|
|
477
|
+
the next sibling.
|
|
478
|
+
- `sections(document, query?)` filters sections by target ID, heading target
|
|
479
|
+
ID, parent section target ID, title, or depth.
|
|
480
|
+
- `textSpans(document, query?)` filters spans by target ID, node type, exact
|
|
481
|
+
text, or included text.
|
|
482
|
+
- `tables(document, query?)` filters table views by target ID.
|
|
483
|
+
- `lists(document, query?)` filters list views by target ID, ordered state, or
|
|
484
|
+
item depth.
|
|
485
|
+
- `links(document, query?)` filters link views by target ID, URL, or text.
|
|
486
|
+
- `linkReferences(document, query?)` filters link-like reference views by target
|
|
487
|
+
ID, kind, URL, text, alt text, label, identifier, reference type, or
|
|
488
|
+
definition target ID.
|
|
489
|
+
- `targetCategory(document, target)` returns `"document"`, `"node"`,
|
|
490
|
+
`"section"`, or `undefined` for targets that do not resolve in the document.
|
|
491
|
+
- `resolveTarget(document, target)` returns a category-specific resolution:
|
|
492
|
+
document target, ordinary node plus optional source slice, or section plus
|
|
493
|
+
optional owning-heading source slice.
|
|
494
|
+
- `sourceSlice(document, target)` returns the precomputed source slice for node
|
|
495
|
+
targets when parser offsets are present, integer, ordered, non-negative, and
|
|
496
|
+
in bounds. For section targets, it returns the source slice for the owning
|
|
497
|
+
heading target. For document targets, it returns `undefined` because complete
|
|
498
|
+
source text is not stored on `EngineDocument`. It returns `undefined` instead
|
|
499
|
+
of guessing when offsets are absent, non-integer, reversed, negative,
|
|
500
|
+
unsupported, out of bounds, or when the target does not resolve.
|
|
501
|
+
|
|
502
|
+
### Annotation Contract
|
|
503
|
+
|
|
504
|
+
Annotations use an explicit address-mode wrapper:
|
|
505
|
+
|
|
506
|
+
```ts
|
|
507
|
+
type EngineAnnotationTarget =
|
|
508
|
+
| { kind: "node"; nodeTarget: EngineNodeTarget }
|
|
509
|
+
| { kind: "source"; sourceRange: SourceRange };
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
For node annotations, `kind: "node"` identifies the annotation addressing mode.
|
|
513
|
+
The annotated Markdown node type remains `nodeTarget.nodeType`, such as
|
|
514
|
+
`"heading"` or `"paragraph"`. For source annotations, `sourceRange` contains
|
|
515
|
+
the exact caller-provided range. Annotation `payload` values remain opaque and
|
|
516
|
+
caller-owned; the engine validates only target shape and target existence.
|
|
517
|
+
|
|
518
|
+
`validateAnnotations(document, annotations)` returns:
|
|
519
|
+
|
|
520
|
+
- `valid`: `true` when all annotation targets are accepted.
|
|
521
|
+
- `annotations`: cloned annotations with target data preserved.
|
|
522
|
+
- `diagnostics`: deterministic `EngineTargetDiagnostic[]`.
|
|
523
|
+
|
|
524
|
+
The annotation validator accepts all resolvable engine targets: the document
|
|
525
|
+
target, ordinary node targets, and section targets. These keep
|
|
526
|
+
`target.kind: "node"` for wire compatibility; target category is determined by
|
|
527
|
+
the resolver APIs above. For source targets, it verifies start/end shape and
|
|
528
|
+
ordering. When the normalized
|
|
529
|
+
document has `sourceRange`, source targets must be contained by that document
|
|
530
|
+
range; when `sourceRange` is absent, the validator cannot prove source-target
|
|
531
|
+
bounds and does not synthesize a document range. It rejects malformed target
|
|
532
|
+
wrappers, malformed node targets, unknown node targets, invalid source range
|
|
533
|
+
ordering, and source ranges proven out of bounds. It does not interpret,
|
|
534
|
+
normalize, validate, or serialize caller payload semantics beyond normal public
|
|
535
|
+
serialization behavior.
|
|
536
|
+
|
|
537
|
+
### Compatibility And Migration
|
|
538
|
+
|
|
539
|
+
The current package version is `2.0.0`. The serialized document contract
|
|
540
|
+
version remains `"1.0.0"`. Package 2.0 selects that rich IR contract by
|
|
541
|
+
default for `normalize(parsed)`; callers may also request it explicitly with
|
|
542
|
+
`normalize(..., { documentVersion: "1.0.0" })`. Serialization gates check it
|
|
543
|
+
with `compatibilityMode: "default"`.
|
|
544
|
+
|
|
545
|
+
The retained compatibility selector is `compatibilityMode: "legacy-0.1"`,
|
|
546
|
+
which accepts document-bearing public results with `version: "0.0.0"`. This is
|
|
547
|
+
the documented 0.1.x-compatible behavior gate. Consumers should not infer
|
|
548
|
+
compatibility from the absence of rich IR fields.
|
|
549
|
+
|
|
550
|
+
Migration from the `0.1.0` document shape, or from pre-2.0 API callers that
|
|
551
|
+
depended on implicit legacy normalization, requires consumers to:
|
|
552
|
+
|
|
553
|
+
- use package 2.0's default `normalize(parsed)` rich IR output or request
|
|
554
|
+
`documentVersion: "1.0.0"` during normalization;
|
|
555
|
+
- read `target`, `sections`, `textSpans`, `tables`, `lists`, `links`,
|
|
556
|
+
`linkReferences`, and `source` from the normalized document instead of
|
|
557
|
+
re-deriving them from raw Markdown;
|
|
558
|
+
- use `documentQueries` for structural access rather than depending on internal
|
|
559
|
+
traversal helpers;
|
|
560
|
+
- use `validateAnnotations` for caller-owned node and source annotations;
|
|
561
|
+
- serialize document-bearing rich IR outputs with `compatibilityMode:
|
|
562
|
+
"default"` in gates that must reject legacy document versions;
|
|
563
|
+
- use `compatibilityMode: "legacy-0.1"` only for retained 0.1.x-compatible
|
|
564
|
+
parse or normalize outputs.
|
|
565
|
+
|
|
566
|
+
### CLI Impact
|
|
567
|
+
|
|
568
|
+
The local CLI runs parse and normalization for one Markdown file and writes
|
|
569
|
+
pretty JSON. BEL-952 changes the CLI default output to the 1.0 rich IR
|
|
570
|
+
contract: `--file` and `--path` emit a normalized result whose
|
|
571
|
+
`document.version` is `"1.0.0"` and whose document includes derived rich
|
|
572
|
+
IR views such as `target`, `sections`, `textSpans`, `tables`, `lists`, and
|
|
573
|
+
`links` when present. The document also exposes `linkReferences` for
|
|
574
|
+
URL-bearing links, images, definitions, and source-located reference usages.
|
|
575
|
+
|
|
576
|
+
Legacy CLI output remains explicit:
|
|
577
|
+
|
|
578
|
+
```sh
|
|
579
|
+
markdown-engine --document-version 0.0.0 --file mission.md
|
|
580
|
+
```
|
|
581
|
+
|
|
582
|
+
The supported CLI selector values are:
|
|
583
|
+
|
|
584
|
+
- `--document-version 1.0.0`: 1.0 rich IR output, also the default
|
|
585
|
+
when the selector is omitted.
|
|
586
|
+
- `--document-version 0.0.0`: retained `0.1.0`-compatible normalized document
|
|
587
|
+
output without rich derived views.
|
|
588
|
+
|
|
589
|
+
The selector accepts spaced or assignment-form syntax, such as
|
|
590
|
+
`--document-version 0.0.0` or `--document-version=0.0.0`. Missing, invalid, or
|
|
591
|
+
repeated `--document-version` selectors exit with code `2` and usage text; an
|
|
592
|
+
empty assignment-form selector is treated as missing. Directory traversal
|
|
593
|
+
remains unsupported.
|
|
594
|
+
|
|
595
|
+
Declarative validation is exposed through a separate subcommand:
|
|
596
|
+
|
|
597
|
+
```sh
|
|
598
|
+
markdown-engine validate --file mission.md --profile profile.yaml
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
The validate subcommand always normalizes the Markdown document as
|
|
602
|
+
`document.version` `"1.0.0"` and does not accept `--document-version`.
|
|
603
|
+
`--format json` is the default and only supported validation format. It reads,
|
|
604
|
+
parses, and compile-preflights the profile before reading the Markdown file.
|
|
605
|
+
Profile parse/config/compile failures exit with code `1` and emit JSON with
|
|
606
|
+
`stage: "profile"`, empty `ruleResults`, no `profile`, and no `evidence`.
|
|
607
|
+
Usage errors, unsupported formats, unknown arguments, and local file read errors
|
|
608
|
+
exit with code `2`. Validation success exits with code `0`; validation or
|
|
609
|
+
normalization error diagnostics exit with code `1`. Validation JSON includes
|
|
610
|
+
`profile`, `ruleResults`, `diagnostics`, and `evidence`.
|
|
611
|
+
|
|
612
|
+
Semver classification: package 2.0 makes the rich IR contract the default API
|
|
613
|
+
normalization output while retaining the document contract version
|
|
614
|
+
`"1.0.0"`. This is breaking for API consumers that call `normalize(parsed)` and
|
|
615
|
+
expect the legacy `0.0.0` document shape. Migration is to either consume the
|
|
616
|
+
rich IR fields or pin `documentVersion: "0.0.0"` until the downstream consumer
|
|
617
|
+
is ready. CLI consumers can still pin `--document-version 0.0.0` for explicit
|
|
618
|
+
legacy output.
|
|
619
|
+
|
|
620
|
+
### Non-Goals And Limits
|
|
621
|
+
|
|
622
|
+
Structural views are derived from engine-owned document nodes, targets, and
|
|
623
|
+
source metadata. They do not expose raw parser AST fields as public contract.
|
|
624
|
+
|
|
625
|
+
The package boundary remains domain-neutral. The 1.0 contract does not
|
|
626
|
+
implement SpecTrace entities, profile compiler behavior, runtime lenses, MCP
|
|
627
|
+
transport, agent adapters, semantic or LLM evaluation, arbitrary rule plugins,
|
|
628
|
+
network services, persistence, file watching, graph storage, rendering,
|
|
629
|
+
sanitization, fetching, or raw HTML execution.
|
|
630
|
+
|
|
631
|
+
Source text and raw HTML remain inert strings. The engine does not promise
|
|
632
|
+
source slices when parser offsets are missing or unusable, and it does not
|
|
633
|
+
promise node target stability across arbitrary edits.
|
|
634
|
+
|
|
635
|
+
## Diagnostic Contract
|
|
636
|
+
|
|
637
|
+
`MarkdownDiagnostic` contains:
|
|
638
|
+
|
|
639
|
+
- `code`: stable diagnostic code string
|
|
640
|
+
- `ruleId`: optional validation rule identifier
|
|
641
|
+
- `message`: human-readable diagnostic message
|
|
642
|
+
- `severity`: `"error"`, `"warning"`, or `"info"`
|
|
643
|
+
- `sourceRange`: optional source range
|
|
644
|
+
|
|
645
|
+
`SourceRange` contains `start` and `end` positions. Each position has `line`,
|
|
646
|
+
`column`, and optional `offset`.
|
|
647
|
+
|
|
648
|
+
## Compatibility Notes
|
|
649
|
+
|
|
650
|
+
The `0.1.0` contract was review-gated by WP-2, MS-2, and MS-3 before first
|
|
651
|
+
publication. From the published `0.1.0` baseline forward, changes to public API
|
|
652
|
+
signatures, result fields, diagnostic schema, source-location semantics,
|
|
653
|
+
validation config semantics, or serialized output shape require
|
|
654
|
+
semantic-version classification. The planned 1.0 rich IR contract will update
|
|
655
|
+
this API contract before 1.0 release approval.
|
|
656
|
+
|
|
657
|
+
The `@jasonbelmonti/markdown-engine` package boundary remains limited to
|
|
658
|
+
parsing, normalization, deterministic validation, diagnostics, and
|
|
659
|
+
serialization. Profile compiler behavior, runtime lenses, MCP transport, agent
|
|
660
|
+
adapters, network services, persistence, LLM calls, semantic rubrics, and
|
|
661
|
+
arbitrary rule plugins are out of scope.
|