@agentshouse/mdmodel 0.1.0-c64dbada0730d → 0.1.0-c679f403bf3fb

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.
Files changed (53) hide show
  1. package/API.md +230 -216
  2. package/README.md +15 -18
  3. package/dist/blocks.d.ts.map +1 -1
  4. package/dist/blocks.js +7 -14
  5. package/dist/condition.d.ts +21 -8
  6. package/dist/condition.d.ts.map +1 -1
  7. package/dist/condition.js +208 -89
  8. package/dist/definition.d.ts +16 -1
  9. package/dist/definition.d.ts.map +1 -1
  10. package/dist/definition.js +255 -29
  11. package/dist/divide.d.ts.map +1 -1
  12. package/dist/divide.js +27 -17
  13. package/dist/document.d.ts +6 -3
  14. package/dist/document.d.ts.map +1 -1
  15. package/dist/document.js +315 -167
  16. package/dist/fields.d.ts +2 -0
  17. package/dist/fields.d.ts.map +1 -1
  18. package/dist/fields.js +7 -0
  19. package/dist/index.d.ts +14 -8
  20. package/dist/index.d.ts.map +1 -1
  21. package/dist/index.js +7 -5
  22. package/dist/links.d.ts +3 -0
  23. package/dist/links.d.ts.map +1 -1
  24. package/dist/links.js +66 -40
  25. package/dist/paths.d.ts +10 -1
  26. package/dist/paths.d.ts.map +1 -1
  27. package/dist/paths.js +115 -12
  28. package/dist/project.d.ts +1 -0
  29. package/dist/project.d.ts.map +1 -1
  30. package/dist/project.js +38 -15
  31. package/dist/references.d.ts +2 -2
  32. package/dist/references.d.ts.map +1 -1
  33. package/dist/references.js +6 -1
  34. package/dist/schema.js +2 -2
  35. package/dist/types.d.ts +49 -2
  36. package/dist/types.d.ts.map +1 -1
  37. package/dist/validate.d.ts +30 -2
  38. package/dist/validate.d.ts.map +1 -1
  39. package/dist/validate.js +290 -115
  40. package/dist/yaml.d.ts +7 -3
  41. package/dist/yaml.d.ts.map +1 -1
  42. package/dist/yaml.js +72 -43
  43. package/fixtures/README.md +6 -5
  44. package/fixtures/cases/cross-room-link/context.json +1 -0
  45. package/fixtures/cases/cross-room-link/expected.json +1 -0
  46. package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
  47. package/fixtures/cases/cross-room-link/schema.yaml +3 -0
  48. package/fixtures/cases/cross-room-reference/context.json +1 -0
  49. package/fixtures/cases/cross-room-reference/expected.json +1 -0
  50. package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
  51. package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
  52. package/fixtures/division.json +26 -26
  53. package/package.json +4 -2
package/dist/types.d.ts CHANGED
@@ -13,13 +13,14 @@ export type ModelVerification = {
13
13
  };
14
14
  export type ValidationContext = {
15
15
  readonly binaryTargets: readonly string[];
16
+ readonly anyRoom?: true;
16
17
  };
17
18
  export type ProjectionContext = {
18
19
  readonly documentTargets: readonly string[];
19
20
  readonly definition?: Definition;
20
21
  };
21
22
  export type DivisionContext = ProjectionContext & {
22
- readonly budget: number;
23
+ readonly bound: number;
23
24
  };
