@agentshouse/mdmodel 0.1.0-alpha.2 → 0.1.0-alpha.3
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/README.md +24 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +3 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +2 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +9 -5
- package/dist/validate.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/fixtures/README.md +8 -4
- package/fixtures/cases/any-without-type/context.json +1 -0
- package/fixtures/cases/binary-any-reference/context.json +5 -0
- package/fixtures/cases/binary-any-reference/expected.json +7 -0
- package/fixtures/cases/binary-any-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-any-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-document-collision/context.json +5 -0
- package/fixtures/cases/binary-document-collision/expected.json +6 -0
- package/fixtures/cases/binary-document-collision/library/notes/draft.md +3 -0
- package/fixtures/cases/binary-document-collision/library/types/note.md +3 -0
- package/fixtures/cases/binary-link-outside-collection/context.json +6 -0
- package/fixtures/cases/binary-link-outside-collection/expected.json +6 -0
- package/fixtures/cases/binary-link-outside-collection/library/notes/draft.md +5 -0
- package/fixtures/cases/binary-link-outside-collection/library/types/note.md +3 -0
- package/fixtures/cases/binary-prototype-reference/context.json +1 -0
- package/fixtures/cases/binary-prototype-reference/expected.json +7 -0
- package/fixtures/cases/binary-prototype-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-prototype-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-typed-reference/context.json +5 -0
- package/fixtures/cases/binary-typed-reference/expected.json +7 -0
- package/fixtures/cases/binary-typed-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-typed-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-typed-reference/library/types/person.md +3 -0
- package/fixtures/cases/declared-binary-links/context.json +6 -0
- package/fixtures/cases/declared-binary-links/expected.json +1 -0
- package/fixtures/cases/declared-binary-links/library/notes/draft.md +7 -0
- package/fixtures/cases/declared-binary-links/library/types/note.md +3 -0
- package/fixtures/cases/field-enum/context.json +1 -0
- package/fixtures/cases/malformed-definition/context.json +1 -0
- package/fixtures/cases/missing-binary-image/context.json +6 -0
- package/fixtures/cases/missing-binary-image/expected.json +6 -0
- package/fixtures/cases/missing-binary-image/library/notes/draft.md +5 -0
- package/fixtures/cases/missing-binary-image/library/types/note.md +3 -0
- package/fixtures/cases/missing-binary-link/context.json +6 -0
- package/fixtures/cases/missing-binary-link/expected.json +6 -0
- package/fixtures/cases/missing-binary-link/library/notes/draft.md +5 -0
- package/fixtures/cases/missing-binary-link/library/types/note.md +3 -0
- package/fixtures/cases/missing-required-field/context.json +1 -0
- package/fixtures/cases/prd-definition/context.json +1 -0
- package/fixtures/cases/referenced-missing-file/context.json +1 -0
- package/fixtures/cases/structured-section/context.json +1 -0
- package/fixtures/cases/unclosed-frontmatter/context.json +1 -0
- package/fixtures/cases/unresolved-link/context.json +1 -0
- package/fixtures/cases/valid-typed-document/context.json +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,8 @@ deterministic application of one structured change to Document content, the
|
|
|
5
5
|
Markdown syntax profile, and the conformance fixtures.
|
|
6
6
|
|
|
7
7
|
The package runs in a browser and in Node. It makes no network call and reads
|
|
8
|
-
no filesystem on its own. Callers pass Library state as path-to-content
|
|
8
|
+
no filesystem on its own. Callers pass text Library state as path-to-content and declare retained binary
|
|
9
|
+
link targets separately in a `ValidationContext`.
|
|
9
10
|
The public root exposes one ESM artifact. Node 24.20.0 and later can load it
|
|
10
11
|
through either `import` or `require`; browser bundlers consume the same artifact.
|
|
11
12
|
|
|
@@ -30,6 +31,13 @@ import {
|
|
|
30
31
|
} from '@agentshouse/mdmodel';
|
|
31
32
|
|
|
32
33
|
validate({ 'note.md': '# Hello\n' });
|
|
34
|
+
validate(
|
|
35
|
+
{
|
|
36
|
+
'types/note.md': '---\ntype: definition\n---\n',
|
|
37
|
+
'note.md': '---\ntype: note\n---\n\n',
|
|
38
|
+
},
|
|
39
|
+
{ binaryTargets: ['assets/figure.png'] },
|
|
40
|
+
);
|
|
33
41
|
const parsed = parse(content);
|
|
34
42
|
if (parsed.ok) {
|
|
35
43
|
const next = apply(parsed.document, {
|
|
@@ -42,8 +50,21 @@ if (parsed.ok) {
|
|
|
42
50
|
}
|
|
43
51
|
```
|
|
44
52
|
|
|
45
|
-
`validate` takes
|
|
46
|
-
|
|
53
|
+
`validate(library, context?)` takes the resulting text Library and one
|
|
54
|
+
`ValidationContext` containing `binaryTargets: readonly string[]`. Omitting the
|
|
55
|
+
context declares no binary targets. Library keys and binary targets use the
|
|
56
|
+
same collection-relative path namespace; callers supply canonical paths, and
|
|
57
|
+
a path declared as both text and binary is refused. Ordinary links and images
|
|
58
|
+
in typed Documents may resolve to either membership, including relative
|
|
59
|
+
normalization from the source Document. A binary target supplies no Document
|
|
60
|
+
or MD Type and cannot satisfy a typed reference, including one to `any`.
|
|
61
|
+
The existing `any` Document rules are unchanged.
|
|
62
|
+
|
|
63
|
+
Validation returns acceptance or one refusal naming the file, the field or
|
|
64
|
+
section, the violated rule, and `VERSION`. Every caller operation that validates
|
|
65
|
+
a resulting collection supplies that collection's context to this same
|
|
66
|
+
`validate` function. `parse`, `apply`, and `serialize` operate on a single text
|
|
67
|
+
Document; they do not validate collection membership or consume binary bytes.
|
|
47
68
|
`apply` sets one typed field, including a list field as a whole, or replaces
|
|
48
69
|
one declared section body against that value's prior content. A field change
|
|
49
70
|
does not reformat the rest of the file.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { apply, parse, serialize } from './document.js';
|
|
2
2
|
export { MARKDOWN_SYNTAX_PROFILE } from './profile.js';
|
|
3
|
-
export type { ApplyResult, Change, Document, Library, ParseResult, Refusal, Validation, } from './types.js';
|
|
3
|
+
export type { ApplyResult, Change, Document, Library, ParseResult, Refusal, Validation, ValidationContext, } from './types.js';
|
|
4
4
|
export { validate } from './validate.js';
|
|
5
5
|
export { VERSION } from './version.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EACV,WAAW,EACX,MAAM,EACN,QAAQ,EACR,OAAO,EACP,WAAW,EACX,OAAO,EACP,UAAU,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,YAAY,EACV,WAAW,EACX,MAAM,EACN,QAAQ,EACR,OAAO,EACP,WAAW,EACX,OAAO,EACP,UAAU,EACV,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/workspace/packages/mdmodel/src/index.ts"],"sourcesContent":["export { apply, parse, serialize } from './document.js';\nexport { MARKDOWN_SYNTAX_PROFILE } from './profile.js';\nexport type {\n ApplyResult,\n Change,\n Document,\n Library,\n ParseResult,\n Refusal,\n Validation,\n} from './types.js';\nexport { validate } from './validate.js';\nexport { VERSION } from './version.js';\n"],"names":["apply","parse","serialize","MARKDOWN_SYNTAX_PROFILE","validate","VERSION"],"mappings":"AAAA,SAASA,KAAK,EAAEC,KAAK,EAAEC,SAAS,QAAQ,gBAAgB;AACxD,SAASC,uBAAuB,QAAQ,eAAe;
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/index.ts"],"sourcesContent":["export { apply, parse, serialize } from './document.js';\nexport { MARKDOWN_SYNTAX_PROFILE } from './profile.js';\nexport type {\n ApplyResult,\n Change,\n Document,\n Library,\n ParseResult,\n Refusal,\n Validation,\n ValidationContext,\n} from './types.js';\nexport { validate } from './validate.js';\nexport { VERSION } from './version.js';\n"],"names":["apply","parse","serialize","MARKDOWN_SYNTAX_PROFILE","validate","VERSION"],"mappings":"AAAA,SAASA,KAAK,EAAEC,KAAK,EAAEC,SAAS,QAAQ,gBAAgB;AACxD,SAASC,uBAAuB,QAAQ,eAAe;AAWvD,SAASC,QAAQ,QAAQ,gBAAgB;AACzC,SAASC,OAAO,QAAQ,eAAe"}
|
package/dist/types.d.ts
CHANGED
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAC9B,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC;AAE/C,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,MAAM,GACd;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAC9B,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC;AAE/C,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,MAAM,GACd;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/workspace/packages/mdmodel/src/types.ts"],"sourcesContent":["export type Library = Readonly<Record<string, string>>;\n\nexport type Document = {\n readonly content: string;\n readonly type: string | undefined;\n readonly fields: Readonly<Record<string, unknown>>;\n readonly sections: Readonly<Record<string, string>>;\n};\n\nexport type Refusal = {\n readonly file: string;\n readonly rule: string;\n readonly version: string;\n readonly location?: string;\n readonly referrers?: readonly string[];\n};\n\nexport type Validation =\n | { readonly verdict: 'accept' }\n | ({ readonly verdict: 'refuse' } & Refusal);\n\nexport type ParseResult =\n | { readonly ok: true; readonly document: Document }\n | { readonly ok: false; readonly refusal: Refusal };\n\nexport type Change =\n | {\n readonly kind: 'field';\n readonly name: string;\n readonly value: unknown;\n readonly prior: unknown;\n }\n | {\n readonly kind: 'section';\n readonly name: string;\n readonly value: string;\n readonly prior: string;\n };\n\nexport type ApplyResult =\n | { readonly outcome: 'applied'; readonly document: Document }\n | { readonly outcome: 'stale'; readonly document: Document }\n | { readonly outcome: 'refuse'; readonly refusal: Refusal };\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/types.ts"],"sourcesContent":["export type Library = Readonly<Record<string, string>>;\n\nexport type ValidationContext = {\n readonly binaryTargets: readonly string[];\n};\n\nexport type Document = {\n readonly content: string;\n readonly type: string | undefined;\n readonly fields: Readonly<Record<string, unknown>>;\n readonly sections: Readonly<Record<string, string>>;\n};\n\nexport type Refusal = {\n readonly file: string;\n readonly rule: string;\n readonly version: string;\n readonly location?: string;\n readonly referrers?: readonly string[];\n};\n\nexport type Validation =\n | { readonly verdict: 'accept' }\n | ({ readonly verdict: 'refuse' } & Refusal);\n\nexport type ParseResult =\n | { readonly ok: true; readonly document: Document }\n | { readonly ok: false; readonly refusal: Refusal };\n\nexport type Change =\n | {\n readonly kind: 'field';\n readonly name: string;\n readonly value: unknown;\n readonly prior: unknown;\n }\n | {\n readonly kind: 'section';\n readonly name: string;\n readonly value: string;\n readonly prior: string;\n };\n\nexport type ApplyResult =\n | { readonly outcome: 'applied'; readonly document: Document }\n | { readonly outcome: 'stale'; readonly document: Document }\n | { readonly outcome: 'refuse'; readonly refusal: Refusal };\n"],"names":[],"mappings":"AA2CA,WAG8D"}
|
package/dist/validate.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Library, Validation } from './types.js';
|
|
2
|
-
export declare function validate(library: Library): Validation;
|
|
1
|
+
import type { Library, Validation, ValidationContext } from './types.js';
|
|
2
|
+
export declare function validate(library: Library, context?: ValidationContext): Validation;
|
|
3
3
|
//# sourceMappingURL=validate.d.ts.map
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAY,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAY,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAuCnF,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,GACjD,UAAU,CAkHZ"}
|
package/dist/validate.js
CHANGED
|
@@ -38,10 +38,14 @@ function declaredTypeOf(content) {
|
|
|
38
38
|
if (!parsed.ok) return undefined;
|
|
39
39
|
return parsed.document.type ?? 'any';
|
|
40
40
|
}
|
|
41
|
-
export function validate(library
|
|
41
|
+
export function validate(library, context = {
|
|
42
|
+
binaryTargets: []
|
|
43
|
+
}) {
|
|
44
|
+
const binaryTargets = new Set(context.binaryTargets);
|
|
42
45
|
const files = Object.keys(library).sort();
|
|
43
46
|
const documents = new Map();
|
|
44
47
|
for (const file of files){
|
|
48
|
+
if (binaryTargets.has(file)) return refuse(file, 'binary-target-document');
|
|
45
49
|
const parsed = parse(library[file], file);
|
|
46
50
|
documents.set(file, parsed);
|
|
47
51
|
if (!parsed.ok) return {
|
|
@@ -114,10 +118,10 @@ export function validate(library) {
|
|
|
114
118
|
if (expected === null) continue;
|
|
115
119
|
for (const target of targets){
|
|
116
120
|
const resolved = classifyHref(file, target);
|
|
117
|
-
if (resolved.kind !== 'path') return refuse(file, 'unresolved-reference', {
|
|
121
|
+
if (resolved.kind !== 'path' || binaryTargets.has(resolved.path)) return refuse(file, 'unresolved-reference', {
|
|
118
122
|
location: name
|
|
119
123
|
});
|
|
120
|
-
if (!(resolved.path
|
|
124
|
+
if (!documents.has(resolved.path)) continue;
|
|
121
125
|
const targetType = declaredTypeOf(library[resolved.path]);
|
|
122
126
|
if (targetType !== expected) return refuse(file, 'unresolved-reference', {
|
|
123
127
|
location: name
|
|
@@ -128,7 +132,7 @@ export function validate(library) {
|
|
|
128
132
|
for (const href of extractRelativeHrefs(body)){
|
|
129
133
|
const resolved = classifyHref(file, href);
|
|
130
134
|
if (resolved.kind === 'skip') continue;
|
|
131
|
-
if (resolved.kind === 'invalid' || !(resolved.path
|
|
135
|
+
if (resolved.kind === 'invalid' || !documents.has(resolved.path) && !binaryTargets.has(resolved.path)) {
|
|
132
136
|
return refuse(file, 'unresolved-link');
|
|
133
137
|
}
|
|
134
138
|
}
|
|
@@ -147,7 +151,7 @@ export function validate(library) {
|
|
|
147
151
|
for (const target of referenceTargets(spec, parsed.document.fields[name])){
|
|
148
152
|
const resolved = classifyHref(file, target);
|
|
149
153
|
if (resolved.kind !== 'path') continue;
|
|
150
|
-
if (resolved.path
|
|
154
|
+
if (documents.has(resolved.path)) continue;
|
|
151
155
|
const referrers = missing.get(resolved.path) ?? [];
|
|
152
156
|
referrers.push(file);
|
|
153
157
|
missing.set(resolved.path, referrers);
|
package/dist/validate.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/workspace/packages/mdmodel/src/validate.ts"],"sourcesContent":["import { readDefinition, type Definition, type FieldSpec } from './definition.js';\nimport { parse } from './document.js';\nimport { extractRelativeHrefs } from './links.js';\nimport { classifyHref, isTypesPath } from './paths.js';\nimport { refusal } from './refuse.js';\nimport { parseListSection } from './sections.js';\nimport { validateFields } from './schema.js';\nimport type { Document, Library, Validation } from './types.js';\nimport { bodyAfterFrontmatter } from './yaml.js';\n\nfunction refuse(\n file: string,\n rule: string,\n extra?: { location?: string; referrers?: readonly string[] },\n): Validation {\n return { verdict: 'refuse', ...refusal(file, rule, extra) };\n}\n\nfunction instanceType(document: Document, file: string): 'any' | 'definition' | 'invalid' | string {\n if (isTypesPath(file)) return 'definition';\n const raw = document.fields.type;\n if (raw === undefined || raw === null) return 'any';\n if (typeof raw !== 'string' || raw === '') return 'invalid';\n return raw;\n}\n\nfunction referenceTargets(spec: FieldSpec, value: unknown): string[] {\n if (spec.kind === 'reference' && typeof value === 'string') return [value];\n if (spec.kind === 'list' && spec.of.kind === 'reference' && Array.isArray(value)) {\n return value.filter((item): item is string => typeof item === 'string');\n }\n return [];\n}\n\nfunction expectedReferenceType(spec: FieldSpec): string | null {\n if (spec.kind === 'reference') return spec.to;\n if (spec.kind === 'list' && spec.of.kind === 'reference') return spec.of.to;\n return null;\n}\n\nfunction declaredTypeOf(content: string): string | undefined {\n const parsed = parse(content);\n if (!parsed.ok) return undefined;\n return parsed.document.type ?? 'any';\n}\n\nexport function validate(library: Library): Validation {\n const files = Object.keys(library).sort();\n const documents = new Map<string, ReturnType<typeof parse>>();\n for (const file of files) {\n const parsed = parse(library[file]!, file);\n documents.set(file, parsed);\n if (!parsed.ok) return { verdict: 'refuse', ...parsed.refusal };\n }\n\n const definitions = new Map<string, Definition>();\n for (const file of files) {\n if (!isTypesPath(file)) continue;\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const definition = readDefinition(file, parsed.document);\n if ('rule' in definition) return { verdict: 'refuse', ...definition };\n const existing = definitions.get(definition.name);\n if (existing !== undefined)\n return refuse(file, 'definition-duplicate', { location: definition.name });\n definitions.set(definition.name, definition);\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any') continue;\n if (kind === 'invalid' || kind === 'definition') {\n if (kind === 'definition' && isTypesPath(file)) continue;\n return refuse(file, 'unknown-type', { location: 'type' });\n }\n const definition = definitions.get(kind);\n if (definition === undefined) return refuse(file, 'unknown-type', { location: 'type' });\n const fieldFailure = validateFields(definition.fields, parsed.document.fields);\n if (fieldFailure !== undefined) {\n return refuse(file, fieldFailure.rule, { location: fieldFailure.field });\n }\n for (const [name, spec] of Object.entries(definition.sections)) {\n const body = parsed.document.sections[name];\n if (body === undefined) {\n if (spec.required) return refuse(file, 'required-section', { location: name });\n continue;\n }\n if (spec.kind === 'list' && !parseListSection(body)) {\n return refuse(file, 'structured-section', { location: name });\n }\n }\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const targets = referenceTargets(spec, parsed.document.fields[name]);\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of targets) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path')\n return refuse(file, 'unresolved-reference', { location: name });\n if (!(resolved.path in library)) continue;\n const targetType = declaredTypeOf(library[resolved.path]!);\n if (targetType !== expected)\n return refuse(file, 'unresolved-reference', { location: name });\n }\n }\n const body = bodyAfterFrontmatter(library[file]!);\n for (const href of extractRelativeHrefs(body)) {\n const resolved = classifyHref(file, href);\n if (resolved.kind === 'skip') continue;\n if (resolved.kind === 'invalid' || !(resolved.path in library)) {\n return refuse(file, 'unresolved-link');\n }\n }\n }\n\n const missing = new Map<string, string[]>();\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of referenceTargets(spec, parsed.document.fields[name])) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path') continue;\n if (resolved.path in library) continue;\n const referrers = missing.get(resolved.path) ?? [];\n referrers.push(file);\n missing.set(resolved.path, referrers);\n }\n }\n }\n const missingPaths = [...missing.keys()].sort();\n if (missingPaths.length > 0) {\n const path = missingPaths[0]!;\n const referrers = [...new Set(missing.get(path) ?? [])].sort();\n return refuse(path, 'referenced-missing-file', { referrers });\n }\n\n return { verdict: 'accept' };\n}\n"],"names":["readDefinition","parse","extractRelativeHrefs","classifyHref","isTypesPath","refusal","parseListSection","validateFields","bodyAfterFrontmatter","refuse","file","rule","extra","verdict","instanceType","document","raw","fields","type","undefined","referenceTargets","spec","value","kind","of","Array","isArray","filter","item","expectedReferenceType","to","declaredTypeOf","content","parsed","ok","validate","library","files","Object","keys","sort","documents","Map","set","definitions","get","definition","existing","name","location","fieldFailure","field","entries","sections","body","required","targets","expected","target","resolved","path","targetType","href","missing","referrers","push","missingPaths","length","Set"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/validate.ts"],"sourcesContent":["import { readDefinition, type Definition, type FieldSpec } from './definition.js';\nimport { parse } from './document.js';\nimport { extractRelativeHrefs } from './links.js';\nimport { classifyHref, isTypesPath } from './paths.js';\nimport { refusal } from './refuse.js';\nimport { parseListSection } from './sections.js';\nimport { validateFields } from './schema.js';\nimport type { Document, Library, Validation, ValidationContext } from './types.js';\nimport { bodyAfterFrontmatter } from './yaml.js';\n\nfunction refuse(\n file: string,\n rule: string,\n extra?: { location?: string; referrers?: readonly string[] },\n): Validation {\n return { verdict: 'refuse', ...refusal(file, rule, extra) };\n}\n\nfunction instanceType(document: Document, file: string): 'any' | 'definition' | 'invalid' | string {\n if (isTypesPath(file)) return 'definition';\n const raw = document.fields.type;\n if (raw === undefined || raw === null) return 'any';\n if (typeof raw !== 'string' || raw === '') return 'invalid';\n return raw;\n}\n\nfunction referenceTargets(spec: FieldSpec, value: unknown): string[] {\n if (spec.kind === 'reference' && typeof value === 'string') return [value];\n if (spec.kind === 'list' && spec.of.kind === 'reference' && Array.isArray(value)) {\n return value.filter((item): item is string => typeof item === 'string');\n }\n return [];\n}\n\nfunction expectedReferenceType(spec: FieldSpec): string | null {\n if (spec.kind === 'reference') return spec.to;\n if (spec.kind === 'list' && spec.of.kind === 'reference') return spec.of.to;\n return null;\n}\n\nfunction declaredTypeOf(content: string): string | undefined {\n const parsed = parse(content);\n if (!parsed.ok) return undefined;\n return parsed.document.type ?? 'any';\n}\n\nexport function validate(\n library: Library,\n context: ValidationContext = { binaryTargets: [] },\n): Validation {\n const binaryTargets = new Set(context.binaryTargets);\n const files = Object.keys(library).sort();\n const documents = new Map<string, ReturnType<typeof parse>>();\n for (const file of files) {\n if (binaryTargets.has(file)) return refuse(file, 'binary-target-document');\n const parsed = parse(library[file]!, file);\n documents.set(file, parsed);\n if (!parsed.ok) return { verdict: 'refuse', ...parsed.refusal };\n }\n\n const definitions = new Map<string, Definition>();\n for (const file of files) {\n if (!isTypesPath(file)) continue;\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const definition = readDefinition(file, parsed.document);\n if ('rule' in definition) return { verdict: 'refuse', ...definition };\n const existing = definitions.get(definition.name);\n if (existing !== undefined)\n return refuse(file, 'definition-duplicate', { location: definition.name });\n definitions.set(definition.name, definition);\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any') continue;\n if (kind === 'invalid' || kind === 'definition') {\n if (kind === 'definition' && isTypesPath(file)) continue;\n return refuse(file, 'unknown-type', { location: 'type' });\n }\n const definition = definitions.get(kind);\n if (definition === undefined) return refuse(file, 'unknown-type', { location: 'type' });\n const fieldFailure = validateFields(definition.fields, parsed.document.fields);\n if (fieldFailure !== undefined) {\n return refuse(file, fieldFailure.rule, { location: fieldFailure.field });\n }\n for (const [name, spec] of Object.entries(definition.sections)) {\n const body = parsed.document.sections[name];\n if (body === undefined) {\n if (spec.required) return refuse(file, 'required-section', { location: name });\n continue;\n }\n if (spec.kind === 'list' && !parseListSection(body)) {\n return refuse(file, 'structured-section', { location: name });\n }\n }\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const targets = referenceTargets(spec, parsed.document.fields[name]);\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of targets) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path' || binaryTargets.has(resolved.path))\n return refuse(file, 'unresolved-reference', { location: name });\n if (!documents.has(resolved.path)) continue;\n const targetType = declaredTypeOf(library[resolved.path]!);\n if (targetType !== expected)\n return refuse(file, 'unresolved-reference', { location: name });\n }\n }\n const body = bodyAfterFrontmatter(library[file]!);\n for (const href of extractRelativeHrefs(body)) {\n const resolved = classifyHref(file, href);\n if (resolved.kind === 'skip') continue;\n if (\n resolved.kind === 'invalid' ||\n (!documents.has(resolved.path) && !binaryTargets.has(resolved.path))\n ) {\n return refuse(file, 'unresolved-link');\n }\n }\n }\n\n const missing = new Map<string, string[]>();\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of referenceTargets(spec, parsed.document.fields[name])) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path') continue;\n if (documents.has(resolved.path)) continue;\n const referrers = missing.get(resolved.path) ?? [];\n referrers.push(file);\n missing.set(resolved.path, referrers);\n }\n }\n }\n const missingPaths = [...missing.keys()].sort();\n if (missingPaths.length > 0) {\n const path = missingPaths[0]!;\n const referrers = [...new Set(missing.get(path) ?? [])].sort();\n return refuse(path, 'referenced-missing-file', { referrers });\n }\n\n return { verdict: 'accept' };\n}\n"],"names":["readDefinition","parse","extractRelativeHrefs","classifyHref","isTypesPath","refusal","parseListSection","validateFields","bodyAfterFrontmatter","refuse","file","rule","extra","verdict","instanceType","document","raw","fields","type","undefined","referenceTargets","spec","value","kind","of","Array","isArray","filter","item","expectedReferenceType","to","declaredTypeOf","content","parsed","ok","validate","library","context","binaryTargets","Set","files","Object","keys","sort","documents","Map","has","set","definitions","get","definition","existing","name","location","fieldFailure","field","entries","sections","body","required","targets","expected","target","resolved","path","targetType","href","missing","referrers","push","missingPaths","length"],"mappings":"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"}
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.1.0-alpha.
|
|
1
|
+
export declare const VERSION = "0.1.0-alpha.3";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/dist/version.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/workspace/packages/mdmodel/src/version.ts"],"sourcesContent":["export const VERSION = '0.1.0-alpha.
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/version.ts"],"sourcesContent":["export const VERSION = '0.1.0-alpha.3';\n"],"names":["VERSION"],"mappings":"AAAA,OAAO,MAAMA,UAAU,gBAAgB"}
|
package/fixtures/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# Conformance fixtures
|
|
2
2
|
|
|
3
|
-
Each directory under `cases/` is one Library
|
|
4
|
-
Consumers load the files under `library/` as
|
|
5
|
-
`
|
|
3
|
+
Each directory under `cases/` is one text Library, one validation context,
|
|
4
|
+
and one expected verdict. Consumers load the files under `library/` as
|
|
5
|
+
path-to-content, load the required `context.json` as `ValidationContext`, and
|
|
6
|
+
compare `validate(library, context)` against `expected.json`. Text-only cases
|
|
7
|
+
carry `{ "binaryTargets": [] }`. Binary targets are membership declarations;
|
|
8
|
+
the corpus supplies no binary bytes or placeholder Documents.
|
|
6
9
|
|
|
7
10
|
## Verdict format
|
|
8
11
|
|
|
@@ -34,6 +37,7 @@ replace it with the package's semantic version before comparing.
|
|
|
34
37
|
|
|
35
38
|
| Rule | When |
|
|
36
39
|
| ------------------------- | ---------------------------------------------------------------------- |
|
|
40
|
+
| `binary-target-document` | A path is declared as both a text Document and a binary target |
|
|
37
41
|
| `frontmatter-fence` | A present frontmatter fence does not parse as the accepted YAML subset |
|
|
38
42
|
| `definition-type` | A `types/` file is not a definition, or its type name is empty |
|
|
39
43
|
| `definition-shape` | A definition carries a key other than `type`, `fields`, and `sections` |
|
|
@@ -55,7 +59,7 @@ replace it with the package's semantic version before comparing.
|
|
|
55
59
|
| `unresolved-reference` | A reference does not resolve to a current file of the required type |
|
|
56
60
|
| `unresolved-link` | A relative body link does not resolve to a current path |
|
|
57
61
|
| `structured-section` | A declared structured-list section does not parse as a list |
|
|
58
|
-
| `referenced-missing-file` | Remaining files still reference
|
|
62
|
+
| `referenced-missing-file` | Remaining files still reference an absent path |
|
|
59
63
|
|
|
60
64
|
## YAML subset
|
|
61
65
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": ["constructor"] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "verdict": "accept" }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{ "binaryTargets": [] }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentshouse/mdmodel",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.3",
|
|
4
4
|
"description": "MD Type language, parser, validator, structured change application, Markdown syntax profile, and conformance fixtures",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|