@agentshouse/mdmodel 0.1.0-cc9fa0498a7f7 → 0.1.0-cd90851746292
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/API.md +231 -225
- package/README.md +16 -19
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +35 -20
- package/dist/condition.d.ts +41 -11
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +223 -87
- package/dist/definition.d.ts +17 -1
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +319 -43
- package/dist/divide.d.ts.map +1 -1
- package/dist/divide.js +27 -17
- package/dist/document.d.ts +6 -3
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +326 -176
- package/dist/index.d.ts +13 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -6
- package/dist/links.d.ts +3 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +108 -51
- package/dist/paths.d.ts +10 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +118 -12
- package/dist/pattern.d.ts +10 -0
- package/dist/pattern.d.ts.map +1 -0
- package/dist/pattern.js +355 -0
- package/dist/project.d.ts +1 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +38 -15
- package/dist/references.d.ts +2 -2
- package/dist/references.d.ts.map +1 -1
- package/dist/references.js +6 -1
- package/dist/schema.d.ts +1 -0
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +55 -4
- package/dist/types.d.ts +50 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/validate.d.ts +30 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +317 -114
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +66 -21
- package/fixtures/README.md +10 -5
- package/fixtures/cases/conditional-section/context.json +1 -0
- package/fixtures/cases/conditional-section/expected.json +6 -0
- package/fixtures/cases/conditional-section/library/questions/hosting.md +9 -0
- package/fixtures/cases/conditional-section/library/questions/payments.md +12 -0
- package/fixtures/cases/conditional-section/schema.yaml +14 -0
- package/fixtures/cases/cross-room-link/context.json +1 -0
- package/fixtures/cases/cross-room-link/expected.json +1 -0
- package/fixtures/cases/cross-room-link/library/clients/acme.md +6 -0
- package/fixtures/cases/cross-room-link/schema.yaml +3 -0
- package/fixtures/cases/cross-room-reference/context.json +1 -0
- package/fixtures/cases/cross-room-reference/expected.json +1 -0
- package/fixtures/cases/cross-room-reference/library/clients/acme.md +9 -0
- package/fixtures/cases/cross-room-reference/schema.yaml +9 -0
- package/fixtures/division.json +26 -26
- package/package.json +10 -3
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { Definition } from './definition.js';
|
|
|
2
2
|
export type Library = Readonly<Record<string, string>>;
|
|
3
3
|
export type VerifiedModel = {
|
|
4
4
|
readonly types: Readonly<Record<string, Definition>>;
|
|
5
|
+
readonly nameable?: readonly string[];
|
|
5
6
|
};
|
|
6
7
|
export type ModelVerification = {
|
|
7
8
|
readonly verdict: 'accept';
|
|
@@ -13,13 +14,14 @@ export type ModelVerification = {
|
|
|
13
14
|
};
|
|
14
15
|
export type ValidationContext = {
|
|
15
16
|
readonly binaryTargets: readonly string[];
|
|
17
|
+
readonly anyRoom?: true;
|
|
16
18
|
};
|
|
17
19
|
export type ProjectionContext = {
|
|
18
20
|
readonly documentTargets: readonly string[];
|
|
19
21
|
readonly definition?: Definition;
|
|
20
22
|
};
|
|
21
23
|
export type DivisionContext = ProjectionContext & {
|
|
22
|
-
readonly
|
|
24
|
+
readonly bound: number;
|
|
23
25
|
};
|
|
24
26
|
export type Extent = {
|
|
25
27
|
readonly start: number;
|
|
@@ -28,10 +30,12 @@ export type Extent = {
|
|
|
28
30
|
export type Span = Extent & {
|
|
29
31
|
readonly text: string;
|
|
30
32
|
};
|
|
31
|
-
export type
|
|
33
|
+
export type Frontmatter = {
|
|
32
34
|
readonly content: string;
|
|
33
35
|
readonly type: string | undefined;
|
|
34
36
|
readonly fields: Readonly<Record<string, unknown>>;
|
|
37
|
+
};
|
|
38
|
+
export type Document = Frontmatter & {
|
|
35
39
|
readonly preamble: string;
|
|
36
40
|
readonly sections: Readonly<Record<string, string>>;
|
|
37
41
|
};
|
|
@@ -41,11 +45,27 @@ export type Refusal = {
|
|
|
41
45
|
readonly location?: string;
|
|
42
46
|
readonly referrers?: readonly string[];
|
|
43
47
|
};
|
|
48
|
+
export type Reached = {
|
|
49
|
+
readonly target: string | null;
|
|
50
|
+
readonly to: readonly string[];
|
|
51
|
+
};
|
|
52
|
+
export type DocumentCheck = {
|
|
53
|
+
readonly ok: false;
|
|
54
|
+
} | {
|
|
55
|
+
readonly ok: true;
|
|
56
|
+
readonly type: string;
|
|
57
|
+
readonly typed: boolean;
|
|
58
|
+
readonly references: readonly Reached[];
|
|
59
|
+
};
|
|
44
60
|
export type Validation = {
|
|
45
61
|
readonly verdict: 'accept';
|
|
46
62
|
} | ({
|
|
47
63
|
readonly verdict: 'refuse';
|
|
48
64
|
} & Refusal);
|
|
65
|
+
export type ValidationStep = {
|
|
66
|
+
readonly path: string;
|
|
67
|
+
readonly resolved: number;
|
|
68
|
+
};
|
|
49
69
|
export type Projection = {
|
|
50
70
|
readonly ok: true;
|
|
51
71
|
readonly text: string;
|
|
@@ -60,6 +80,13 @@ export type Division = {
|
|
|
60
80
|
readonly ok: false;
|
|
61
81
|
readonly refusal: Refusal;
|
|
62
82
|
};
|
|
83
|
+
export type FrontmatterResult = {
|
|
84
|
+
readonly ok: true;
|
|
85
|
+
readonly frontmatter: Frontmatter;
|
|
86
|
+
} | {
|
|
87
|
+
readonly ok: false;
|
|
88
|
+
readonly refusal: Refusal;
|
|
89
|
+
};
|
|
63
90
|
export type ParseResult = {
|
|
64
91
|
readonly ok: true;
|
|
65
92
|
readonly document: Document;
|
|
@@ -75,7 +102,27 @@ export type Reference = {
|
|
|
75
102
|
readonly pointer: string;
|
|
76
103
|
readonly value: string;
|
|
77
104
|
readonly to: readonly string[];
|
|
105
|
+
readonly crossRoom?: true;
|
|
78
106
|
};
|
|
107
|
+
export type RoomReference = {
|
|
108
|
+
readonly handle: string;
|
|
109
|
+
readonly path: string;
|
|
110
|
+
} & ({
|
|
111
|
+
readonly kind: 'link';
|
|
112
|
+
readonly href: string;
|
|
113
|
+
} | {
|
|
114
|
+
readonly kind: 'field';
|
|
115
|
+
readonly pointer: string;
|
|
116
|
+
readonly value: string;
|
|
117
|
+
readonly to: readonly string[];
|
|
118
|
+
readonly crossRoom?: true;
|
|
119
|
+
} | {
|
|
120
|
+
readonly kind: 'item';
|
|
121
|
+
readonly section: string;
|
|
122
|
+
readonly href: string;
|
|
123
|
+
readonly to: readonly string[];
|
|
124
|
+
readonly crossRoom?: true;
|
|
125
|
+
});
|
|
79
126
|
export type Change = {
|
|
80
127
|
readonly kind: 'field';
|
|
81
128
|
readonly name: string;
|
|
@@ -106,6 +153,7 @@ export type ApplyResult = {
|
|
|
106
153
|
} | {
|
|
107
154
|
readonly outcome: 'stale';
|
|
108
155
|
readonly document: Document;
|
|
156
|
+
readonly stale: readonly number[];
|
|
109
157
|
} | {
|
|
110
158
|
readonly outcome: 'refuse';
|
|
111
159
|
readonly refusal: Refusal;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAElD,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAC1B,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/validate.d.ts
CHANGED
|
@@ -1,4 +1,32 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
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
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AASzF,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;AA0ED,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,CA0BZ;AAyCD,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,CAsB7C;AAED,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,EAClD,KAAK,GAAE,aAA6B,GACnC,UAAU,CAKZ"}
|
package/dist/validate.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
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
|
-
import { fitsItem, frontmatterRefusal } from './schema.js';
|
|
7
|
+
import { conditionedSections, fitsItem, frontmatterRefusal } from './schema.js';
|
|
8
|
+
import { openPatternBudget, PatternTooCostly } from './pattern.js';
|
|
8
9
|
import { headingSpans, listItems } from './sections.js';
|
|
9
10
|
import { bodyAfterFrontmatter, bodyStartOf } from './yaml.js';
|
|
10
11
|
function refuse(file, rule, extra) {
|
|
@@ -18,33 +19,50 @@ function instanceType(document) {
|
|
|
18
19
|
return null;
|
|
19
20
|
return raw;
|
|
20
21
|
}
|
|
21
|
-
function reaches(
|
|
22
|
-
|
|
23
|
-
if (resolved.kind !== 'path')
|
|
22
|
+
function reaches(reference, typeOf, binary) {
|
|
23
|
+
if (reference.target === null)
|
|
24
24
|
return false;
|
|
25
|
-
if (to.includes(ATTACHMENT))
|
|
25
|
+
if (reference.to.includes(ATTACHMENT))
|
|
26
26
|
return true;
|
|
27
|
-
if (
|
|
27
|
+
if (binary(reference.target))
|
|
28
|
+
return false;
|
|
29
|
+
const held = typeOf(reference.target);
|
|
30
|
+
return held === undefined || reference.to.includes(held);
|
|
31
|
+
}
|
|
32
|
+
function missing(reference, typeOf, binary) {
|
|
33
|
+
if (reference.to.includes(ATTACHMENT) || reference.target === null)
|
|
28
34
|
return false;
|
|
29
|
-
|
|
30
|
-
|
|
35
|
+
return typeOf(reference.target) === undefined && !binary(reference.target);
|
|
36
|
+
}
|
|
37
|
+
export function resolves(reference, typeOf, binary) {
|
|
38
|
+
return reaches(reference, typeOf, binary) && !missing(reference, typeOf, binary);
|
|
31
39
|
}
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
40
|
+
function usesIn(content) {
|
|
41
|
+
let held;
|
|
42
|
+
return () => {
|
|
43
|
+
if (held !== undefined)
|
|
44
|
+
return held;
|
|
45
|
+
const bodyStart = bodyStartOf(content);
|
|
46
|
+
held = linkInventory(content.slice(bodyStart)).uses.map((use) => ({
|
|
47
|
+
...use,
|
|
48
|
+
start: bodyStart + use.start,
|
|
49
|
+
end: bodyStart + use.end,
|
|
50
|
+
}));
|
|
51
|
+
return held;
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function itemHrefs(content, items, uses) {
|
|
35
55
|
const hrefs = [];
|
|
36
56
|
for (const item of items) {
|
|
37
|
-
const link = uses.find((use) =>
|
|
38
|
-
bodyStart + use.end === item.end &&
|
|
39
|
-
content[item.start] === '[');
|
|
57
|
+
const link = uses().find((use) => use.start === item.start && use.end === item.end && content[item.start] === '[');
|
|
40
58
|
if (link === undefined)
|
|
41
59
|
return null;
|
|
42
60
|
hrefs.push(link.destination.href);
|
|
43
61
|
}
|
|
44
62
|
return hrefs;
|
|
45
63
|
}
|
|
46
|
-
export function verify(schema) {
|
|
47
|
-
const read = readSchema(schema);
|
|
64
|
+
export function verify(schema, provided) {
|
|
65
|
+
const read = readSchema(schema, provided);
|
|
48
66
|
if ('types' in read)
|
|
49
67
|
return { verdict: 'accept', model: read };
|
|
50
68
|
return {
|
|
@@ -53,114 +71,299 @@ export function verify(schema) {
|
|
|
53
71
|
...(read.location === undefined ? {} : { location: read.location }),
|
|
54
72
|
};
|
|
55
73
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
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);
|
|
74
|
+
function structure(file, content, document, definition) {
|
|
75
|
+
if (definition === undefined)
|
|
76
|
+
return { refusal: refuse(file, 'unknown-type', { location: '/type' }) };
|
|
77
|
+
const fieldFailure = frontmatterRefusal(definition, document.fields);
|
|
78
|
+
if (fieldFailure !== undefined) {
|
|
79
|
+
return { refusal: refuse(file, fieldFailure.rule, { location: fieldFailure.location }) };
|
|
70
80
|
}
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
81
|
+
const spans = headingSpans(content, bodyStartOf(content));
|
|
82
|
+
const uses = usesIn(content);
|
|
83
|
+
const sections = [];
|
|
84
|
+
const conditioned = conditionedSections(definition, document.fields);
|
|
85
|
+
for (const [name, spec] of Object.entries(definition.sections)) {
|
|
86
|
+
const occurrences = spans.filter((one) => one.name === name);
|
|
87
|
+
if (occurrences.length === 0 && spec.required)
|
|
88
|
+
return { refusal: refuse(file, 'required-section', { location: name }) };
|
|
89
|
+
if (conditioned.includes(name) &&
|
|
90
|
+
occurrences.every((span) => content.slice(span.bodyStart, span.bodyEnd).trim() === ''))
|
|
91
|
+
return { refusal: refuse(file, 'conditional-section', { location: name }) };
|
|
92
|
+
if (spec.kind !== 'list')
|
|
76
93
|
continue;
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
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')
|
|
94
|
+
for (const span of occurrences) {
|
|
95
|
+
const items = listItems(content, span.bodyStart, span.bodyEnd);
|
|
96
|
+
if (items === null ||
|
|
97
|
+
items.some((item) => !fitsItem(definition, name, content.slice(item.start, item.end))))
|
|
98
|
+
return { refusal: refuse(file, 'structured-section', { location: name }) };
|
|
99
|
+
if (spec.items.reference === undefined)
|
|
92
100
|
continue;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
return refuse(file, 'structured-section', { location: name });
|
|
103
|
-
references.push({ section: name, to: spec.items.reference, hrefs });
|
|
104
|
-
}
|
|
101
|
+
const hrefs = itemHrefs(content, items, uses);
|
|
102
|
+
if (hrefs === null)
|
|
103
|
+
return { refusal: refuse(file, 'structured-section', { location: name }) };
|
|
104
|
+
sections.push({
|
|
105
|
+
section: name,
|
|
106
|
+
to: spec.items.reference,
|
|
107
|
+
crossRoom: spec.items.crossRoom === true,
|
|
108
|
+
hrefs,
|
|
109
|
+
});
|
|
105
110
|
}
|
|
106
|
-
sectionReferences.set(file, references);
|
|
107
111
|
}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
return { sections };
|
|
113
|
+
}
|
|
114
|
+
function linked(file, content) {
|
|
115
|
+
return hrefOccurrences(bodyAfterFrontmatter(content)).every((occurrence) => classifyHref(file, occurrence.href).kind !== 'invalid');
|
|
116
|
+
}
|
|
117
|
+
function reached(file, href, to) {
|
|
118
|
+
const resolved = classifyHref(file, href);
|
|
119
|
+
return { target: resolved.kind === 'path' ? resolved.path : null, to };
|
|
120
|
+
}
|
|
121
|
+
function crossing(file, href, crossRoom) {
|
|
122
|
+
return crossRoom === true && classifyHref(file, href).kind === 'room';
|
|
123
|
+
}
|
|
124
|
+
function definitionOf(document, model) {
|
|
125
|
+
const kind = instanceType(document);
|
|
126
|
+
return kind === null || !Object.hasOwn(model.types, kind) ? undefined : model.types[kind];
|
|
127
|
+
}
|
|
128
|
+
export function checkDocument(file, content, model, context = {}) {
|
|
129
|
+
const anyRoom = context.anyRoom === true;
|
|
130
|
+
const parsed = parse(content, file);
|
|
131
|
+
if (!parsed.ok)
|
|
132
|
+
return { ok: false };
|
|
133
|
+
const document = parsed.document;
|
|
134
|
+
const type = document.type ?? BUILT_IN_TYPE;
|
|
135
|
+
if (instanceType(document) === BUILT_IN_TYPE)
|
|
136
|
+
return { ok: true, type, typed: false, references: [] };
|
|
137
|
+
const definition = definitionOf(document, model);
|
|
138
|
+
const read = structure(file, content, document, definition);
|
|
139
|
+
if ('refusal' in read || definition === undefined || !linked(file, content))
|
|
140
|
+
return { ok: false };
|
|
141
|
+
return {
|
|
142
|
+
ok: true,
|
|
143
|
+
type,
|
|
144
|
+
typed: true,
|
|
145
|
+
references: [
|
|
146
|
+
...references(document, definition).flatMap(({ value, to, crossRoom }) => crossing(file, value, anyRoom || crossRoom) ? [] : [reached(file, value, to)]),
|
|
147
|
+
...read.sections.flatMap(({ to, crossRoom, hrefs }) => hrefs.flatMap((href) => crossing(file, href, anyRoom || crossRoom) ? [] : [reached(file, href, to)])),
|
|
148
|
+
],
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export function sectionReferences(file, content, definition) {
|
|
152
|
+
const referring = (name) => {
|
|
153
|
+
const spec = Object.hasOwn(definition.sections, name) ? definition.sections[name] : undefined;
|
|
154
|
+
return spec?.kind === 'list' && spec.items.reference !== undefined ? spec.items : undefined;
|
|
155
|
+
};
|
|
156
|
+
if (!Object.keys(definition.sections).some((name) => referring(name) !== undefined))
|
|
157
|
+
return [];
|
|
158
|
+
const uses = usesIn(content);
|
|
159
|
+
const found = [];
|
|
160
|
+
for (const span of headingSpans(content, bodyStartOf(content))) {
|
|
161
|
+
const items = referring(span.name);
|
|
162
|
+
if (items === undefined)
|
|
111
163
|
continue;
|
|
112
|
-
const
|
|
113
|
-
|
|
164
|
+
const listed = listItems(content, span.bodyStart, span.bodyEnd);
|
|
165
|
+
const hrefs = listed === null ? null : itemHrefs(content, listed, uses);
|
|
166
|
+
for (const href of hrefs ?? [])
|
|
167
|
+
if (!crossing(file, href, items.crossRoom))
|
|
168
|
+
found.push(reached(file, href, items.reference));
|
|
169
|
+
}
|
|
170
|
+
return found;
|
|
171
|
+
}
|
|
172
|
+
export function bodyRoomLinks(body) {
|
|
173
|
+
const found = [];
|
|
174
|
+
for (const href of new Set(hrefOccurrences(body).map((occurrence) => occurrence.href))) {
|
|
175
|
+
const room = roomTarget(href);
|
|
176
|
+
if (room !== null)
|
|
177
|
+
found.push({ kind: 'link', href, ...room });
|
|
178
|
+
}
|
|
179
|
+
return found;
|
|
180
|
+
}
|
|
181
|
+
export function roomReferences(file, content, definition) {
|
|
182
|
+
const found = bodyRoomLinks(bodyAfterFrontmatter(content));
|
|
183
|
+
if (definition === undefined)
|
|
184
|
+
return found;
|
|
185
|
+
const parsed = parse(content, file);
|
|
186
|
+
if (!parsed.ok)
|
|
187
|
+
return found;
|
|
188
|
+
for (const { pointer, value, to, crossRoom } of references(parsed.document, definition)) {
|
|
189
|
+
const room = roomTarget(value);
|
|
190
|
+
if (room !== null)
|
|
191
|
+
found.push({
|
|
192
|
+
kind: 'field',
|
|
193
|
+
pointer,
|
|
194
|
+
value,
|
|
195
|
+
to,
|
|
196
|
+
...room,
|
|
197
|
+
...(crossRoom ? { crossRoom } : {}),
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
const uses = usesIn(content);
|
|
201
|
+
for (const span of headingSpans(content, bodyStartOf(content))) {
|
|
202
|
+
const spec = Object.hasOwn(definition.sections, span.name)
|
|
203
|
+
? definition.sections[span.name]
|
|
204
|
+
: undefined;
|
|
205
|
+
if (spec?.kind !== 'list' || spec.items.reference === undefined)
|
|
114
206
|
continue;
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
207
|
+
const listed = listItems(content, span.bodyStart, span.bodyEnd);
|
|
208
|
+
for (const href of (listed === null ? null : itemHrefs(content, listed, uses)) ?? []) {
|
|
209
|
+
const room = roomTarget(href);
|
|
210
|
+
if (room !== null)
|
|
211
|
+
found.push({
|
|
212
|
+
kind: 'item',
|
|
213
|
+
section: span.name,
|
|
214
|
+
href,
|
|
215
|
+
to: spec.items.reference,
|
|
216
|
+
...room,
|
|
217
|
+
...(spec.items.crossRoom === true ? { crossRoom: true } : {}),
|
|
218
|
+
});
|
|
124
219
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
220
|
+
}
|
|
221
|
+
return found;
|
|
222
|
+
}
|
|
223
|
+
function least(refused, file, verdict) {
|
|
224
|
+
return refused === undefined || file < refused.file ? { file, verdict } : refused;
|
|
225
|
+
}
|
|
226
|
+
export function assess(file, content, binary, model = { types: {} }, context = {}) {
|
|
227
|
+
const unread = { file, type: undefined, targets: [], structured: null, fields: [], sections: [] };
|
|
228
|
+
if (binary)
|
|
229
|
+
return { ...unread, read: refuse(file, 'binary-target-document'), linked: true };
|
|
230
|
+
const parsed = parse(content, file);
|
|
231
|
+
if (!parsed.ok)
|
|
232
|
+
return { ...unread, read: { verdict: 'refuse', ...parsed.refusal }, linked: true };
|
|
233
|
+
const document = parsed.document;
|
|
234
|
+
const type = document.type ?? BUILT_IN_TYPE;
|
|
235
|
+
const typed = { file, type, read: null, structured: null };
|
|
236
|
+
if (instanceType(document) === BUILT_IN_TYPE) {
|
|
237
|
+
return { ...typed, targets: [], fields: [], linked: true, sections: [] };
|
|
238
|
+
}
|
|
239
|
+
const definition = definitionOf(document, model);
|
|
240
|
+
try {
|
|
241
|
+
return structured(file, content, typed, document, definition, context);
|
|
242
|
+
}
|
|
243
|
+
catch (error) {
|
|
244
|
+
if (!(error instanceof PatternTooCostly))
|
|
245
|
+
throw error;
|
|
246
|
+
return {
|
|
247
|
+
...typed,
|
|
248
|
+
targets: [],
|
|
249
|
+
structured: refuse(file, 'pattern', { location: '' }),
|
|
250
|
+
fields: [],
|
|
251
|
+
linked: true,
|
|
252
|
+
sections: [],
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function structured(file, content, typed, document, definition, context) {
|
|
257
|
+
const read = structure(file, content, document, definition);
|
|
258
|
+
if ('refusal' in read || definition === undefined) {
|
|
259
|
+
return {
|
|
260
|
+
...typed,
|
|
261
|
+
targets: [],
|
|
262
|
+
structured: 'refusal' in read ? read.refusal : null,
|
|
263
|
+
fields: [],
|
|
264
|
+
linked: true,
|
|
265
|
+
sections: [],
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
const anyRoom = context.anyRoom === true;
|
|
269
|
+
const fields = references(document, definition).flatMap(({ pointer, value, to, crossRoom }) => crossing(file, value, anyRoom || crossRoom)
|
|
270
|
+
? []
|
|
271
|
+
: [{ reference: reached(file, value, to), location: pointer }]);
|
|
272
|
+
const sections = read.sections.flatMap(({ section, to, crossRoom, hrefs }) => hrefs.flatMap((href) => crossing(file, href, anyRoom || crossRoom)
|
|
273
|
+
? []
|
|
274
|
+
: [{ reference: reached(file, href, to), location: section }]));
|
|
275
|
+
const targets = new Set();
|
|
276
|
+
for (const { reference } of [...fields, ...sections]) {
|
|
277
|
+
if (reference.target !== null)
|
|
278
|
+
targets.add(reference.target);
|
|
279
|
+
}
|
|
280
|
+
return { ...typed, targets: [...targets], fields, linked: linked(file, content), sections };
|
|
281
|
+
}
|
|
282
|
+
export function verdicts() {
|
|
283
|
+
let read;
|
|
284
|
+
let structured;
|
|
285
|
+
let referred;
|
|
286
|
+
let missed;
|
|
287
|
+
const unreached = (placed, typeOf, binary) => placed.find(({ reference }) => !reaches(reference, typeOf, binary));
|
|
288
|
+
return {
|
|
289
|
+
add(assessment, typeOf, binary) {
|
|
290
|
+
const { file } = assessment;
|
|
291
|
+
if (assessment.read !== null) {
|
|
292
|
+
read = least(read, file, assessment.read);
|
|
293
|
+
return 0;
|
|
294
|
+
}
|
|
295
|
+
if (assessment.structured !== null) {
|
|
296
|
+
structured = least(structured, file, assessment.structured);
|
|
297
|
+
return 0;
|
|
298
|
+
}
|
|
299
|
+
const field = unreached(assessment.fields, typeOf, binary);
|
|
300
|
+
if (field !== undefined) {
|
|
301
|
+
referred = least(referred, file, refuse(file, 'unresolved-reference', { location: field.location }));
|
|
302
|
+
return 0;
|
|
129
303
|
}
|
|
304
|
+
if (!assessment.linked) {
|
|
305
|
+
referred = least(referred, file, refuse(file, 'unresolved-link'));
|
|
306
|
+
return 0;
|
|
307
|
+
}
|
|
308
|
+
const section = unreached(assessment.sections, typeOf, binary);
|
|
309
|
+
if (section !== undefined) {
|
|
310
|
+
referred = least(referred, file, refuse(file, 'unresolved-reference', { location: section.location }));
|
|
311
|
+
return 0;
|
|
312
|
+
}
|
|
313
|
+
const all = [...assessment.fields, ...assessment.sections];
|
|
314
|
+
for (const { reference } of all) {
|
|
315
|
+
if (!missing(reference, typeOf, binary))
|
|
316
|
+
continue;
|
|
317
|
+
const path = reference.target;
|
|
318
|
+
if (missed === undefined || path < missed.path)
|
|
319
|
+
missed = { path, referrers: [] };
|
|
320
|
+
if (path === missed.path && missed.referrers.at(-1) !== file)
|
|
321
|
+
missed.referrers.push(file);
|
|
322
|
+
}
|
|
323
|
+
return all.length;
|
|
324
|
+
},
|
|
325
|
+
verdict() {
|
|
326
|
+
const refused = read ?? structured ?? referred;
|
|
327
|
+
if (refused !== undefined)
|
|
328
|
+
return refused.verdict;
|
|
329
|
+
if (missed !== undefined) {
|
|
330
|
+
return refuse(missed.path, 'referenced-missing-file', {
|
|
331
|
+
referrers: [...missed.referrers].sort(),
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
return { verdict: 'accept' };
|
|
335
|
+
},
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
export function* validating(library, context = { binaryTargets: [] }, model = { types: {} }) {
|
|
339
|
+
const binaryTargets = new Set(context.binaryTargets);
|
|
340
|
+
const binary = (path) => binaryTargets.has(path);
|
|
341
|
+
const types = new Map();
|
|
342
|
+
const assessments = [];
|
|
343
|
+
const closeBudget = openPatternBudget();
|
|
344
|
+
try {
|
|
345
|
+
for (const [file, content] of library) {
|
|
346
|
+
const assessment = assess(file, content, binary(file), model, context);
|
|
347
|
+
if (assessment.type !== undefined)
|
|
348
|
+
types.set(file, assessment.type);
|
|
349
|
+
assessments.push(assessment);
|
|
350
|
+
yield { path: file, resolved: 0 };
|
|
130
351
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
if (kind === null || kind === BUILT_IN_TYPE)
|
|
136
|
-
continue;
|
|
137
|
-
const definition = definitions.get(kind);
|
|
138
|
-
if (definition === undefined)
|
|
139
|
-
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);
|
|
352
|
+
const judged = verdicts();
|
|
353
|
+
for (const assessment of assessments) {
|
|
354
|
+
const resolved = judged.add(assessment, (path) => types.get(path), binary);
|
|
355
|
+
yield { path: assessment.file, resolved };
|
|
157
356
|
}
|
|
357
|
+
return judged.verdict();
|
|
158
358
|
}
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
const path = missingPaths[0];
|
|
162
|
-
const referrers = [...new Set(missing.get(path) ?? [])].sort();
|
|
163
|
-
return refuse(path, 'referenced-missing-file', { referrers });
|
|
359
|
+
finally {
|
|
360
|
+
closeBudget();
|
|
164
361
|
}
|
|
165
|
-
|
|
362
|
+
}
|
|
363
|
+
export function validate(library, context = { binaryTargets: [] }, model = { types: {} }) {
|
|
364
|
+
const steps = validating(new Map(Object.entries(library)), context, model);
|
|
365
|
+
let step = steps.next();
|
|
366
|
+
while (step.done !== true)
|
|
367
|
+
step = steps.next();
|
|
368
|
+
return step.value;
|
|
166
369
|
}
|