@agentshouse/mdmodel 0.1.0-c3d58cb8652e6 → 0.1.0-c4fe1bc82bc55
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 +62 -1
- package/dist/blocks.d.ts.map +1 -1
- package/dist/blocks.js +30 -16
- package/dist/condition.d.ts +17 -5
- package/dist/condition.d.ts.map +1 -1
- package/dist/condition.js +208 -111
- package/dist/definition.d.ts +8 -0
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +48 -0
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +7 -12
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +19 -25
- package/dist/yaml.d.ts +6 -1
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +33 -14
- package/package.json +1 -1
package/API.md
CHANGED
|
@@ -38,6 +38,9 @@ if (parsed.ok) {
|
|
|
38
38
|
}
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
+
`MARKDOWN_SYNTAX_PROFILE` is the Markdown every reader here applies, GitHub Flavored Markdown
|
|
42
|
+
0.29, and `VERSION` is the MD model version.
|
|
43
|
+
|
|
41
44
|
`verify(schema)` reads one schema text, the MD Types of one Room or App: one
|
|
42
45
|
JSON Schema document (draft 2020-12) in the YAML subset. Every top-level key but
|
|
43
46
|
`$defs` names an MD Type holding the JSON Schema of its frontmatter; `$defs`
|
|
@@ -72,6 +75,10 @@ variant's own keys `conditional`; a path without one `type`, `null` aside, has
|
|
|
72
75
|
none. A malformed schema is refused whole, naming its `rule`, the keyword or the
|
|
73
76
|
model's own, and the JSON Pointer `location` it concerns, such as
|
|
74
77
|
`/plan/properties/status/enum`, or `line <n>` outside the YAML subset.
|
|
78
|
+
`pointerFacts(definition, pointer)` reads the facts a frontmatter pointer reaches,
|
|
79
|
+
`itemFacts` and `memberFacts` take one step and `crossedFacts` reads a list's item
|
|
80
|
+
facts; `pointerSegments` and `escapePointer` split and write a pointer, `ARRAY_INDEX`
|
|
81
|
+
matches an index segment, and `ATTACHMENT` is the `reference` that admits any path.
|
|
75
82
|
|
|
76
83
|
`validate(library, context?, model?)` takes the resulting text Library and one
|
|
77
84
|
`ValidationContext` of `binaryTargets: readonly string[]`, none when omitted.
|
|
@@ -103,10 +110,14 @@ and no body link is a referrer.
|
|
|
103
110
|
Validation returns acceptance or one refusal naming the file, the field or
|
|
104
111
|
section, and the violated rule. `parse`, `apply`, and `serialize` operate on a single text
|
|
105
112
|
Document; they do not validate collection membership or consume binary bytes.
|
|
106
|
-
`apply` sets one typed field, including a list
|
|
113
|
+
`apply` sets one typed field, including a list or an object as a whole, replaces
|
|
107
114
|
one existing section body or the preamble against that value's prior content,
|
|
108
115
|
or rewrites one Markdown link destination. A section need not be declared by
|
|
109
116
|
the Document's MD Type to be replaced. A field change does not reformat the rest of the file.
|
|
117
|
+
A field holds a `FrontmatterValue`: null, a string, a boolean, a finite number, a list
|
|
118
|
+
without holes or a plain object of them, holding no cycle. `frontmatterValue(value)` is that test, and
|
|
119
|
+
`apply` refuses any other value as `frontmatter-fence`; `equalValue(left, right)` compares
|
|
120
|
+
two by value, whatever their key order, as `apply` compares a field with its prior.
|
|
110
121
|
|
|
111
122
|
`Document.preamble` is a readonly string containing the exact source after
|
|
112
123
|
frontmatter and before the first section heading recognized by the existing
|
|
@@ -296,3 +307,53 @@ author quoted. A Span divided out of one free-text field value addresses that
|
|
|
296
307
|
whole value, because a YAML scalar's own positions are the only ones its source
|
|
297
308
|
has, and a Span carrying part of one internal link's label addresses that whole
|
|
298
309
|
link, because a cut never falls inside link syntax.
|
|
310
|
+
|
|
311
|
+
## Conditions
|
|
312
|
+
|
|
313
|
+
`facts(document, { id, path }, model, resolve)` reads one Document as the `DocumentFacts` a
|
|
314
|
+
condition tests: its `id`, its `path` with a leading `/`, its `type` or `null`, its `sections`, and
|
|
315
|
+
a `Fact` for each frontmatter field it writes that its MD Type declares. `factKind(facts)` names
|
|
316
|
+
the kind a declared value compares as: `reference`, `enum`, `number`, `boolean`, `date`, `time`
|
|
317
|
+
(a `date-time`) or `string`, else `null`. A prose value, or one of no kind, is `prose`, a list or
|
|
318
|
+
an object holds the facts of its members, and a value written `null` is `null`. A value that does
|
|
319
|
+
not fit its kind, such as a string in a number field, a value outside its `enum` or a reference
|
|
320
|
+
`resolve` maps to no `{ id, member? }`, is `unreadable`; a readable reference compares as that `id`.
|
|
321
|
+
|
|
322
|
+
`holds(test, facts, owner)` is `true`, `false` or `undefined`, unknown; a Trigger fires on `true`
|
|
323
|
+
alone. A test's `path` is `/path`, `/type`, `/sections/<heading>`, `/fields/<pointer>`, or
|
|
324
|
+
`/members/<pointer>`, the member of the Document a reference field reaches. A pointer segment that
|
|
325
|
+
is not an index reads every item of a list, an item lacking it unknown, and a test over several
|
|
326
|
+
values holds as `any` does. The value `{ owner: true }` stands for `owner`, a User id.
|
|
327
|
+
|
|
328
|
+
| The path reaches | `exists` | `contains` | any other test |
|
|
329
|
+
| --------------------------------------- | ----------- | -------------- | -------------- |
|
|
330
|
+
| a value | present | `undefined` | compared |
|
|
331
|
+
| `null`, prose or a section | present | `undefined` | `undefined` |
|
|
332
|
+
| a list | present | `any` of items | `undefined` |
|
|
333
|
+
| no item, through an empty list | absent | `false` | `false` |
|
|
334
|
+
| nothing: no such field, section or type | absent | `undefined` | `undefined` |
|
|
335
|
+
| only unreadable values | `undefined` | `undefined` | `undefined` |
|
|
336
|
+
|
|
337
|
+
`exists: true` holds where present and fails where absent, `exists: false` the reverse. `all` is
|
|
338
|
+
`false` if a part is, else `undefined` if a part is; `any` is `true` if a part is, else `undefined`
|
|
339
|
+
if a part is; `not` keeps `undefined`, so absence is tested with `exists`, never with `not`. `eq`
|
|
340
|
+
and `in` are `undefined` against a value of another JSON type and compare a `time` as an instant;
|
|
341
|
+
`prefix` reads only a string, never a reference or a member; `gt`, `gte`, `lt` and `lte` order
|
|
342
|
+
numbers, dates and times alone.
|
|
343
|
+
|
|
344
|
+
`fires(condition, event, owner)` reads one change, `{ before, after, changed, by }`: the facts of
|
|
345
|
+
each side, `null` on the side a creation or a deletion lacks, the `changed` paths whose prose
|
|
346
|
+
changed, and the actor whose `/user`, `/site` and `/door`, one of `WRITE_DOORS`, a `by` test reads.
|
|
347
|
+
`starts_matching` fires when the Document is in `scope` and holds `match` after the change and did
|
|
348
|
+
not before; a creation fires only with `new_documents: true`, and a deletion never fires.
|
|
349
|
+
`field_changes` fires when the side the Document has, after or for a deletion before, is in `scope`
|
|
350
|
+
and holds `match`, and `field` changed: its facts differ, or with neither `from` nor `to` `changed`
|
|
351
|
+
names it. A field absent on both sides never fires; `from: 'new'` admits only a creation and
|
|
352
|
+
`to: 'deleted'` only a deletion, and listed values need that side to hold `field` `in` them.
|
|
353
|
+
|
|
354
|
+
`itemFires(condition, item, owner)` compares `source` and `address` where given and holds `match`
|
|
355
|
+
over `/delivery`, `/source`, `/provider`, `/container`, `/author`, `/has_attachment`,
|
|
356
|
+
`/headers/<name>` and `/json/<pointer>`, unknown for an item with no JSON. `prosePaths(facts)` lists
|
|
357
|
+
the prose and section paths whose text builds `changed`; `pointed(value, pointer)` reads a JSON
|
|
358
|
+
Pointer, `undefined` where nothing is; `dated(value)` checks a `YYYY-MM-DD` date, and
|
|
359
|
+
`instant(value)` reads an RFC 3339 time with its offset as epoch nanoseconds, a `bigint`.
|
package/dist/blocks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;
|
|
1
|
+
{"version":3,"file":"blocks.d.ts","sourceRoot":"","sources":["../src/blocks.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,CAAC;AAqCF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,EAAE,CA+BrF;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,CAe/E"}
|
package/dist/blocks.js
CHANGED
|
@@ -23,24 +23,38 @@ function scan(content, from, to, visit) {
|
|
|
23
23
|
i = next;
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
const HASH = 0x23;
|
|
26
27
|
export function headingLines(content, from, to) {
|
|
27
28
|
const found = [];
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
29
|
+
let fences = null;
|
|
30
|
+
let i = from;
|
|
31
|
+
while (i < to) {
|
|
32
|
+
const nl = content.indexOf('\n', i);
|
|
33
|
+
const end = nl === -1 || nl >= to ? to : nl;
|
|
34
|
+
const next = end === to ? to : end + 1;
|
|
35
|
+
if (content.charCodeAt(i) === HASH) {
|
|
36
|
+
fences ??= fenceSpans(content.slice(from, to));
|
|
37
|
+
const at = i - from;
|
|
38
|
+
if (!fences.some(([start, stop]) => at >= start && at < stop)) {
|
|
39
|
+
const { text } = lineAt(content, i, to);
|
|
40
|
+
const match = HEADING.exec(text);
|
|
41
|
+
const hashes = match?.[1];
|
|
42
|
+
const name = match?.[2];
|
|
43
|
+
if (hashes !== undefined && name !== undefined) {
|
|
44
|
+
found.push({
|
|
45
|
+
level: hashes.length,
|
|
46
|
+
name: name.trim(),
|
|
47
|
+
start: i,
|
|
48
|
+
textEnd: i + text.length,
|
|
49
|
+
next,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (next === i)
|
|
55
|
+
break;
|
|
56
|
+
i = next;
|
|
57
|
+
}
|
|
44
58
|
return found;
|
|
45
59
|
}
|
|
46
60
|
export function blockRanges(content, from, to) {
|
package/dist/condition.d.ts
CHANGED
|
@@ -77,18 +77,30 @@ export type DateCondition = {
|
|
|
77
77
|
};
|
|
78
78
|
export type Condition = DocumentCondition | ItemCondition | CronCondition | DateCondition;
|
|
79
79
|
export type FactKind = 'string' | 'number' | 'boolean' | 'date' | 'time' | 'enum' | 'reference';
|
|
80
|
+
type Scalar = string | number | boolean;
|
|
80
81
|
export type Fact = {
|
|
81
82
|
readonly kind: FactKind;
|
|
82
|
-
readonly value: Scalar
|
|
83
|
+
readonly value: Scalar;
|
|
84
|
+
readonly member?: string;
|
|
85
|
+
} | {
|
|
86
|
+
readonly kind: 'prose';
|
|
87
|
+
} | {
|
|
88
|
+
readonly kind: 'null';
|
|
89
|
+
} | {
|
|
90
|
+
readonly kind: 'unreadable';
|
|
91
|
+
} | {
|
|
92
|
+
readonly kind: 'list';
|
|
93
|
+
readonly items: readonly Fact[];
|
|
94
|
+
} | {
|
|
95
|
+
readonly kind: 'object';
|
|
96
|
+
readonly fields: Readonly<Record<string, Fact>>;
|
|
83
97
|
};
|
|
84
98
|
export type DocumentFacts = {
|
|
85
99
|
readonly id: string;
|
|
86
100
|
readonly path: string;
|
|
87
101
|
readonly type: string | null;
|
|
88
102
|
readonly fields: Readonly<Record<string, Fact>>;
|
|
89
|
-
readonly
|
|
90
|
-
readonly prose: readonly string[];
|
|
91
|
-
readonly unreadable: readonly string[];
|
|
103
|
+
readonly sections: readonly string[];
|
|
92
104
|
};
|
|
93
105
|
export declare const WRITE_DOORS: readonly ['browser', 'agent', 'client'];
|
|
94
106
|
export type WriteDoor = (typeof WRITE_DOORS)[number];
|
|
@@ -121,12 +133,12 @@ export type Resolved = {
|
|
|
121
133
|
readonly member?: string;
|
|
122
134
|
};
|
|
123
135
|
type Truth = boolean | undefined;
|
|
124
|
-
type Scalar = string | number | boolean;
|
|
125
136
|
export declare function factKind(facts: ValueFacts): FactKind | null;
|
|
126
137
|
export declare function facts(document: Document, at: {
|
|
127
138
|
readonly id: string;
|
|
128
139
|
readonly path: string;
|
|
129
140
|
}, model: VerifiedModel, resolve: (target: string) => Resolved | undefined): DocumentFacts;
|
|
141
|
+
export declare function prosePaths(facts: DocumentFacts): string[];
|
|
130
142
|
export declare function dated(value: unknown): value is string;
|
|
131
143
|
export declare function instant(value: unknown): bigint | undefined;
|
|
132
144
|
export declare function pointed(value: unknown, pointer: string): unknown;
|
package/dist/condition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../src/condition.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"condition.d.ts","sourceRoot":"","sources":["../src/condition.ts"],"names":[],"mappings":"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"}
|
package/dist/condition.js
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
|
-
import { ARRAY_INDEX } from './definition.js';
|
|
1
|
+
import { ARRAY_INDEX, escapePointer, fieldFacts, itemFacts, memberFacts, pointerSegments, } from './definition.js';
|
|
2
2
|
import { target } from './paths.js';
|
|
3
|
-
import { isRecord } from './yaml.js';
|
|
3
|
+
import { isRecord, plain } from './yaml.js';
|
|
4
4
|
export const WRITE_DOORS = ['browser', 'agent', 'client'];
|
|
5
|
+
const PROSE = { kind: 'prose' };
|
|
6
|
+
const NULL = { kind: 'null' };
|
|
7
|
+
const UNREADABLE = { kind: 'unreadable' };
|
|
8
|
+
const UNREAD = { present: undefined, values: [undefined], items: [undefined] };
|
|
9
|
+
const NO_ITEM = { present: false, values: [], items: [] };
|
|
5
10
|
const DATE = /^\d{4}-\d{2}-\d{2}$/u;
|
|
6
11
|
const DATE_TIME = /^(\d{4})-(\d{2})-(\d{2})[Tt](\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?(?:[Zz]|([+-])(\d{2}):(\d{2}))$/u;
|
|
7
12
|
export function factKind(facts) {
|
|
@@ -21,9 +26,6 @@ export function factKind(facts) {
|
|
|
21
26
|
return 'time';
|
|
22
27
|
return 'string';
|
|
23
28
|
}
|
|
24
|
-
function referenced(model, facts) {
|
|
25
|
-
return (facts.reference ?? []).some((to) => Object.hasOwn(model.types, to) && model.types[to].memberDocument);
|
|
26
|
-
}
|
|
27
29
|
function fits(kind, facts, value) {
|
|
28
30
|
if (!scalar(value))
|
|
29
31
|
return false;
|
|
@@ -41,81 +43,156 @@ function fits(kind, facts, value) {
|
|
|
41
43
|
return instant(value) !== undefined;
|
|
42
44
|
return true;
|
|
43
45
|
}
|
|
44
|
-
function
|
|
45
|
-
if (
|
|
46
|
-
return
|
|
46
|
+
function factOf(value, declared, place) {
|
|
47
|
+
if (value === null)
|
|
48
|
+
return NULL;
|
|
49
|
+
if (Array.isArray(value)) {
|
|
50
|
+
if (declared?.type !== undefined && declared.type !== 'array')
|
|
51
|
+
return UNREADABLE;
|
|
52
|
+
return {
|
|
53
|
+
kind: 'list',
|
|
54
|
+
items: value.map((item, index) => factOf(item, declared === undefined ? undefined : itemFacts(declared, index), place)),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (plain(value)) {
|
|
58
|
+
if (declared?.type !== undefined && declared.type !== 'object')
|
|
59
|
+
return UNREADABLE;
|
|
60
|
+
const fields = Object.create(null);
|
|
61
|
+
for (const [key, held] of Object.entries(value))
|
|
62
|
+
fields[key] = factOf(held, declared === undefined ? undefined : memberFacts(declared, key), place);
|
|
63
|
+
return { kind: 'object', fields };
|
|
64
|
+
}
|
|
65
|
+
if (declared?.type === 'array' || declared?.type === 'object')
|
|
66
|
+
return UNREADABLE;
|
|
67
|
+
const kind = declared === undefined || declared.prose ? null : factKind(declared);
|
|
68
|
+
if (kind === null)
|
|
69
|
+
return PROSE;
|
|
70
|
+
if (!fits(kind, declared, value))
|
|
71
|
+
return UNREADABLE;
|
|
47
72
|
if (kind !== 'reference')
|
|
48
|
-
return { value };
|
|
49
|
-
const reached = target(path, value);
|
|
50
|
-
|
|
73
|
+
return { kind, value };
|
|
74
|
+
const reached = target(place.path, value);
|
|
75
|
+
const resolved = reached === null ? undefined : place.resolve(reached);
|
|
76
|
+
if (resolved === undefined)
|
|
77
|
+
return UNREADABLE;
|
|
78
|
+
return resolved.member === undefined
|
|
79
|
+
? { kind, value: resolved.id }
|
|
80
|
+
: { kind, value: resolved.id, member: resolved.member };
|
|
51
81
|
}
|
|
52
82
|
export function facts(document, at, model, resolve) {
|
|
53
83
|
const type = document.type ?? null;
|
|
54
84
|
const definition = type !== null && Object.hasOwn(model.types, type) ? model.types[type] : null;
|
|
55
|
-
const fields =
|
|
56
|
-
const
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (value === undefined || value === null)
|
|
62
|
-
continue;
|
|
63
|
-
const list = declared.type === 'array';
|
|
64
|
-
const facts = list ? declared.items : declared;
|
|
65
|
-
const kind = facts === undefined || facts.prose ? null : factKind(facts);
|
|
66
|
-
if (kind === null) {
|
|
67
|
-
prose.push(`/fields/${name}`);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
const items = list ? value : [value];
|
|
71
|
-
const held = Array.isArray(items)
|
|
72
|
-
? items.map((item) => fitted(kind, facts, item, at.path, resolve))
|
|
73
|
-
: [undefined];
|
|
74
|
-
if (held.some((item) => item === undefined)) {
|
|
75
|
-
unreadable.push(`/fields/${name}`);
|
|
76
|
-
if (referenced(model, facts))
|
|
77
|
-
unreadable.push(`/members/${name}`);
|
|
78
|
-
continue;
|
|
79
|
-
}
|
|
80
|
-
const values = held.map((item) => ('id' in item ? item.id : item.value));
|
|
81
|
-
fields[name] = { kind, value: list ? values : values[0] };
|
|
82
|
-
if (!referenced(model, facts))
|
|
83
|
-
continue;
|
|
84
|
-
const bound = held.flatMap((item) => 'member' in item && item.member !== undefined ? [item.member] : []);
|
|
85
|
-
if (list)
|
|
86
|
-
members[name] = bound;
|
|
87
|
-
else if (bound[0] !== undefined)
|
|
88
|
-
members[name] = bound[0];
|
|
85
|
+
const fields = Object.create(null);
|
|
86
|
+
const place = { path: at.path, resolve };
|
|
87
|
+
for (const [name, value] of Object.entries(document.fields)) {
|
|
88
|
+
const declared = definition === null ? undefined : fieldFacts(definition, name);
|
|
89
|
+
if (declared !== undefined)
|
|
90
|
+
fields[name] = factOf(value, declared, place);
|
|
89
91
|
}
|
|
90
92
|
return {
|
|
91
93
|
id: at.id,
|
|
92
94
|
path: `/${at.path}`,
|
|
93
95
|
type,
|
|
94
96
|
fields,
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
97
|
+
sections: Object.keys(document.sections).sort(),
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
function rootOf(facts, prefix) {
|
|
101
|
+
return { pointer: prefix, fact: { kind: 'object', fields: facts.fields } };
|
|
102
|
+
}
|
|
103
|
+
export function prosePaths(facts) {
|
|
104
|
+
const paths = facts.sections.map((heading) => `/sections/${heading}`);
|
|
105
|
+
const visit = ({ pointer, fact }) => {
|
|
106
|
+
if (fact.kind === 'prose')
|
|
107
|
+
paths.push(pointer);
|
|
108
|
+
if (fact.kind === 'list')
|
|
109
|
+
fact.items.forEach((item, index) => visit({ pointer: `${pointer}/${index}`, fact: item }));
|
|
110
|
+
if (fact.kind === 'object')
|
|
111
|
+
for (const [key, held] of Object.entries(fact.fields))
|
|
112
|
+
visit({ pointer: `${pointer}/${escapePointer(key)}`, fact: held });
|
|
113
|
+
};
|
|
114
|
+
visit(rootOf(facts, '/fields'));
|
|
115
|
+
return paths.sort();
|
|
116
|
+
}
|
|
117
|
+
function walked(start, pointer) {
|
|
118
|
+
let reached = [start];
|
|
119
|
+
let several = false;
|
|
120
|
+
let missing = false;
|
|
121
|
+
const each = (from, next) => from.flatMap((one) => {
|
|
122
|
+
const found = next(one);
|
|
123
|
+
if (found === null)
|
|
124
|
+
missing = true;
|
|
125
|
+
return found ?? [];
|
|
126
|
+
});
|
|
127
|
+
for (const token of pointerSegments(pointer)) {
|
|
128
|
+
const step = ({ pointer: at, fact }) => {
|
|
129
|
+
if (fact.kind === 'unreadable')
|
|
130
|
+
return [{ pointer: at, fact }];
|
|
131
|
+
if (fact.kind === 'object')
|
|
132
|
+
return Object.hasOwn(fact.fields, token)
|
|
133
|
+
? [{ pointer: `${at}/${escapePointer(token)}`, fact: fact.fields[token] }]
|
|
134
|
+
: null;
|
|
135
|
+
if (fact.kind !== 'list')
|
|
136
|
+
return null;
|
|
137
|
+
if (ARRAY_INDEX.test(token)) {
|
|
138
|
+
const item = fact.items[Number(token)];
|
|
139
|
+
return item === undefined ? null : [{ pointer: `${at}/${token}`, fact: item }];
|
|
140
|
+
}
|
|
141
|
+
several = true;
|
|
142
|
+
return each(fact.items.map((item, index) => ({ pointer: `${at}/${index}`, fact: item })), step);
|
|
143
|
+
};
|
|
144
|
+
reached = each(reached, step);
|
|
145
|
+
}
|
|
146
|
+
return { reached, several, missing };
|
|
147
|
+
}
|
|
148
|
+
function expand(fact) {
|
|
149
|
+
return fact.kind === 'list' ? fact.items.flatMap(expand) : [fact];
|
|
150
|
+
}
|
|
151
|
+
function fieldHeld(fact) {
|
|
152
|
+
if (fact.kind === 'unreadable')
|
|
153
|
+
return undefined;
|
|
154
|
+
if (fact.kind === 'null')
|
|
155
|
+
return { kind: 'null' };
|
|
156
|
+
return 'value' in fact ? { kind: fact.kind, value: fact.value } : { kind: 'prose' };
|
|
157
|
+
}
|
|
158
|
+
function memberHeld(fact) {
|
|
159
|
+
if (fact.kind === 'unreadable')
|
|
160
|
+
return undefined;
|
|
161
|
+
return fact.kind === 'reference' && fact.member !== undefined
|
|
162
|
+
? { kind: 'member', value: fact.member }
|
|
163
|
+
: null;
|
|
164
|
+
}
|
|
165
|
+
function single(held) {
|
|
166
|
+
return { present: true, values: [held], items: null };
|
|
167
|
+
}
|
|
168
|
+
function documentRead({ reached, several, missing }, held) {
|
|
169
|
+
if (reached.length === 0)
|
|
170
|
+
return missing ? undefined : NO_ITEM;
|
|
171
|
+
const facts = reached.map(({ fact }) => fact);
|
|
172
|
+
const kept = (all) => all.map(held).filter((value) => value !== null);
|
|
173
|
+
const unknown = missing ? [undefined] : [];
|
|
174
|
+
const values = kept(facts.filter((fact) => fact.kind !== 'list'));
|
|
175
|
+
const listed = several || facts.some((fact) => fact.kind === 'list');
|
|
176
|
+
const present = facts.some((fact) => fact.kind === 'list') || values.some(Boolean);
|
|
177
|
+
return {
|
|
178
|
+
present: present ? true : values.length > 0 ? undefined : false,
|
|
179
|
+
values: [...values, ...unknown],
|
|
180
|
+
items: listed ? [...kept(facts.flatMap(expand)), ...unknown] : null,
|
|
98
181
|
};
|
|
99
182
|
}
|
|
100
183
|
function readDocument(facts, path) {
|
|
101
184
|
if (path === '/path')
|
|
102
|
-
return { kind: 'path', value: facts.path };
|
|
185
|
+
return single({ kind: 'path', value: facts.path });
|
|
103
186
|
if (path === '/type')
|
|
104
|
-
return facts.type === null ? undefined : { kind: 'string', value: facts.type };
|
|
105
|
-
if (
|
|
106
|
-
return
|
|
107
|
-
|
|
108
|
-
return { kind: 'present' };
|
|
109
|
-
if (path.startsWith('/fields/')) {
|
|
110
|
-
const name = path.slice('/fields/'.length);
|
|
111
|
-
return Object.hasOwn(facts.fields, name) ? facts.fields[name] : undefined;
|
|
112
|
-
}
|
|
113
|
-
if (path.startsWith('/members/')) {
|
|
114
|
-
const name = path.slice('/members/'.length);
|
|
115
|
-
return Object.hasOwn(facts.members, name)
|
|
116
|
-
? { kind: 'member', value: facts.members[name] }
|
|
187
|
+
return facts.type === null ? undefined : single({ kind: 'string', value: facts.type });
|
|
188
|
+
if (path.startsWith('/sections/'))
|
|
189
|
+
return facts.sections.includes(path.slice('/sections/'.length))
|
|
190
|
+
? single({ kind: 'prose' })
|
|
117
191
|
: undefined;
|
|
118
|
-
|
|
192
|
+
if (path.startsWith('/fields/'))
|
|
193
|
+
return documentRead(walked(rootOf(facts, '/fields'), path.slice('/fields'.length)), fieldHeld);
|
|
194
|
+
if (path.startsWith('/members/'))
|
|
195
|
+
return documentRead(walked(rootOf(facts, '/members'), path.slice('/members'.length)), memberHeld);
|
|
119
196
|
return undefined;
|
|
120
197
|
}
|
|
121
198
|
function readActor(actor, path) {
|
|
@@ -126,13 +203,7 @@ function readActor(actor, path) {
|
|
|
126
203
|
: path === '/door'
|
|
127
204
|
? actor.door
|
|
128
205
|
: undefined;
|
|
129
|
-
return value === undefined ? undefined : { kind: 'actor', value };
|
|
130
|
-
}
|
|
131
|
-
function plain(value) {
|
|
132
|
-
if (!isRecord(value))
|
|
133
|
-
return false;
|
|
134
|
-
const prototype = Object.getPrototypeOf(value);
|
|
135
|
-
return prototype === Object.prototype || prototype === null;
|
|
206
|
+
return value === undefined ? undefined : single({ kind: 'actor', value });
|
|
136
207
|
}
|
|
137
208
|
export function dated(value) {
|
|
138
209
|
return (typeof value === 'string' && DATE.test(value) && instant(`${value}T00:00:00Z`) !== undefined);
|
|
@@ -187,8 +258,6 @@ function scalar(value) {
|
|
|
187
258
|
(typeof value === 'number' && Number.isFinite(value)));
|
|
188
259
|
}
|
|
189
260
|
function jsonHeld(value) {
|
|
190
|
-
if (value === undefined)
|
|
191
|
-
return undefined;
|
|
192
261
|
if (typeof value === 'string')
|
|
193
262
|
return {
|
|
194
263
|
kind: dated(value) ? 'date' : instant(value) === undefined ? 'string' : 'time',
|
|
@@ -196,26 +265,31 @@ function jsonHeld(value) {
|
|
|
196
265
|
};
|
|
197
266
|
if (typeof value === 'boolean')
|
|
198
267
|
return { kind: 'boolean', value };
|
|
268
|
+
return { kind: 'number', value };
|
|
269
|
+
}
|
|
270
|
+
function jsonRead(value) {
|
|
271
|
+
if (value === undefined)
|
|
272
|
+
return undefined;
|
|
199
273
|
if (scalar(value))
|
|
200
|
-
return
|
|
201
|
-
if (Array.isArray(value))
|
|
202
|
-
return { kind: '
|
|
203
|
-
return {
|
|
274
|
+
return single(jsonHeld(value));
|
|
275
|
+
if (!Array.isArray(value))
|
|
276
|
+
return single({ kind: 'prose' });
|
|
277
|
+
return { present: true, values: [], items: value.filter(scalar).map(jsonHeld), loose: true };
|
|
204
278
|
}
|
|
205
279
|
function readItem(item, path) {
|
|
206
280
|
if (path.startsWith('/json/')) {
|
|
207
281
|
if (item.json === null)
|
|
208
|
-
return
|
|
209
|
-
return
|
|
282
|
+
return UNREAD;
|
|
283
|
+
return jsonRead(pointed(item.json.value, path.slice('/json'.length)));
|
|
210
284
|
}
|
|
211
285
|
if (path.startsWith('/headers/')) {
|
|
212
286
|
const name = path.slice('/headers/'.length);
|
|
213
287
|
return Object.hasOwn(item.headers, name)
|
|
214
|
-
? { kind: 'string', value: item.headers[name] }
|
|
288
|
+
? single({ kind: 'string', value: item.headers[name] })
|
|
215
289
|
: undefined;
|
|
216
290
|
}
|
|
217
291
|
if (path === '/has_attachment')
|
|
218
|
-
return { kind: 'boolean', value: item.has_attachment };
|
|
292
|
+
return single({ kind: 'boolean', value: item.has_attachment });
|
|
219
293
|
const value = path === '/delivery'
|
|
220
294
|
? item.delivery
|
|
221
295
|
: path === '/source'
|
|
@@ -227,13 +301,13 @@ function readItem(item, path) {
|
|
|
227
301
|
: path === '/author'
|
|
228
302
|
? item.author
|
|
229
303
|
: null;
|
|
230
|
-
return value === null ? undefined : { kind: 'string', value };
|
|
304
|
+
return value === null ? undefined : single({ kind: 'string', value });
|
|
231
305
|
}
|
|
232
306
|
function wanted(value, owner) {
|
|
233
307
|
return isRecord(value) && value.owner === true ? owner : value;
|
|
234
308
|
}
|
|
235
309
|
function equal(held, value, owner) {
|
|
236
|
-
if (
|
|
310
|
+
if (!('value' in held))
|
|
237
311
|
return undefined;
|
|
238
312
|
const expected = wanted(value, owner);
|
|
239
313
|
if (typeof expected !== typeof held.value)
|
|
@@ -248,7 +322,7 @@ function sign(left, right) {
|
|
|
248
322
|
return left < right ? -1 : left > right ? 1 : 0;
|
|
249
323
|
}
|
|
250
324
|
function ordered(held, value, compare) {
|
|
251
|
-
if (
|
|
325
|
+
if (!('value' in held))
|
|
252
326
|
return undefined;
|
|
253
327
|
if (held.kind === 'number') {
|
|
254
328
|
if (typeof value !== 'number' || typeof held.value !== 'number')
|
|
@@ -278,29 +352,13 @@ function allOf(truths) {
|
|
|
278
352
|
return false;
|
|
279
353
|
return truths.some((truth) => truth === undefined) ? undefined : true;
|
|
280
354
|
}
|
|
281
|
-
function
|
|
282
|
-
if (held?.kind === 'unreadable')
|
|
283
|
-
return undefined;
|
|
284
|
-
if ('exists' in test)
|
|
285
|
-
return (held !== undefined) === test.exists;
|
|
286
|
-
if (held === undefined)
|
|
287
|
-
return undefined;
|
|
355
|
+
function compared(test, held, owner) {
|
|
288
356
|
if ('eq' in test)
|
|
289
357
|
return equal(held, test.eq, owner);
|
|
290
358
|
if ('in' in test)
|
|
291
359
|
return anyOf(test.in.map((value) => equal(held, value, owner)));
|
|
292
|
-
if ('contains' in test) {
|
|
293
|
-
if (held.kind === 'present' || !Array.isArray(held.value))
|
|
294
|
-
return undefined;
|
|
295
|
-
const expected = wanted(test.contains, owner);
|
|
296
|
-
if (held.value.some((item) => item === expected))
|
|
297
|
-
return true;
|
|
298
|
-
if (held.kind === 'list')
|
|
299
|
-
return false;
|
|
300
|
-
return held.value.every((item) => typeof item === typeof expected) ? false : undefined;
|
|
301
|
-
}
|
|
302
360
|
if ('prefix' in test) {
|
|
303
|
-
if (
|
|
361
|
+
if (!('value' in held) || typeof held.value !== 'string')
|
|
304
362
|
return undefined;
|
|
305
363
|
if (held.kind === 'number' || held.kind === 'reference' || held.kind === 'member')
|
|
306
364
|
return undefined;
|
|
@@ -314,6 +372,23 @@ function leaf(test, held, owner) {
|
|
|
314
372
|
return ordered(held, test.lt, (sign) => sign < 0);
|
|
315
373
|
return ordered(held, test.lte, (sign) => sign <= 0);
|
|
316
374
|
}
|
|
375
|
+
function leaf(test, read, owner) {
|
|
376
|
+
if ('exists' in test) {
|
|
377
|
+
const present = read === undefined ? false : read.present;
|
|
378
|
+
return present === undefined ? undefined : present === test.exists;
|
|
379
|
+
}
|
|
380
|
+
if (read === undefined)
|
|
381
|
+
return undefined;
|
|
382
|
+
if ('contains' in test) {
|
|
383
|
+
if (read.items === null)
|
|
384
|
+
return undefined;
|
|
385
|
+
const truths = read.items.map((item) => item === undefined ? undefined : equal(item, test.contains, owner));
|
|
386
|
+
return read.loose === true && !truths.includes(true) ? false : anyOf(truths);
|
|
387
|
+
}
|
|
388
|
+
if (read.values.length === 0)
|
|
389
|
+
return read === NO_ITEM ? false : undefined;
|
|
390
|
+
return anyOf(read.values.map((value) => (value === undefined ? undefined : compared(test, value, owner))));
|
|
391
|
+
}
|
|
317
392
|
function evaluated(test, read, owner) {
|
|
318
393
|
if ('all' in test)
|
|
319
394
|
return allOf(test.all.map((part) => evaluated(part, read, owner)));
|
|
@@ -342,24 +417,46 @@ function matched(condition, test, document, owner) {
|
|
|
342
417
|
return false;
|
|
343
418
|
return test === undefined || holds(test, document, owner) === true;
|
|
344
419
|
}
|
|
345
|
-
function
|
|
346
|
-
|
|
420
|
+
function reachedAt(document, field) {
|
|
421
|
+
if (document === null)
|
|
422
|
+
return [];
|
|
423
|
+
if (field.startsWith('/sections/'))
|
|
424
|
+
return document.sections.includes(field.slice('/sections/'.length))
|
|
425
|
+
? [{ pointer: field, fact: PROSE }]
|
|
426
|
+
: [];
|
|
427
|
+
if (!field.startsWith('/fields/'))
|
|
428
|
+
return [];
|
|
429
|
+
return walked(rootOf(document, '/fields'), field.slice('/fields'.length)).reached;
|
|
430
|
+
}
|
|
431
|
+
function valueOf(fact) {
|
|
432
|
+
if (fact.kind === 'list')
|
|
433
|
+
return { kind: fact.kind, items: fact.items.map(valueOf) };
|
|
434
|
+
if (fact.kind === 'object')
|
|
435
|
+
return {
|
|
436
|
+
kind: fact.kind,
|
|
437
|
+
fields: Object.keys(fact.fields)
|
|
438
|
+
.sort()
|
|
439
|
+
.map((key) => [key, valueOf(fact.fields[key])]),
|
|
440
|
+
};
|
|
441
|
+
return 'value' in fact ? { kind: fact.kind, value: fact.value } : fact;
|
|
442
|
+
}
|
|
443
|
+
function signature(reached) {
|
|
444
|
+
return JSON.stringify(reached.map(({ fact }) => valueOf(fact)));
|
|
347
445
|
}
|
|
348
446
|
function among(values, document, field, owner) {
|
|
349
447
|
return holds({ path: field, in: values }, document, owner) === true;
|
|
350
448
|
}
|
|
351
449
|
function fieldChanged(condition, event, owner) {
|
|
352
450
|
const { field, from, to } = condition;
|
|
353
|
-
|
|
451
|
+
const before = reachedAt(event.before, field);
|
|
452
|
+
const after = reachedAt(event.after, field);
|
|
453
|
+
const pointers = [field, ...[...before, ...after].map(({ pointer }) => pointer)];
|
|
454
|
+
const prose = event.changed.some((changed) => pointers.some((pointer) => changed === pointer || changed.startsWith(`${pointer}/`)));
|
|
455
|
+
if (from === undefined && to === undefined && prose)
|
|
354
456
|
return true;
|
|
355
|
-
if (
|
|
356
|
-
return false;
|
|
357
|
-
const name = field.slice('/fields/'.length);
|
|
358
|
-
const before = event.before?.fields[name];
|
|
359
|
-
const after = event.after?.fields[name];
|
|
360
|
-
if (before === undefined && after === undefined)
|
|
457
|
+
if (before.length === 0 && after.length === 0)
|
|
361
458
|
return false;
|
|
362
|
-
if (event.before !== null && event.after !== null &&
|
|
459
|
+
if (event.before !== null && event.after !== null && signature(before) === signature(after))
|
|
363
460
|
return false;
|
|
364
461
|
if (from === 'new'
|
|
365
462
|
? event.before !== null
|
package/dist/definition.d.ts
CHANGED
|
@@ -54,5 +54,13 @@ export declare function refTarget(reference: string, defs: Readonly<Record<strin
|
|
|
54
54
|
export declare function valueFacts(node: unknown, defs: Readonly<Record<string, unknown>>): ValueFacts;
|
|
55
55
|
export declare function itemFacts(facts: ValueFacts, index: number): ValueFacts | undefined;
|
|
56
56
|
export declare function memberFacts(facts: ValueFacts, key: string): ValueFacts | undefined;
|
|
57
|
+
export type PointerFacts = {
|
|
58
|
+
readonly facts: ValueFacts;
|
|
59
|
+
readonly through: boolean;
|
|
60
|
+
readonly conditional: boolean;
|
|
61
|
+
};
|
|
62
|
+
export declare function crossedFacts(facts: ValueFacts): ValueFacts[];
|
|
63
|
+
export declare function fieldFacts(definition: Definition, key: string): ValueFacts | undefined;
|
|
64
|
+
export declare function pointerFacts(definition: Definition, pointer: string): PointerFacts | undefined;
|
|
57
65
|
export declare function readSchema(text: string): VerifiedModel | Failure;
|
|
58
66
|
//# sourceMappingURL=definition.d.ts.map
|
package/dist/definition.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGhD,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,MAAM,CAAC;AAEjG,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IACrC,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,WAAW,CAAC,EAAE,IAAI,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAC3D,QAAQ,CAAC,QAAQ,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IAC5C,QAAQ,CAAC,UAAU,CAAC,EAAE,UAAU,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAEpF,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC;AAEtF,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;CAClD,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,QAAQ,CAAC,WAAW,EAAE,UAAU,CAAC;IACjC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACtD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IACzD,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAc5E,eAAO,MAAM,UAAU,EAAE,SAAS,QAAQ,EAQzC,CAAC;AAEF,eAAO,MAAM,aAAa,QAAQ,CAAC;AAEnC,eAAO,MAAM,UAAU,eAAe,CAAC;AAQvC,eAAO,MAAM,WAAW,QAAyB,CAAC;AAYlD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEjD;AAMD,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAEzD;AAED,wBAAgB,SAAS,CACvB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACtC;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,SAAS,CAiC/D;AA4UD,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,UAAU,CAE7F;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAElF;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS,CAKlF;AAmGD,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,GAAG,OAAO,CAiChE"}
|
|
1
|
+
{"version":3,"file":"definition.d.ts","sourceRoot":"","sources":["../src/definition.ts"],"names":[],"mappings":"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"}
|
package/dist/definition.js
CHANGED
|
@@ -370,6 +370,54 @@ export function memberFacts(facts, key) {
|
|
|
370
370
|
const pattern = facts.patterns?.find((one) => new RegExp(one.pattern, 'u').test(key));
|
|
371
371
|
return pattern === undefined ? facts.additional : pattern.facts;
|
|
372
372
|
}
|
|
373
|
+
export function crossedFacts(facts) {
|
|
374
|
+
if (facts.type !== 'array')
|
|
375
|
+
return [facts];
|
|
376
|
+
return [...(facts.prefix ?? []), ...(facts.items === undefined ? [] : [facts.items])].flatMap(crossedFacts);
|
|
377
|
+
}
|
|
378
|
+
export function fieldFacts(definition, key) {
|
|
379
|
+
if (Object.hasOwn(definition.fields, key))
|
|
380
|
+
return definition.fields[key];
|
|
381
|
+
if (Object.hasOwn(HOUSE_KEYS, key))
|
|
382
|
+
return undefined;
|
|
383
|
+
return memberFacts(definition.frontmatter, key);
|
|
384
|
+
}
|
|
385
|
+
function stepped({ facts, through, conditional }, token) {
|
|
386
|
+
if (facts.type === 'array' && ARRAY_INDEX.test(token)) {
|
|
387
|
+
const item = itemFacts(facts, Number(token));
|
|
388
|
+
return item === undefined ? [] : [{ facts: item, through, conditional }];
|
|
389
|
+
}
|
|
390
|
+
return crossedFacts(facts).flatMap((crossed) => {
|
|
391
|
+
const member = memberFacts(crossed, token);
|
|
392
|
+
return member === undefined
|
|
393
|
+
? []
|
|
394
|
+
: [
|
|
395
|
+
{
|
|
396
|
+
facts: member,
|
|
397
|
+
through: through || facts.type === 'array',
|
|
398
|
+
conditional: conditional || member.conditional === true,
|
|
399
|
+
},
|
|
400
|
+
];
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
export function pointerFacts(definition, pointer) {
|
|
404
|
+
const [field, ...rest] = pointerSegments(pointer);
|
|
405
|
+
const declared = field === undefined ? undefined : fieldFacts(definition, field);
|
|
406
|
+
if (declared === undefined)
|
|
407
|
+
return undefined;
|
|
408
|
+
let reached = [
|
|
409
|
+
{ facts: declared, through: false, conditional: declared.conditional === true },
|
|
410
|
+
];
|
|
411
|
+
for (const token of rest)
|
|
412
|
+
reached = reached.flatMap((held) => stepped(held, token));
|
|
413
|
+
if (reached.length === 0)
|
|
414
|
+
return undefined;
|
|
415
|
+
return reached.reduce((kept, held) => ({
|
|
416
|
+
facts: joined(kept.facts, held.facts),
|
|
417
|
+
through: kept.through || held.through,
|
|
418
|
+
conditional: kept.conditional || held.conditional,
|
|
419
|
+
}));
|
|
420
|
+
}
|
|
373
421
|
function reachedDefs(value, defs, reached) {
|
|
374
422
|
if (Array.isArray(value)) {
|
|
375
423
|
for (const item of value)
|
package/dist/document.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMhF,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,WAAW,EAEZ,MAAM,YAAY,CAAC;AACpB,OAAO,
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAMhF,OAAO,KAAK,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,QAAQ,EACR,IAAI,EACJ,WAAW,EAEZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAaL,KAAK,OAAO,EAEb,MAAM,WAAW,CAAC;AAwCnB,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,WAAW,CAkD7D;AA8KD,wBAAgB,UAAU,CACxB,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,GACtB,WAAW,CAYb;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAOrF;AAED,wBAAgB,UAAU,CACxB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACjC,UAAU,CAeZ;AAeD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,IAAI,EAAE,CAEvE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,IAAI,EAAE,CAErE;AAED,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAOrE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAE9D"}
|
package/dist/document.js
CHANGED
|
@@ -4,7 +4,7 @@ import { relative, retarget, SHELL_ROOMS, shellTarget, target } from './paths.js
|
|
|
4
4
|
import { references } from './references.js';
|
|
5
5
|
import { headingSpans, sectionsRecord } from './sections.js';
|
|
6
6
|
import { refusal } from './refuse.js';
|
|
7
|
-
import { bodyStartAfterYaml, bodyStartOf, equalValue, extractFrontmatter, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError, } from './yaml.js';
|
|
7
|
+
import { bodyStartAfterYaml, bodyStartOf, equalValue, extractFrontmatter, frontmatterValue, jsValue, lineEnding, mapEntry, parseYamlMapping, serializeJs, serializeKey, YamlError, } from './yaml.js';
|
|
8
8
|
const internals = new WeakMap();
|
|
9
9
|
function refuse(file, rule, location) {
|
|
10
10
|
return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });
|
|
@@ -78,6 +78,9 @@ function applyField(document, name, value, prior) {
|
|
|
78
78
|
if (!equalValue(document.fields[name], prior)) {
|
|
79
79
|
return { outcome: 'stale', document };
|
|
80
80
|
}
|
|
81
|
+
if (!frontmatterValue(value)) {
|
|
82
|
+
return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', name) };
|
|
83
|
+
}
|
|
81
84
|
let nextContent;
|
|
82
85
|
const existing = mapEntry(internal.root, name);
|
|
83
86
|
if (existing !== undefined) {
|
|
@@ -297,17 +300,9 @@ export function apply(document, change) {
|
|
|
297
300
|
return applyReference(document, change.pointer, change.value, change.prior);
|
|
298
301
|
if (change.kind === 'preamble')
|
|
299
302
|
return applyPreamble(document, change.value, change.prior);
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return applySection(document, change.name, change.value, change.prior);
|
|
304
|
-
}
|
|
305
|
-
catch (error) {
|
|
306
|
-
if (error instanceof YamlError) {
|
|
307
|
-
return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', change.name) };
|
|
308
|
-
}
|
|
309
|
-
throw error;
|
|
310
|
-
}
|
|
303
|
+
if (change.kind === 'field')
|
|
304
|
+
return applyField(document, change.name, change.value, change.prior);
|
|
305
|
+
return applySection(document, change.name, change.value, change.prior);
|
|
311
306
|
}
|
|
312
307
|
export function serialize(document) {
|
|
313
308
|
return document.content;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { dated, factKind, facts, fires, holds, instant, itemFires, pointed, WRITE_DOORS, } from './condition.js';
|
|
1
|
+
export { dated, factKind, facts, fires, holds, instant, itemFires, pointed, prosePaths, WRITE_DOORS, } from './condition.js';
|
|
2
2
|
export type { Actor, Condition, ConditionScope, ConditionTest, ConditionValue, CronCondition, DateCondition, DocumentCondition, DocumentEvent, DocumentFacts, Fact, FactKind, ItemCondition, ItemFacts, Resolved, WriteDoor, } from './condition.js';
|
|
3
3
|
export { divide } from './divide.js';
|
|
4
4
|
export { apply, bodyLinks, links, parse, relativize, relativizeBody, relinkBody, serialize, } from './document.js';
|
|
@@ -7,9 +7,11 @@ export { relative, retarget, target } from './paths.js';
|
|
|
7
7
|
export { MARKDOWN_SYNTAX_PROFILE } from './profile.js';
|
|
8
8
|
export { project } from './project.js';
|
|
9
9
|
export { references } from './references.js';
|
|
10
|
-
export { ARRAY_INDEX, ATTACHMENT, escapePointer, itemFacts, memberFacts, pointerSegments, } from './definition.js';
|
|
11
|
-
export type { Definition, JsonType, PatternFacts, SectionSpec, Shape, ValueFacts, } from './definition.js';
|
|
10
|
+
export { ARRAY_INDEX, ATTACHMENT, crossedFacts, escapePointer, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
|
|
11
|
+
export type { Definition, JsonType, PatternFacts, PointerFacts, SectionSpec, Shape, ValueFacts, } from './definition.js';
|
|
12
12
|
export type { ApplyResult, BodyResult, Change, Division, DivisionContext, Document, Library, ModelVerification, Link, ParseResult, Projection, ProjectionContext, Reference, Refusal, Span, Validation, ValidationContext, VerifiedModel, } from './types.js';
|
|
13
13
|
export { validate, verify } from './validate.js';
|
|
14
14
|
export { VERSION } from './version.js';
|
|
15
|
+
export { equalValue, frontmatterValue } from './yaml.js';
|
|
16
|
+
export type { FrontmatterValue } from './yaml.js';
|
|
15
17
|
//# 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,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,SAAS,EACT,QAAQ,EACR,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,KAAK,EACL,SAAS,EACT,KAAK,EACL,KAAK,EACL,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,UAAU,EACV,aAAa,EACb,SAAS,EACT,WAAW,EACX,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,WAAW,EACX,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,QAAQ,EACR,KAAK,EACL,KAAK,EACL,KAAK,EACL,OAAO,EACP,SAAS,EACT,OAAO,EACP,UAAU,EACV,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,YAAY,EACV,KAAK,EACL,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,aAAa,EACb,IAAI,EACJ,QAAQ,EACR,aAAa,EACb,SAAS,EACT,QAAQ,EACR,SAAS,GACV,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACL,KAAK,EACL,SAAS,EACT,KAAK,EACL,KAAK,EACL,UAAU,EACV,cAAc,EACd,UAAU,EACV,SAAS,GACV,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACvE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AACvD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,EACb,SAAS,EACT,WAAW,EACX,YAAY,EACZ,eAAe,GAChB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,UAAU,EACV,QAAQ,EACR,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,KAAK,EACL,UAAU,GACX,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,WAAW,EACX,UAAU,EACV,MAAM,EACN,QAAQ,EACR,eAAe,EACf,QAAQ,EACR,OAAO,EACP,iBAAiB,EACjB,IAAI,EACJ,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,SAAS,EACT,OAAO,EACP,IAAI,EACJ,UAAU,EACV,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACzD,YAAY,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { dated, factKind, facts, fires, holds, instant, itemFires, pointed, WRITE_DOORS, } from './condition.js';
|
|
1
|
+
export { dated, factKind, facts, fires, holds, instant, itemFires, pointed, prosePaths, WRITE_DOORS, } from './condition.js';
|
|
2
2
|
export { divide } from './divide.js';
|
|
3
3
|
export { apply, bodyLinks, links, parse, relativize, relativizeBody, relinkBody, serialize, } from './document.js';
|
|
4
4
|
export { MEMBER_FIELD, RECEIVED_FIELD, SITE_FIELD } from './fields.js';
|
|
@@ -6,6 +6,7 @@ export { relative, retarget, target } from './paths.js';
|
|
|
6
6
|
export { MARKDOWN_SYNTAX_PROFILE } from './profile.js';
|
|
7
7
|
export { project } from './project.js';
|
|
8
8
|
export { references } from './references.js';
|
|
9
|
-
export { ARRAY_INDEX, ATTACHMENT, escapePointer, itemFacts, memberFacts, pointerSegments, } from './definition.js';
|
|
9
|
+
export { ARRAY_INDEX, ATTACHMENT, crossedFacts, escapePointer, itemFacts, memberFacts, pointerFacts, pointerSegments, } from './definition.js';
|
|
10
10
|
export { validate, verify } from './validate.js';
|
|
11
11
|
export { VERSION } from './version.js';
|
|
12
|
+
export { equalValue, frontmatterValue } from './yaml.js';
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAGV,OAAO,EACP,iBAAiB,
|
|
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"}
|
package/dist/validate.js
CHANGED
|
@@ -18,7 +18,7 @@ function instanceType(document) {
|
|
|
18
18
|
return null;
|
|
19
19
|
return raw;
|
|
20
20
|
}
|
|
21
|
-
function reaches(file, href, to,
|
|
21
|
+
function reaches(file, href, to, types, binaryTargets) {
|
|
22
22
|
const resolved = classifyHref(file, href);
|
|
23
23
|
if (resolved.kind !== 'path')
|
|
24
24
|
return false;
|
|
@@ -26,8 +26,8 @@ function reaches(file, href, to, documents, binaryTargets) {
|
|
|
26
26
|
return true;
|
|
27
27
|
if (binaryTargets.has(resolved.path))
|
|
28
28
|
return false;
|
|
29
|
-
const held =
|
|
30
|
-
return held === undefined ||
|
|
29
|
+
const held = types.get(resolved.path);
|
|
30
|
+
return held === undefined || to.includes(held);
|
|
31
31
|
}
|
|
32
32
|
function itemHrefs(content, items) {
|
|
33
33
|
const bodyStart = bodyStartOf(content);
|
|
@@ -56,28 +56,28 @@ export function verify(schema) {
|
|
|
56
56
|
export function validate(library, context = { binaryTargets: [] }, model = { types: {} }) {
|
|
57
57
|
const binaryTargets = new Set(context.binaryTargets);
|
|
58
58
|
const files = Object.keys(library).sort();
|
|
59
|
+
const types = new Map();
|
|
59
60
|
const documents = new Map();
|
|
60
61
|
for (const file of files) {
|
|
61
62
|
if (binaryTargets.has(file))
|
|
62
63
|
return refuse(file, 'binary-target-document');
|
|
63
64
|
const parsed = parse(library[file], file);
|
|
64
|
-
documents.set(file, parsed);
|
|
65
65
|
if (!parsed.ok)
|
|
66
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);
|
|
67
70
|
}
|
|
68
71
|
const definitions = new Map(Object.entries(model.types));
|
|
69
72
|
const sectionReferences = new Map();
|
|
70
|
-
for (const file of
|
|
71
|
-
const
|
|
72
|
-
if (parsed === undefined || !parsed.ok)
|
|
73
|
-
continue;
|
|
74
|
-
const kind = instanceType(parsed.document);
|
|
73
|
+
for (const [file, document] of documents) {
|
|
74
|
+
const kind = instanceType(document);
|
|
75
75
|
if (kind === BUILT_IN_TYPE)
|
|
76
76
|
continue;
|
|
77
77
|
const definition = kind === null ? undefined : definitions.get(kind);
|
|
78
78
|
if (definition === undefined)
|
|
79
79
|
return refuse(file, 'unknown-type', { location: '/type' });
|
|
80
|
-
const fieldFailure = frontmatterRefusal(definition,
|
|
80
|
+
const fieldFailure = frontmatterRefusal(definition, document.fields);
|
|
81
81
|
if (fieldFailure !== undefined) {
|
|
82
82
|
return refuse(file, fieldFailure.rule, { location: fieldFailure.location });
|
|
83
83
|
}
|
|
@@ -105,18 +105,15 @@ export function validate(library, context = { binaryTargets: [] }, model = { typ
|
|
|
105
105
|
}
|
|
106
106
|
sectionReferences.set(file, references);
|
|
107
107
|
}
|
|
108
|
-
for (const file of
|
|
109
|
-
const
|
|
110
|
-
if (parsed === undefined || !parsed.ok)
|
|
111
|
-
continue;
|
|
112
|
-
const kind = instanceType(parsed.document);
|
|
108
|
+
for (const [file, document] of documents) {
|
|
109
|
+
const kind = instanceType(document);
|
|
113
110
|
if (kind === null || kind === BUILT_IN_TYPE)
|
|
114
111
|
continue;
|
|
115
112
|
const definition = definitions.get(kind);
|
|
116
113
|
if (definition === undefined)
|
|
117
114
|
continue;
|
|
118
|
-
for (const { pointer, to, value } of references(
|
|
119
|
-
if (!reaches(file, value, to,
|
|
115
|
+
for (const { pointer, to, value } of references(document, definition)) {
|
|
116
|
+
if (!reaches(file, value, to, types, binaryTargets))
|
|
120
117
|
return refuse(file, 'unresolved-reference', { location: pointer });
|
|
121
118
|
}
|
|
122
119
|
const body = bodyAfterFrontmatter(library[file]);
|
|
@@ -127,24 +124,21 @@ export function validate(library, context = { binaryTargets: [] }, model = { typ
|
|
|
127
124
|
}
|
|
128
125
|
for (const { section, to, hrefs } of sectionReferences.get(file)) {
|
|
129
126
|
for (const href of hrefs) {
|
|
130
|
-
if (!reaches(file, href, to,
|
|
127
|
+
if (!reaches(file, href, to, types, binaryTargets))
|
|
131
128
|
return refuse(file, 'unresolved-reference', { location: section });
|
|
132
129
|
}
|
|
133
130
|
}
|
|
134
131
|
}
|
|
135
132
|
const missing = new Map();
|
|
136
|
-
for (const file of
|
|
137
|
-
const
|
|
138
|
-
if (parsed === undefined || !parsed.ok)
|
|
139
|
-
continue;
|
|
140
|
-
const kind = instanceType(parsed.document);
|
|
133
|
+
for (const [file, document] of documents) {
|
|
134
|
+
const kind = instanceType(document);
|
|
141
135
|
if (kind === null || kind === BUILT_IN_TYPE)
|
|
142
136
|
continue;
|
|
143
137
|
const definition = definitions.get(kind);
|
|
144
138
|
if (definition === undefined)
|
|
145
139
|
continue;
|
|
146
140
|
const named = [
|
|
147
|
-
...references(
|
|
141
|
+
...references(document, definition),
|
|
148
142
|
...sectionReferences
|
|
149
143
|
.get(file)
|
|
150
144
|
.flatMap(({ to, hrefs }) => hrefs.map((value) => ({ value, to }))),
|
|
@@ -155,7 +149,7 @@ export function validate(library, context = { binaryTargets: [] }, model = { typ
|
|
|
155
149
|
const resolved = classifyHref(file, value);
|
|
156
150
|
if (resolved.kind !== 'path')
|
|
157
151
|
continue;
|
|
158
|
-
if (
|
|
152
|
+
if (types.has(resolved.path) || binaryTargets.has(resolved.path))
|
|
159
153
|
continue;
|
|
160
154
|
const referrers = missing.get(resolved.path) ?? [];
|
|
161
155
|
referrers.push(file);
|
package/dist/yaml.d.ts
CHANGED
|
@@ -32,7 +32,12 @@ export declare function parseYamlMapping(text: string, start: number, end: numbe
|
|
|
32
32
|
export declare function jsValue(node: YamlNode): unknown;
|
|
33
33
|
export declare function mapEntry(map: YamlMap, key: string): YamlEntry | undefined;
|
|
34
34
|
export declare function isPlainSafe(text: string): boolean;
|
|
35
|
-
export
|
|
35
|
+
export type FrontmatterValue = string | number | boolean | null | readonly FrontmatterValue[] | {
|
|
36
|
+
readonly [name: string]: FrontmatterValue;
|
|
37
|
+
};
|
|
38
|
+
export declare function plain(value: unknown): value is Record<string, unknown>;
|
|
39
|
+
export declare function frontmatterValue(value: unknown): value is FrontmatterValue;
|
|
40
|
+
export declare function serializeJs(value: FrontmatterValue): string;
|
|
36
41
|
export declare function isRecord(value: unknown): value is Record<string, unknown>;
|
|
37
42
|
export declare function serializeKey(name: string): string;
|
|
38
43
|
export declare function bodyStartAfterYaml(content: string, yamlEnd: number): number;
|
package/dist/yaml.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../src/yaml.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAnC,YAAqB,MAAM,EAAE,MAAM,EAGlC;CACF;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAoEtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAM7E;AA0QD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAclF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/C;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEzE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD;AAED,wBAAgB,
|
|
1
|
+
{"version":3,"file":"yaml.d.ts","sourceRoot":"","sources":["../src/yaml.ts"],"names":[],"mappings":"AAAA,qBAAa,SAAU,SAAQ,KAAK;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM;IAAnC,YAAqB,MAAM,EAAE,MAAM,EAGlC;CACF;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,SAAS,GAAG;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,SAAS,SAAS,EAAE,CAAC;IACvC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,GAAG,OAAO,CAAC;AAoEtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,CAM7E;AA0QD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAclF;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAM/C;AAED,wBAAgB,QAAQ,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAEzE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAMjD;AAED,MAAM,MAAM,gBAAgB,GACxB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,gBAAgB,EAAE,GAC3B;IAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAAA;CAAE,CAAC;AAElD,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAItE;AAiBD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,gBAAgB,CAE1E;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,MAAM,CAO3D;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG3E;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGnD;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,GACd;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAqB9F;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAgBjE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAEzD"}
|
package/dist/yaml.js
CHANGED
|
@@ -418,24 +418,42 @@ export function isPlainSafe(text) {
|
|
|
418
418
|
return false;
|
|
419
419
|
return true;
|
|
420
420
|
}
|
|
421
|
+
export function plain(value) {
|
|
422
|
+
if (!isRecord(value))
|
|
423
|
+
return false;
|
|
424
|
+
const prototype = Object.getPrototypeOf(value);
|
|
425
|
+
return prototype === Object.prototype || prototype === null;
|
|
426
|
+
}
|
|
427
|
+
function listed(value) {
|
|
428
|
+
const keys = Object.keys(value);
|
|
429
|
+
return keys.length === value.length && keys.every((key, index) => key === String(index));
|
|
430
|
+
}
|
|
431
|
+
function heldWithin(value, within) {
|
|
432
|
+
if (value === null || typeof value === 'string' || typeof value === 'boolean')
|
|
433
|
+
return true;
|
|
434
|
+
if (typeof value === 'number')
|
|
435
|
+
return Number.isFinite(value);
|
|
436
|
+
if (typeof value !== 'object' || within.includes(value))
|
|
437
|
+
return false;
|
|
438
|
+
const path = [...within, value];
|
|
439
|
+
const held = (item) => heldWithin(item, path);
|
|
440
|
+
if (Array.isArray(value))
|
|
441
|
+
return listed(value) && value.every(held);
|
|
442
|
+
return plain(value) && Object.values(value).every(held);
|
|
443
|
+
}
|
|
444
|
+
export function frontmatterValue(value) {
|
|
445
|
+
return heldWithin(value, []);
|
|
446
|
+
}
|
|
421
447
|
export function serializeJs(value) {
|
|
422
|
-
if (value === null)
|
|
423
|
-
return 'null';
|
|
424
|
-
if (value === true)
|
|
425
|
-
return 'true';
|
|
426
|
-
if (value === false)
|
|
427
|
-
return 'false';
|
|
428
|
-
if (typeof value === 'number' && Number.isFinite(value))
|
|
429
|
-
return JSON.stringify(value);
|
|
430
448
|
if (typeof value === 'string')
|
|
431
449
|
return isPlainSafe(value) ? value : JSON.stringify(value);
|
|
450
|
+
if (value === null || typeof value !== 'object')
|
|
451
|
+
return JSON.stringify(value);
|
|
432
452
|
if (Array.isArray(value))
|
|
433
453
|
return `[${value.map(serializeJs).join(', ')}]`;
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
.join(', ')}}`;
|
|
438
|
-
throw new YamlError(0);
|
|
454
|
+
return `{${Object.entries(value)
|
|
455
|
+
.map(([key, held]) => `${serializeKey(key)}: ${serializeJs(held)}`)
|
|
456
|
+
.join(', ')}}`;
|
|
439
457
|
}
|
|
440
458
|
export function isRecord(value) {
|
|
441
459
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
@@ -485,7 +503,8 @@ export function equalValue(left, right) {
|
|
|
485
503
|
if (left === right)
|
|
486
504
|
return true;
|
|
487
505
|
if (Array.isArray(left) && Array.isArray(right)) {
|
|
488
|
-
return (left.length === right.length &&
|
|
506
|
+
return (left.length === right.length &&
|
|
507
|
+
Array.from(left).every((item, index) => equalValue(item, right[index])));
|
|
489
508
|
}
|
|
490
509
|
if (isRecord(left) && isRecord(right)) {
|
|
491
510
|
const keys = Object.keys(left);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentshouse/mdmodel",
|
|
3
|
-
"version": "0.1.0-
|
|
3
|
+
"version": "0.1.0-c4fe1bc82bc55",
|
|
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",
|