24
25
  export type Extent = {
25
26
  readonly start: number;
@@ -28,10 +29,12 @@ export type Extent = {
28
29
  export type Span = Extent & {
29
30
  readonly text: string;
30
31
  };
31
- export type Document = {
32
+ export type Frontmatter = {
32
33
  readonly content: string;
33
34
  readonly type: string | undefined;
34
35
  readonly fields: Readonly<Record<string, unknown>>;
36
+ };
37
+ export type Document = Frontmatter & {
35
38
  readonly preamble: string;
36
39
  readonly sections: Readonly<Record<string, string>>;
37
40
  };
@@ -41,11 +44,27 @@ export type Refusal = {
41
44
  readonly location?: string;
42
45
  readonly referrers?: readonly string[];
43
46
  };
47
+ export type Reached = {
48
+ readonly target: string | null;
49
+ readonly to: readonly string[];
50
+ };
51
+ export type DocumentCheck = {
52
+ readonly ok: false;
53
+ } | {
54
+ readonly ok: true;
55
+ readonly type: string;
56
+ readonly typed: boolean;
57
+ readonly references: readonly Reached[];
58
+ };
44
59
  export type Validation = {
45
60
  readonly verdict: 'accept';
46
61
  } | ({
47
62
  readonly verdict: 'refuse';
48
63
  } & Refusal);
64
+ export type ValidationStep = {
65
+ readonly path: string;
66
+ readonly resolved: number;
67
+ };
49
68
  export type Projection = {
50
69
  readonly ok: true;
51
70
  readonly text: string;
@@ -60,6 +79,13 @@ export type Division = {
60
79
  readonly ok: false;
61
80
  readonly refusal: Refusal;
62
81
  };
82
+ export type FrontmatterResult = {
83
+ readonly ok: true;
84
+ readonly frontmatter: Frontmatter;
85
+ } | {
86
+ readonly ok: false;
87
+ readonly refusal: Refusal;
88
+ };
63
89
  export type ParseResult = {
64
90
  readonly ok: true;
65
91
  readonly document: Document;
@@ -75,7 +101,27 @@ export type Reference = {
75
101
  readonly pointer: string;
76
102
  readonly value: string;
77
103
  readonly to: readonly string[];
104
+ readonly crossRoom?: true;
78
105
  };
106
+ export type RoomReference = {
107
+ readonly handle: string;
108
+ readonly path: string;
109
+ } & ({
110
+ readonly kind: 'link';
111
+ readonly href: string;
112
+ } | {
113
+ readonly kind: 'field';
114
+ readonly pointer: string;
115
+ readonly value: string;
116
+ readonly to: readonly string[];
117
+ readonly crossRoom?: true;
118
+ } | {
119
+ readonly kind: 'item';
120
+ readonly section: string;
121
+ readonly href: string;
122
+ readonly to: readonly string[];
123
+ readonly crossRoom?: true;
124
+ });
79
125
  export type Change = {
80
126
  readonly kind: 'field';
81
127
  readonly name: string;
@@ -106,6 +152,7 @@ export type ApplyResult = {
106
152
  } | {
107
153
  readonly outcome: 'stale';
108
154
  readonly document: Document;
155
+ readonly stale: readonly number[];
109
156
  } | {
110
157
  readonly outcome: 'refuse';
111
158
  readonly refusal: Refusal;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,32 @@
1
- import type { Library, ModelVerification, Validation, ValidationContext, VerifiedModel } from './types.js';
2
- export declare function verify(schema: string): ModelVerification;
1
+ import { type Definition } from './definition.js';
2
+ import type { DocumentCheck, Library, ModelVerification, Reached, RoomReference, Validation, ValidationContext, ValidationStep, VerifiedModel } from './types.js';
3
+ export declare function resolves(reference: Reached, typeOf: (path: string) => string | undefined, binary: (path: string) => boolean): boolean;
4
+ export declare function verify(schema: string, provided?: VerifiedModel): ModelVerification;
5
+ export declare function checkDocument(file: string, content: string, model: VerifiedModel, context?: Pick<ValidationContext, 'anyRoom'>): DocumentCheck;
6
+ export declare function sectionReferences(file: string, content: string, definition: Definition): readonly Reached[];
7
+ export declare function bodyRoomLinks(body: string): RoomReference[];
8
+ export declare function roomReferences(file: string, content: string, definition?: Definition): readonly RoomReference[];
9
+ type Placed = {
10
+ readonly reference: Reached;
11
+ readonly location: string;
12
+ };
13
+ export type Assessment = {
14
+ readonly file: string;
15
+ readonly type: string | undefined;
16
+ readonly targets: readonly string[];
17
+ readonly read: Validation | null;
18
+ readonly structured: Validation | null;
19
+ readonly fields: readonly Placed[];
20
+ readonly linked: boolean;
21
+ readonly sections: readonly Placed[];
22
+ };
23
+ export declare function assess(file: string, content: string, binary: boolean, model?: VerifiedModel, context?: Pick<ValidationContext, 'anyRoom'>): Assessment;
24
+ export type Verdicts = {
25
+ add(assessment: Assessment, typeOf: (path: string) => string | undefined, binary: (path: string) => boolean): number;
26
+ verdict(): Validation;
27
+ };
28
+ export declare function verdicts(): Verdicts;
29
+ export declare function validating(library: ReadonlyMap<string, string>, context?: ValidationContext, model?: VerifiedModel): Generator<ValidationStep, Validation, void>;
3
30
  export declare function validate(library: Library, context?: ValidationContext, model?: VerifiedModel): Validation;
31
+ export {};
4
32
  //# sourceMappingURL=validate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,OAAO,EACP,iBAAiB,EACjB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAwDpB,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAQxD;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,UAAU,CAqGZ"}
1
+ {"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQzF,OAAO,KAAK,EAEV,aAAa,EAEb,OAAO,EACP,iBAAiB,EACjB,OAAO,EACP,aAAa,EACb,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,aAAa,EACd,MAAM,YAAY,CAAC;AA8CpB,wBAAgB,QAAQ,CACtB,SAAS,EAAE,OAAO,EAClB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,OAAO,CAET;AA8BD,wBAAgB,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,aAAa,GAAG,iBAAiB,CAQlF;AAoED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,aAAa,EACpB,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAM,GAC/C,aAAa,CA0Bf;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,UAAU,GACrB,SAAS,OAAO,EAAE,CAiBpB;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CAO3D;AAED,wBAAgB,cAAc,CAC5B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,UAAU,GACtB,SAAS,aAAa,EAAE,CAsC1B;AAQD,KAAK,MAAM,GAAG;IAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzE,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IACvC,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAEF,wBAAgB,MAAM,CACpB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,OAAO,EACf,KAAK,GAAE,aAA6B,EACpC,OAAO,GAAE,IAAI,CAAC,iBAAiB,EAAE,SAAS,CAAM,GAC/C,UAAU,CA0CZ;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,GAAG,CACD,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAC5C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,GAChC,MAAM,CAAC;IACV,OAAO,IAAI,UAAU,CAAC;CACvB,CAAC;AAEF,wBAAgB,QAAQ,IAAI,QAAQ,CA+DnC;AAED,wBAAiB,UAAU,CACzB,OAAO,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EACpC,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,SAAS,CAAC,cAAc,EAAE,UAAU,EAAE,IAAI,CAAC,CAiB7C;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,UAAU,CAKZ"}
package/dist/validate.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ATTACHMENT, BUILT_IN_TYPE, readSchema } from './definition.js';
2
2
  import { parse } from './document.js';
3
3
  import { hrefOccurrences, linkInventory } from './links.js';
4
- import { classifyHref } from './paths.js';
4
+ import { classifyHref, roomTarget } from './paths.js';
5
5
  import { references } from './references.js';
6
6
  import { refusal } from './refuse.js';
7
7
  import { fitsItem, frontmatterRefusal } from './schema.js';
@@ -18,33 +18,50 @@ function instanceType(document) {
18
18
  return null;
19
19
  return raw;
20
20
  }
21
- function reaches(file, href, to, types, binaryTargets) {
22
- const resolved = classifyHref(file, href);
23
- if (resolved.kind !== 'path')
21
+ function reaches(reference, typeOf, binary) {
22
+ if (reference.target === null)
24
23
  return false;
25
- if (to.includes(ATTACHMENT))
24
+ if (reference.to.includes(ATTACHMENT))
26
25
  return true;
27
- if (binaryTargets.has(resolved.path))
26
+ if (binary(reference.target))
27
+ return false;
28
+ const held = typeOf(reference.target);
29
+ return held === undefined || reference.to.includes(held);
30
+ }
31
+ function missing(reference, typeOf, binary) {
32
+ if (reference.to.includes(ATTACHMENT) || reference.target === null)
28
33
  return false;
29
- const held = types.get(resolved.path);
30
- return held === undefined || to.includes(held);
34
+ return typeOf(reference.target) === undefined && !binary(reference.target);
35
+ }
36
+ export function resolves(reference, typeOf, binary) {
37
+ return reaches(reference, typeOf, binary) && !missing(reference, typeOf, binary);
31
38
  }
32
- function itemHrefs(content, items) {
33
- const bodyStart = bodyStartOf(content);
34
- const { uses } = linkInventory(content.slice(bodyStart));
39
+ function usesIn(content) {
40
+ let held;
41
+ return () => {
42
+ if (held !== undefined)
43
+ return held;
44
+ const bodyStart = bodyStartOf(content);
45
+ held = linkInventory(content.slice(bodyStart)).uses.map((use) => ({
46
+ ...use,
47
+ start: bodyStart + use.start,
48
+ end: bodyStart + use.end,
49
+ }));
50
+ return held;
51
+ };
52
+ }
53
+ function itemHrefs(content, items, uses) {
35
54
  const hrefs = [];
36
55
  for (const item of items) {
37
- const link = uses.find((use) => bodyStart + use.start === item.start &&
38
- bodyStart + use.end === item.end &&
39
- content[item.start] === '[');
56
+ const link = uses().find((use) => use.start === item.start && use.end === item.end && content[item.start] === '[');
40
57
  if (link === undefined)
41
58
  return null;
42
59
  hrefs.push(link.destination.href);
43
60
  }
44
61
  return hrefs;
45
62
  }
46
- export function verify(schema) {
47
- const read = readSchema(schema);
63
+ export function verify(schema, provided) {
64
+ const read = readSchema(schema, provided);
48
65
  if ('types' in read)
49
66
  return { verdict: 'accept', model: read };
50
67
  return {
@@ -53,114 +70,272 @@ export function verify(schema) {
53
70
  ...(read.location === undefined ? {} : { location: read.location }),
54
71
  };
55
72
  }
56
- export function validate(library, context = { binaryTargets: [] }, model = { types: {} }) {
57
- const binaryTargets = new Set(context.binaryTargets);
58
- const files = Object.keys(library).sort();
59
- const types = new Map();
60
- const documents = new Map();
61
- for (const file of files) {
62
- if (binaryTargets.has(file))
63
- return refuse(file, 'binary-target-document');
64
- const parsed = parse(library[file], file);
65
- if (!parsed.ok)
66
- return { verdict: 'refuse', ...parsed.refusal };
67
- types.set(file, parsed.document.type ?? BUILT_IN_TYPE);
68
- if (instanceType(parsed.document) !== BUILT_IN_TYPE)
69
- documents.set(file, parsed.document);
73
+ function structure(file, content, document, definition) {
74
+ if (definition === undefined)
75
+ return { refusal: refuse(file, 'unknown-type', { location: '/type' }) };
76
+ const fieldFailure = frontmatterRefusal(definition, document.fields);
77
+ if (fieldFailure !== undefined) {
78
+ return { refusal: refuse(file, fieldFailure.rule, { location: fieldFailure.location }) };
70
79
  }
71
- const definitions = new Map(Object.entries(model.types));
72
- const sectionReferences = new Map();
73
- for (const [file, document] of documents) {
74
- const kind = instanceType(document);
75
- if (kind === BUILT_IN_TYPE)
80
+ const spans = headingSpans(content, bodyStartOf(content));
81
+ const uses = usesIn(content);
82
+ const sections = [];
83
+ for (const [name, spec] of Object.entries(definition.sections)) {
84
+ const occurrences = spans.filter((one) => one.name === name);
85
+ if (occurrences.length === 0 && spec.required)
86
+ return { refusal: refuse(file, 'required-section', { location: name }) };
87
+ if (spec.kind !== 'list')
76
88
  continue;
77
- const definition = kind === null ? undefined : definitions.get(kind);
78
- if (definition === undefined)
79
- return refuse(file, 'unknown-type', { location: '/type' });
80
- const fieldFailure = frontmatterRefusal(definition, document.fields);
81
- if (fieldFailure !== undefined) {
82
- return refuse(file, fieldFailure.rule, { location: fieldFailure.location });
83
- }
84
- const content = library[file];
85
- const spans = headingSpans(content, bodyStartOf(content));
86
- const references = [];
87
- for (const [name, spec] of Object.entries(definition.sections)) {
88
- const occurrences = spans.filter((one) => one.name === name);
89
- if (occurrences.length === 0 && spec.required)
90
- return refuse(file, 'required-section', { location: name });
91
- if (spec.kind !== 'list')
89
+ for (const span of occurrences) {
90
+ const items = listItems(content, span.bodyStart, span.bodyEnd);
91
+ if (items === null ||
92
+ items.some((item) => !fitsItem(definition, name, content.slice(item.start, item.end))))
93
+ return { refusal: refuse(file, 'structured-section', { location: name }) };
94
+ if (spec.items.reference === undefined)
92
95
  continue;
93
- for (const span of occurrences) {
94
- const items = listItems(content, span.bodyStart, span.bodyEnd);
95
- if (items === null ||
96
- items.some((item) => !fitsItem(definition, name, content.slice(item.start, item.end))))
97
- return refuse(file, 'structured-section', { location: name });
98
- if (spec.items.reference === undefined)
99
- continue;
100
- const hrefs = itemHrefs(content, items);
101
- if (hrefs === null)
102
- return refuse(file, 'structured-section', { location: name });
103
- references.push({ section: name, to: spec.items.reference, hrefs });
104
- }
96
+ const hrefs = itemHrefs(content, items, uses);
97
+ if (hrefs === null)
98
+ return { refusal: refuse(file, 'structured-section', { location: name }) };
99
+ sections.push({
100
+ section: name,
101
+ to: spec.items.reference,
102
+ crossRoom: spec.items.crossRoom === true,
103
+ hrefs,
104
+ });
105
105
  }
106
- sectionReferences.set(file, references);
107
106
  }
108
- for (const [file, document] of documents) {
109
- const kind = instanceType(document);
110
- if (kind === null || kind === BUILT_IN_TYPE)
111
- continue;
112
- const definition = definitions.get(kind);
113
- if (definition === undefined)
107
+ return { sections };
108
+ }
109
+ function linked(file, content) {
110
+ return hrefOccurrences(bodyAfterFrontmatter(content)).every((occurrence) => classifyHref(file, occurrence.href).kind !== 'invalid');
111
+ }
112
+ function reached(file, href, to) {
113
+ const resolved = classifyHref(file, href);
114
+ return { target: resolved.kind === 'path' ? resolved.path : null, to };
115
+ }
116
+ function crossing(file, href, crossRoom) {
117
+ return crossRoom === true && classifyHref(file, href).kind === 'room';
118
+ }
119
+ function definitionOf(document, model) {
120
+ const kind = instanceType(document);
121
+ return kind === null || !Object.hasOwn(model.types, kind) ? undefined : model.types[kind];
122
+ }
123
+ export function checkDocument(file, content, model, context = {}) {
124
+ const anyRoom = context.anyRoom === true;
125
+ const parsed = parse(content, file);
126
+ if (!parsed.ok)
127
+ return { ok: false };
128
+ const document = parsed.document;
129
+ const type = document.type ?? BUILT_IN_TYPE;
130
+ if (instanceType(document) === BUILT_IN_TYPE)
131
+ return { ok: true, type, typed: false, references: [] };
132
+ const definition = definitionOf(document, model);
133
+ const read = structure(file, content, document, definition);
134
+ if ('refusal' in read || definition === undefined || !linked(file, content))
135
+ return { ok: false };
136
+ return {
137
+ ok: true,
138
+ type,
139
+ typed: true,
140
+ references: [
141
+ ...references(document, definition).flatMap(({ value, to, crossRoom }) => crossing(file, value, anyRoom || crossRoom) ? [] : [reached(file, value, to)]),
142
+ ...read.sections.flatMap(({ to, crossRoom, hrefs }) => hrefs.flatMap((href) => crossing(file, href, anyRoom || crossRoom) ? [] : [reached(file, href, to)])),
143
+ ],
144
+ };
145
+ }
146
+ export function sectionReferences(file, content, definition) {
147
+ const referring = (name) => {
148
+ const spec = Object.hasOwn(definition.sections, name) ? definition.sections[name] : undefined;
149
+ return spec?.kind === 'list' && spec.items.reference !== undefined ? spec.items : undefined;
150
+ };
151
+ if (!Object.keys(definition.sections).some((name) => referring(name) !== undefined))
152
+ return [];
153
+ const uses = usesIn(content);
154
+ const found = [];
155
+ for (const span of headingSpans(content, bodyStartOf(content))) {
156
+ const items = referring(span.name);
157
+ if (items === undefined)
114
158
  continue;
115
- for (const { pointer, to, value } of references(document, definition)) {
116
- if (!reaches(file, value, to, types, binaryTargets))
117
- return refuse(file, 'unresolved-reference', { location: pointer });
118
- }
119
- const body = bodyAfterFrontmatter(library[file]);
120
- for (const occurrence of hrefOccurrences(body)) {
121
- const resolved = classifyHref(file, occurrence.href);
122
- if (resolved.kind === 'invalid')
123
- return refuse(file, 'unresolved-link');
124
- }
125
- for (const { section, to, hrefs } of sectionReferences.get(file)) {
126
- for (const href of hrefs) {
127
- if (!reaches(file, href, to, types, binaryTargets))
128
- return refuse(file, 'unresolved-reference', { location: section });
129
- }
130
- }
159
+ const listed = listItems(content, span.bodyStart, span.bodyEnd);
160
+ const hrefs = listed === null ? null : itemHrefs(content, listed, uses);
161
+ for (const href of hrefs ?? [])
162
+ if (!crossing(file, href, items.crossRoom))
163
+ found.push(reached(file, href, items.reference));
131
164
  }
132
- const missing = new Map();
133
- for (const [file, document] of documents) {
134
- const kind = instanceType(document);
135
- if (kind === null || kind === BUILT_IN_TYPE)
136
- continue;
137
- const definition = definitions.get(kind);
138
- if (definition === undefined)
165
+ return found;
166
+ }
167
+ export function bodyRoomLinks(body) {
168
+ const found = [];
169
+ for (const href of new Set(hrefOccurrences(body).map((occurrence) => occurrence.href))) {
170
+ const room = roomTarget(href);
171
+ if (room !== null)
172
+ found.push({ kind: 'link', href, ...room });
173
+ }
174
+ return found;
175
+ }
176
+ export function roomReferences(file, content, definition) {
177
+ const found = bodyRoomLinks(bodyAfterFrontmatter(content));
178
+ if (definition === undefined)
179
+ return found;
180
+ const parsed = parse(content, file);
181
+ if (!parsed.ok)
182
+ return found;
183
+ for (const { pointer, value, to, crossRoom } of references(parsed.document, definition)) {
184
+ const room = roomTarget(value);
185
+ if (room !== null)
186
+ found.push({
187
+ kind: 'field',
188
+ pointer,
189
+ value,
190
+ to,
191
+ ...room,
192
+ ...(crossRoom ? { crossRoom } : {}),
193
+ });
194
+ }
195
+ const uses = usesIn(content);
196
+ for (const span of headingSpans(content, bodyStartOf(content))) {
197
+ const spec = Object.hasOwn(definition.sections, span.name)
198
+ ? definition.sections[span.name]
199
+ : undefined;
200
+ if (spec?.kind !== 'list' || spec.items.reference === undefined)
139
201
  continue;
140
- const named = [
141
- ...references(document, definition),
142
- ...sectionReferences
143
- .get(file)
144
- .flatMap(({ to, hrefs }) => hrefs.map((value) => ({ value, to }))),
145
- ];
146
- for (const { value, to } of named) {
147
- if (to.includes(ATTACHMENT))
148
- continue;
149
- const resolved = classifyHref(file, value);
150
- if (resolved.kind !== 'path')
151
- continue;
152
- if (types.has(resolved.path) || binaryTargets.has(resolved.path))
153
- continue;
154
- const referrers = missing.get(resolved.path) ?? [];
155
- referrers.push(file);
156
- missing.set(resolved.path, referrers);
202
+ const listed = listItems(content, span.bodyStart, span.bodyEnd);
203
+ for (const href of (listed === null ? null : itemHrefs(content, listed, uses)) ?? []) {
204
+ const room = roomTarget(href);
205
+ if (room !== null)
206
+ found.push({
207
+ kind: 'item',
208
+ section: span.name,
209
+ href,
210
+ to: spec.items.reference,
211
+ ...room,
212
+ ...(spec.items.crossRoom === true ? { crossRoom: true } : {}),
213
+ });
157
214
  }
158
215
  }
159
- const missingPaths = [...missing.keys()].sort();
160
- if (missingPaths.length > 0) {
161
- const path = missingPaths[0];
162
- const referrers = [...new Set(missing.get(path) ?? [])].sort();
163
- return refuse(path, 'referenced-missing-file', { referrers });
216
+ return found;
217
+ }
218
+ function least(refused, file, verdict) {
219
+ return refused === undefined || file < refused.file ? { file, verdict } : refused;
220
+ }
221
+ export function assess(file, content, binary, model = { types: {} }, context = {}) {
222
+ const unread = { file, type: undefined, targets: [], structured: null, fields: [], sections: [] };
223
+ if (binary)
224
+ return { ...unread, read: refuse(file, 'binary-target-document'), linked: true };
225
+ const parsed = parse(content, file);
226
+ if (!parsed.ok)
227
+ return { ...unread, read: { verdict: 'refuse', ...parsed.refusal }, linked: true };
228
+ const document = parsed.document;
229
+ const type = document.type ?? BUILT_IN_TYPE;
230
+ const typed = { file, type, read: null, structured: null };
231
+ if (instanceType(document) === BUILT_IN_TYPE) {
232
+ return { ...typed, targets: [], fields: [], linked: true, sections: [] };
233
+ }
234
+ const definition = definitionOf(document, model);
235
+ const read = structure(file, content, document, definition);
236
+ if ('refusal' in read || definition === undefined) {
237
+ return {
238
+ ...typed,
239
+ targets: [],
240
+ structured: 'refusal' in read ? read.refusal : null,
241
+ fields: [],
242
+ linked: true,
243
+ sections: [],
244
+ };
245
+ }
246
+ const anyRoom = context.anyRoom === true;
247
+ const fields = references(document, definition).flatMap(({ pointer, value, to, crossRoom }) => crossing(file, value, anyRoom || crossRoom)
248
+ ? []
249
+ : [{ reference: reached(file, value, to), location: pointer }]);
250
+ const sections = read.sections.flatMap(({ section, to, crossRoom, hrefs }) => hrefs.flatMap((href) => crossing(file, href, anyRoom || crossRoom)
251
+ ? []
252
+ : [{ reference: reached(file, href, to), location: section }]));
253
+ const targets = new Set();
254
+ for (const { reference } of [...fields, ...sections]) {
255
+ if (reference.target !== null)
256
+ targets.add(reference.target);
257
+ }
258
+ return { ...typed, targets: [...targets], fields, linked: linked(file, content), sections };
259
+ }
260
+ export function verdicts() {
261
+ let read;
262
+ let structured;
263
+ let referred;
264
+ let missed;
265
+ const unreached = (placed, typeOf, binary) => placed.find(({ reference }) => !reaches(reference, typeOf, binary));
266
+ return {
267
+ add(assessment, typeOf, binary) {
268
+ const { file } = assessment;
269
+ if (assessment.read !== null) {
270
+ read = least(read, file, assessment.read);
271
+ return 0;
272
+ }
273
+ if (assessment.structured !== null) {
274
+ structured = least(structured, file, assessment.structured);
275
+ return 0;
276
+ }
277
+ const field = unreached(assessment.fields, typeOf, binary);
278
+ if (field !== undefined) {
279
+ referred = least(referred, file, refuse(file, 'unresolved-reference', { location: field.location }));
280
+ return 0;
281
+ }
282
+ if (!assessment.linked) {
283
+ referred = least(referred, file, refuse(file, 'unresolved-link'));
284
+ return 0;
285
+ }
286
+ const section = unreached(assessment.sections, typeOf, binary);
287
+ if (section !== undefined) {
288
+ referred = least(referred, file, refuse(file, 'unresolved-reference', { location: section.location }));
289
+ return 0;
290
+ }
291
+ const all = [...assessment.fields, ...assessment.sections];
292
+ for (const { reference } of all) {
293
+ if (!missing(reference, typeOf, binary))
294
+ continue;
295
+ const path = reference.target;
296
+ if (missed === undefined || path < missed.path)
297
+ missed = { path, referrers: [] };
298
+ if (path === missed.path && missed.referrers.at(-1) !== file)
299
+ missed.referrers.push(file);
300
+ }
301
+ return all.length;
302
+ },
303
+ verdict() {
304
+ const refused = read ?? structured ?? referred;
305
+ if (refused !== undefined)
306
+ return refused.verdict;
307
+ if (missed !== undefined) {
308
+ return refuse(missed.path, 'referenced-missing-file', {
309
+ referrers: [...missed.referrers].sort(),
310
+ });
311
+ }
312
+ return { verdict: 'accept' };
313
+ },
314
+ };
315
+ }
316
+ export function* validating(library, context = { binaryTargets: [] }, model = { types: {} }) {
317
+ const binaryTargets = new Set(context.binaryTargets);
318
+ const binary = (path) => binaryTargets.has(path);
319
+ const types = new Map();
320
+ const assessments = [];
321
+ for (const [file, content] of library) {
322
+ const assessment = assess(file, content, binary(file), model, context);
323
+ if (assessment.type !== undefined)
324
+ types.set(file, assessment.type);
325
+ assessments.push(assessment);
326
+ yield { path: file, resolved: 0 };
327
+ }
328
+ const judged = verdicts();
329
+ for (const assessment of assessments) {
330
+ const resolved = judged.add(assessment, (path) => types.get(path), binary);
331
+ yield { path: assessment.file, resolved };
164
332
  }
165
- return { verdict: 'accept' };
333
+ return judged.verdict();
334
+ }
335
+ export function validate(library, context = { binaryTargets: [] }, model = { types: {} }) {
336
+ const steps = validating(new Map(Object.entries(library)), context, model);
337
+ let step = steps.next();
338
+ while (step.done !== true)
339
+ step = steps.next();
340
+ return step.value;
166
341
  }
package/dist/yaml.d.ts CHANGED
@@ -16,8 +16,7 @@ export type YamlSeq = {
16
16
  };
17
17
  export type YamlEntry = {
18
18
  readonly key: string;
19
- readonly keyStart: number;
20
- readonly keyEnd: number;
19
+ readonly after: number;
21
20
  readonly value: YamlNode;
22
21
  };
23
22
  export type YamlMap = {
@@ -32,7 +31,12 @@ export declare function parseYamlMapping(text: string, start: number, end: numbe
32
31
  export declare function jsValue(node: YamlNode): unknown;
33
32
  export declare function mapEntry(map: YamlMap, key: string): YamlEntry | undefined;
34
33
  export declare function isPlainSafe(text: string): boolean;
35
- export declare function serializeJs(value: unknown): string;
34
+ export type FrontmatterValue = string | number | boolean | null | readonly FrontmatterValue[] | {
35
+ readonly [name: string]: FrontmatterValue;
36
+ };
37
+ export declare function plain(value: unknown): value is Record<string, unknown>;
38
+ export declare function frontmatterValue(value: unknown): value is FrontmatterValue;
39
+ export declare function serializeJs(value: FrontmatterValue): string;
36
40
  export declare function isRecord(value: unknown): value is Record<string, unknown>;
37
41
  export declare function serializeKey(name: string): string;
38
42
  export declare function bodyStartAfterYaml(content: string, yamlEnd: number): number;