@agentshouse/mdmodel 0.1.0-alpha.9 → 0.1.0-cf72583e19192
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 +298 -0
- package/README.md +30 -186
- package/dist/blocks.d.ts +11 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +62 -0
- package/dist/condition.d.ts +93 -0
- package/dist/condition.d.ts.map +1 -0
- package/dist/condition.js +240 -0
- package/dist/definition.d.ts +7 -3
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +143 -134
- package/dist/divide.d.ts +3 -0
- package/dist/divide.d.ts.map +1 -0
- package/dist/divide.js +310 -0
- package/dist/document.d.ts +2 -0
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +89 -120
- package/dist/fields.d.ts +4 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +3 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/links.d.ts +1 -0
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +618 -224
- package/dist/paths.d.ts +2 -3
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +27 -37
- package/dist/profile.js +1 -3
- package/dist/project.d.ts +19 -1
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +75 -91
- package/dist/refuse.d.ts.map +1 -1
- package/dist/refuse.js +2 -10
- package/dist/schema.d.ts +3 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +24 -33
- package/dist/sections.d.ts +2 -1
- package/dist/sections.d.ts.map +1 -1
- package/dist/sections.js +44 -66
- package/dist/types.d.ts +30 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -3
- package/dist/validate.d.ts +5 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +145 -127
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -3
- package/dist/yaml.d.ts +1 -0
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +195 -186
- package/fixtures/README.md +77 -53
- package/fixtures/cases/binary-any-reference/expected.json +0 -1
- package/fixtures/cases/binary-any-reference/schema.yaml +4 -0
- package/fixtures/cases/binary-document-collision/expected.json +1 -2
- package/fixtures/cases/binary-document-collision/schema.yaml +2 -0
- package/fixtures/cases/binary-link-outside-collection/expected.json +1 -2
- package/fixtures/cases/binary-link-outside-collection/schema.yaml +2 -0
- package/fixtures/cases/binary-prototype-reference/expected.json +0 -1
- package/fixtures/cases/binary-prototype-reference/schema.yaml +4 -0
- package/fixtures/cases/binary-typed-reference/expected.json +0 -1
- package/fixtures/cases/binary-typed-reference/schema.yaml +5 -0
- package/fixtures/cases/bracketed-link-definition/schema.yaml +6 -0
- package/fixtures/cases/declared-binary-links/schema.yaml +2 -0
- package/fixtures/cases/duplicate-link-definition/schema.yaml +6 -0
- package/fixtures/cases/fenced-link-definition/schema.yaml +6 -0
- package/fixtures/cases/field-enum/expected.json +1 -2
- package/fixtures/cases/field-enum/schema.yaml +7 -0
- package/fixtures/cases/frontmatter-schema/expected.json +5 -0
- package/fixtures/cases/frontmatter-schema/schema.yaml +6 -0
- package/fixtures/cases/interrupted-link-definition/schema.yaml +2 -0
- package/fixtures/cases/long-fence-link-definition/schema.yaml +2 -0
- package/fixtures/cases/malformed-definition/expected.json +2 -4
- package/fixtures/cases/malformed-definition/schema.yaml +4 -0
- package/fixtures/cases/member-document/context.json +1 -0
- package/fixtures/cases/member-document/library/people/ana.md +5 -0
- package/fixtures/cases/member-document/schema.yaml +5 -0
- package/fixtures/cases/missing-binary-image/expected.json +1 -2
- package/fixtures/cases/missing-binary-image/schema.yaml +2 -0
- package/fixtures/cases/missing-binary-link/expected.json +1 -2
- package/fixtures/cases/missing-binary-link/schema.yaml +2 -0
- package/fixtures/cases/missing-required-field/expected.json +1 -2
- package/fixtures/cases/missing-required-field/schema.yaml +7 -0
- package/fixtures/cases/missing-section-item-kind/expected.json +2 -4
- package/fixtures/cases/missing-section-item-kind/schema.yaml +6 -0
- package/fixtures/cases/paragraph-link-definition/schema.yaml +2 -0
- package/fixtures/cases/prototype-field/expected.json +1 -2
- package/fixtures/cases/prototype-field/schema.yaml +6 -0
- package/fixtures/cases/quoted-link-definition/expected.json +1 -2
- package/fixtures/cases/quoted-link-definition/schema.yaml +2 -0
- package/fixtures/cases/referenced-missing-file/expected.json +0 -1
- package/fixtures/cases/referenced-missing-file/schema.yaml +10 -0
- package/fixtures/cases/second-member-document/context.json +1 -0
- package/fixtures/cases/second-member-document/expected.json +5 -0
- package/fixtures/cases/second-member-document/schema.yaml +5 -0
- package/fixtures/cases/section-item-enum/context.json +1 -0
- package/fixtures/cases/section-item-enum/expected.json +6 -0
- package/fixtures/cases/section-item-enum/library/task.md +8 -0
- package/fixtures/cases/section-item-enum/schema.yaml +4 -0
- package/fixtures/cases/section-item-kind/context.json +1 -0
- package/fixtures/cases/section-item-kind/expected.json +6 -0
- package/fixtures/cases/section-item-kind/library/task.md +8 -0
- package/fixtures/cases/section-item-kind/schema.yaml +4 -0
- package/fixtures/cases/section-items/context.json +1 -0
- package/fixtures/cases/section-items/expected.json +1 -0
- package/fixtures/cases/section-items/library/other.md +3 -0
- package/fixtures/cases/section-items/library/page.md +28 -0
- package/fixtures/cases/section-items/schema.yaml +8 -0
- package/fixtures/cases/section-reference-path/context.json +1 -0
- package/fixtures/cases/section-reference-path/expected.json +6 -0
- package/fixtures/cases/section-reference-path/library/other.md +3 -0
- package/fixtures/cases/section-reference-path/library/page.md +7 -0
- package/fixtures/cases/section-reference-path/schema.yaml +4 -0
- package/fixtures/cases/section-reference-type/context.json +1 -0
- package/fixtures/cases/section-reference-type/expected.json +6 -0
- package/fixtures/cases/section-reference-type/library/note.md +1 -0
- package/fixtures/cases/section-reference-type/library/page.md +7 -0
- package/fixtures/cases/section-reference-type/schema.yaml +4 -0
- package/fixtures/cases/shortcut-reference-link/context.json +1 -0
- package/fixtures/cases/shortcut-reference-link/expected.json +5 -0
- package/fixtures/cases/shortcut-reference-link/library/item.md +10 -0
- package/fixtures/cases/shortcut-reference-link/schema.yaml +6 -0
- package/fixtures/cases/structured-section/expected.json +1 -2
- package/fixtures/cases/structured-section/schema.yaml +7 -0
- package/fixtures/cases/submission-keys/context.json +1 -0
- package/fixtures/cases/submission-keys/expected.json +1 -0
- package/fixtures/cases/submission-keys/library/notes/visitor.md +8 -0
- package/fixtures/cases/submission-keys/schema.yaml +4 -0
- package/fixtures/cases/text-field-kind/context.json +1 -0
- package/fixtures/cases/text-field-kind/expected.json +6 -0
- package/fixtures/cases/text-field-kind/library/page.md +4 -0
- package/fixtures/cases/text-field-kind/schema.yaml +4 -0
- package/fixtures/cases/truncated-link-definition/expected.json +1 -2
- package/fixtures/cases/truncated-link-definition/schema.yaml +2 -0
- package/fixtures/cases/types-folder-content/context.json +1 -0
- package/fixtures/cases/types-folder-content/expected.json +1 -0
- package/fixtures/cases/types-folder-content/library/types/task.md +4 -0
- package/fixtures/cases/types-folder-content/schema.yaml +4 -0
- package/fixtures/cases/unclosed-frontmatter/expected.json +1 -2
- package/fixtures/cases/undeclared-field/expected.json +1 -2
- package/fixtures/cases/undeclared-field/schema.yaml +6 -0
- package/fixtures/cases/unknown-type/context.json +1 -0
- package/fixtures/cases/unknown-type/expected.json +6 -0
- package/fixtures/cases/unknown-type/library/item.md +3 -0
- package/fixtures/cases/unknown-type/schema.yaml +4 -0
- package/fixtures/cases/unlisted-reference-type/context.json +1 -0
- package/fixtures/cases/unlisted-reference-type/expected.json +5 -0
- package/fixtures/cases/unlisted-reference-type/schema.yaml +4 -0
- package/fixtures/cases/unresolved-link/expected.json +1 -2
- package/fixtures/cases/unresolved-link/schema.yaml +6 -0
- package/fixtures/cases/valid-typed-document/schema.yaml +15 -0
- package/fixtures/cases/wide-item-fence-link/schema.yaml +2 -0
- package/fixtures/division.json +409 -0
- package/fixtures/projection.json +58 -21
- package/package.json +3 -12
- package/dist/definition.js.map +0 -1
- package/dist/document.js.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/links.js.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/profile.js.map +0 -1
- package/dist/project.js.map +0 -1
- package/dist/refuse.js.map +0 -1
- package/dist/schema.js.map +0 -1
- package/dist/sections.js.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/validate.js.map +0 -1
- package/dist/version.js.map +0 -1
- package/dist/yaml.js.map +0 -1
- package/fixtures/cases/binary-any-reference/library/types/note.md +0 -5
- package/fixtures/cases/binary-document-collision/library/types/note.md +0 -3
- package/fixtures/cases/binary-link-outside-collection/library/types/note.md +0 -3
- package/fixtures/cases/binary-prototype-reference/library/types/note.md +0 -5
- package/fixtures/cases/binary-typed-reference/library/types/note.md +0 -5
- package/fixtures/cases/binary-typed-reference/library/types/person.md +0 -3
- package/fixtures/cases/bracketed-link-definition/library/types/task.md +0 -7
- package/fixtures/cases/declared-binary-links/library/types/note.md +0 -3
- package/fixtures/cases/duplicate-link-definition/library/types/task.md +0 -7
- package/fixtures/cases/fenced-link-definition/library/types/task.md +0 -7
- package/fixtures/cases/field-enum/library/types/task.md +0 -8
- package/fixtures/cases/interrupted-link-definition/library/types/note.md +0 -3
- package/fixtures/cases/long-fence-link-definition/library/types/note.md +0 -3
- package/fixtures/cases/malformed-definition/library/types/task.md +0 -5
- package/fixtures/cases/missing-binary-image/library/types/note.md +0 -3
- package/fixtures/cases/missing-binary-link/library/types/note.md +0 -3
- package/fixtures/cases/missing-required-field/library/types/task.md +0 -8
- package/fixtures/cases/missing-section-item-kind/library/types/task.md +0 -7
- package/fixtures/cases/paragraph-link-definition/library/types/note.md +0 -3
- package/fixtures/cases/prd-definition/library/types/task.md +0 -16
- package/fixtures/cases/prototype-field/library/types/task.md +0 -7
- package/fixtures/cases/quoted-link-definition/library/types/note.md +0 -3
- package/fixtures/cases/referenced-missing-file/library/types/person.md +0 -5
- package/fixtures/cases/referenced-missing-file/library/types/task.md +0 -8
- package/fixtures/cases/structured-section/library/types/task.md +0 -8
- package/fixtures/cases/truncated-link-definition/library/types/note.md +0 -3
- package/fixtures/cases/undeclared-field/library/types/task.md +0 -7
- package/fixtures/cases/unresolved-link/library/types/task.md +0 -7
- package/fixtures/cases/valid-typed-document/library/types/person.md +0 -5
- package/fixtures/cases/valid-typed-document/library/types/task.md +0 -13
- package/fixtures/cases/wide-item-fence-link/library/types/note.md +0 -3
- package/markdown-syntax-profile.md +0 -9
- /package/fixtures/cases/{prd-definition → frontmatter-schema}/context.json +0 -0
- /package/fixtures/cases/{prd-definition → member-document}/expected.json +0 -0
package/dist/definition.js
CHANGED
|
@@ -1,171 +1,180 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
return location === undefined ? refusal(file, rule) : refusal(file, rule, {
|
|
5
|
-
location
|
|
6
|
-
});
|
|
1
|
+
import { jsValue, parseYamlMapping, YamlError } from './yaml.js';
|
|
2
|
+
function refuse(rule, location) {
|
|
3
|
+
return location === undefined ? { rule } : { rule, location };
|
|
7
4
|
}
|
|
8
5
|
function isRecord(value) {
|
|
9
6
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
10
7
|
}
|
|
11
8
|
function requiredFlag(value) {
|
|
12
|
-
if (value === undefined)
|
|
13
|
-
|
|
9
|
+
if (value === undefined)
|
|
10
|
+
return false;
|
|
11
|
+
if (typeof value === 'boolean')
|
|
12
|
+
return value;
|
|
14
13
|
return undefined;
|
|
15
14
|
}
|
|
16
15
|
function stringList(value) {
|
|
17
|
-
if (!Array.isArray(value) || value.length === 0)
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
if (!Array.isArray(value) || value.length === 0)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (!value.every((item) => typeof item === 'string' && item !== ''))
|
|
19
|
+
return undefined;
|
|
20
|
+
return [...value];
|
|
20
21
|
}
|
|
21
|
-
const SCALAR_KINDS = new Set([
|
|
22
|
-
|
|
23
|
-
'string',
|
|
24
|
-
'number',
|
|
25
|
-
'date',
|
|
26
|
-
'enum',
|
|
27
|
-
'reference'
|
|
28
|
-
]);
|
|
29
|
-
function parseScalar(file, location, spec, required) {
|
|
22
|
+
const SCALAR_KINDS = new Set(['text', 'string', 'number', 'date', 'enum', 'reference']);
|
|
23
|
+
function parseScalar(names, location, spec, required) {
|
|
30
24
|
const kind = spec.kind;
|
|
31
|
-
if (kind === 'text')
|
|
32
|
-
kind: 'text',
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
if (kind === '
|
|
36
|
-
kind: '
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (kind === 'number') return {
|
|
40
|
-
kind: 'number',
|
|
41
|
-
required
|
|
42
|
-
};
|
|
43
|
-
if (kind === 'date') return {
|
|
44
|
-
kind: 'date',
|
|
45
|
-
required
|
|
46
|
-
};
|
|
25
|
+
if (kind === 'text')
|
|
26
|
+
return { kind: 'text', required };
|
|
27
|
+
if (kind === 'string')
|
|
28
|
+
return { kind: 'string', required };
|
|
29
|
+
if (kind === 'number')
|
|
30
|
+
return { kind: 'number', required };
|
|
31
|
+
if (kind === 'date')
|
|
32
|
+
return { kind: 'date', required };
|
|
47
33
|
if (kind === 'enum') {
|
|
48
34
|
const values = stringList(spec.values);
|
|
49
|
-
if (values === undefined)
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
required,
|
|
53
|
-
values
|
|
54
|
-
};
|
|
35
|
+
if (values === undefined)
|
|
36
|
+
return refuse('definition-enum-values', location);
|
|
37
|
+
return { kind: 'enum', required, values };
|
|
55
38
|
}
|
|
56
39
|
if (kind === 'reference') {
|
|
57
|
-
if (typeof spec.to !== 'string' || spec.to
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
required,
|
|
61
|
-
to: spec.to
|
|
62
|
-
};
|
|
40
|
+
if (typeof spec.to !== 'string' || (spec.to !== 'any' && !names.has(spec.to)))
|
|
41
|
+
return refuse('definition-reference-to', location);
|
|
42
|
+
return { kind: 'reference', required, to: spec.to };
|
|
63
43
|
}
|
|
64
|
-
return refuse(
|
|
44
|
+
return refuse('definition-field-kind', location);
|
|
65
45
|
}
|
|
66
46
|
function extraKeys(spec, allowed) {
|
|
67
|
-
return Object.keys(spec).some((key)
|
|
47
|
+
return Object.keys(spec).some((key) => !allowed.includes(key));
|
|
68
48
|
}
|
|
69
|
-
function parseList(
|
|
49
|
+
function parseList(names, location, spec, required, malformed) {
|
|
70
50
|
if (typeof spec.of !== 'string' || !SCALAR_KINDS.has(spec.of)) {
|
|
71
|
-
return refuse(
|
|
51
|
+
return refuse('definition-list-of', location);
|
|
72
52
|
}
|
|
73
|
-
const allowed = spec.of === 'enum'
|
|
74
|
-
'kind',
|
|
75
|
-
'
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
'kind',
|
|
85
|
-
'required',
|
|
86
|
-
'of'
|
|
87
|
-
];
|
|
88
|
-
if (extraKeys(spec, allowed)) return refuse(file, malformed, location);
|
|
89
|
-
const inner = parseScalar(file, location, {
|
|
90
|
-
...spec,
|
|
91
|
-
kind: spec.of
|
|
92
|
-
}, false);
|
|
93
|
-
if ('rule' in inner) return inner;
|
|
94
|
-
return {
|
|
95
|
-
kind: 'list',
|
|
96
|
-
required,
|
|
97
|
-
of: inner
|
|
98
|
-
};
|
|
53
|
+
const allowed = spec.of === 'enum'
|
|
54
|
+
? ['kind', 'required', 'of', 'values']
|
|
55
|
+
: spec.of === 'reference'
|
|
56
|
+
? ['kind', 'required', 'of', 'to']
|
|
57
|
+
: ['kind', 'required', 'of'];
|
|
58
|
+
if (extraKeys(spec, allowed))
|
|
59
|
+
return refuse(malformed, location);
|
|
60
|
+
const inner = parseScalar(names, location, { ...spec, kind: spec.of }, false);
|
|
61
|
+
if ('rule' in inner)
|
|
62
|
+
return inner;
|
|
63
|
+
return { kind: 'list', required, of: inner };
|
|
99
64
|
}
|
|
100
|
-
function parseField(
|
|
101
|
-
if (!isRecord(value) || typeof value.kind !== 'string')
|
|
65
|
+
function parseField(names, location, value) {
|
|
66
|
+
if (!isRecord(value) || typeof value.kind !== 'string')
|
|
67
|
+
return refuse('definition-field', location);
|
|
102
68
|
const required = requiredFlag(value.required);
|
|
103
|
-
if (required === undefined)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
'
|
|
107
|
-
|
|
108
|
-
'values'
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
'required'
|
|
116
|
-
];
|
|
117
|
-
if (extraKeys(value, allowed)) return refuse(file, 'definition-field', location);
|
|
118
|
-
return parseScalar(file, location, value, required);
|
|
69
|
+
if (required === undefined)
|
|
70
|
+
return refuse('definition-field', location);
|
|
71
|
+
if (value.kind === 'list')
|
|
72
|
+
return parseList(names, location, value, required, 'definition-field');
|
|
73
|
+
const allowed = value.kind === 'enum'
|
|
74
|
+
? ['kind', 'required', 'values']
|
|
75
|
+
: value.kind === 'reference'
|
|
76
|
+
? ['kind', 'required', 'to']
|
|
77
|
+
: ['kind', 'required'];
|
|
78
|
+
if (extraKeys(value, allowed))
|
|
79
|
+
return refuse('definition-field', location);
|
|
80
|
+
return parseScalar(names, location, value, required);
|
|
119
81
|
}
|
|
120
|
-
function parseSection(
|
|
121
|
-
if (!isRecord(value) || value.kind !== 'text' && value.kind !== 'list') {
|
|
122
|
-
return refuse(
|
|
82
|
+
function parseSection(names, location, value) {
|
|
83
|
+
if (!isRecord(value) || (value.kind !== 'text' && value.kind !== 'list')) {
|
|
84
|
+
return refuse('definition-section-kind', location);
|
|
123
85
|
}
|
|
124
86
|
const required = requiredFlag(value.required);
|
|
125
|
-
if (required === undefined)
|
|
126
|
-
|
|
127
|
-
if (
|
|
128
|
-
'
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
return {
|
|
132
|
-
kind: 'text',
|
|
133
|
-
required
|
|
134
|
-
};
|
|
87
|
+
if (required === undefined)
|
|
88
|
+
return refuse('definition-section', location);
|
|
89
|
+
if (value.kind === 'list')
|
|
90
|
+
return parseList(names, location, value, required, 'definition-section');
|
|
91
|
+
if (extraKeys(value, ['kind', 'required']))
|
|
92
|
+
return refuse('definition-section', location);
|
|
93
|
+
return { kind: 'text', required };
|
|
135
94
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
for (const key of Object.keys(
|
|
141
|
-
if (key !== '
|
|
142
|
-
return refuse(
|
|
95
|
+
function readType(names, name, value) {
|
|
96
|
+
const location = `types.${name}`;
|
|
97
|
+
if (!isRecord(value))
|
|
98
|
+
return refuse('definition-shape', location);
|
|
99
|
+
for (const key of Object.keys(value)) {
|
|
100
|
+
if (key !== 'fields' && key !== 'sections' && key !== 'member_document') {
|
|
101
|
+
return refuse('definition-shape', `${location}.${key}`);
|
|
143
102
|
}
|
|
144
103
|
}
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
104
|
+
const mark = value.member_document === undefined ? false : value.member_document;
|
|
105
|
+
if (typeof mark !== 'boolean')
|
|
106
|
+
return refuse('definition-shape', `${location}.member_document`);
|
|
107
|
+
const fieldsValue = value.fields;
|
|
108
|
+
const sectionsValue = value.sections;
|
|
109
|
+
if (fieldsValue !== undefined && !isRecord(fieldsValue))
|
|
110
|
+
return refuse('definition-fields', `${location}.fields`);
|
|
148
111
|
if (sectionsValue !== undefined && !isRecord(sectionsValue)) {
|
|
149
|
-
return refuse(
|
|
112
|
+
return refuse('definition-sections', `${location}.sections`);
|
|
150
113
|
}
|
|
151
114
|
const fields = Object.create(null);
|
|
152
|
-
for (const [fieldName, spec] of Object.entries(fieldsValue ?? {})){
|
|
153
|
-
const parsed = parseField(
|
|
154
|
-
if ('rule' in parsed)
|
|
115
|
+
for (const [fieldName, spec] of Object.entries(fieldsValue ?? {})) {
|
|
116
|
+
const parsed = parseField(names, `${location}.fields.${fieldName}`, spec);
|
|
117
|
+
if ('rule' in parsed)
|
|
118
|
+
return parsed;
|
|
155
119
|
fields[fieldName] = parsed;
|
|
156
120
|
}
|
|
157
121
|
const sections = Object.create(null);
|
|
158
|
-
for (const [sectionName, spec] of Object.entries(sectionsValue ?? {})){
|
|
159
|
-
const parsed = parseSection(
|
|
160
|
-
if ('rule' in parsed)
|
|
122
|
+
for (const [sectionName, spec] of Object.entries(sectionsValue ?? {})) {
|
|
123
|
+
const parsed = parseSection(names, `${location}.sections.${sectionName}`, spec);
|
|
124
|
+
if ('rule' in parsed)
|
|
125
|
+
return parsed;
|
|
161
126
|
sections[sectionName] = parsed;
|
|
162
127
|
}
|
|
163
|
-
return {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
128
|
+
return { name, memberDocument: mark, fields, sections };
|
|
129
|
+
}
|
|
130
|
+
function freezeSpec(spec) {
|
|
131
|
+
if (spec.kind === 'list')
|
|
132
|
+
freezeSpec(spec.of);
|
|
133
|
+
if (spec.kind === 'enum')
|
|
134
|
+
Object.freeze(spec.values);
|
|
135
|
+
Object.freeze(spec);
|
|
136
|
+
}
|
|
137
|
+
function lineAt(text, offset) {
|
|
138
|
+
return text.slice(0, offset).split(/\r\n|\r|\n/).length;
|
|
139
|
+
}
|
|
140
|
+
export function readSchema(text) {
|
|
141
|
+
let root;
|
|
142
|
+
try {
|
|
143
|
+
root = jsValue(parseYamlMapping(text, 0, text.length));
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
if (error instanceof YamlError)
|
|
147
|
+
return refuse('schema-yaml', `line ${lineAt(text, error.offset)}`);
|
|
148
|
+
throw error;
|
|
149
|
+
}
|
|
150
|
+
const schema = root;
|
|
151
|
+
for (const key of Object.keys(schema)) {
|
|
152
|
+
if (key !== 'types')
|
|
153
|
+
return refuse('schema-shape', key);
|
|
154
|
+
}
|
|
155
|
+
if (!isRecord(schema.types))
|
|
156
|
+
return refuse('schema-shape', 'types');
|
|
157
|
+
const names = new Set(Object.keys(schema.types));
|
|
158
|
+
if (names.has(''))
|
|
159
|
+
return refuse('schema-shape', 'types');
|
|
160
|
+
const types = Object.create(null);
|
|
161
|
+
let marked = false;
|
|
162
|
+
for (const [name, value] of Object.entries(schema.types)) {
|
|
163
|
+
const definition = readType(names, name, value);
|
|
164
|
+
if ('rule' in definition)
|
|
165
|
+
return definition;
|
|
166
|
+
if (definition.memberDocument) {
|
|
167
|
+
if (marked)
|
|
168
|
+
return refuse('schema-member-document', `types.${name}.member_document`);
|
|
169
|
+
marked = true;
|
|
170
|
+
}
|
|
171
|
+
for (const spec of Object.values(definition.fields))
|
|
172
|
+
freezeSpec(spec);
|
|
173
|
+
for (const spec of Object.values(definition.sections))
|
|
174
|
+
freezeSpec(spec);
|
|
175
|
+
Object.freeze(definition.fields);
|
|
176
|
+
Object.freeze(definition.sections);
|
|
177
|
+
types[name] = Object.freeze(definition);
|
|
178
|
+
}
|
|
179
|
+
return Object.freeze({ types: Object.freeze(types) });
|
|
169
180
|
}
|
|
170
|
-
|
|
171
|
-
//# sourceMappingURL=definition.js.map
|
package/dist/divide.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"divide.d.ts","sourceRoot":"","sources":["../src/divide.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAgB,MAAM,YAAY,CAAC;AA4WpF,wBAAgB,MAAM,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,GAAG,QAAQ,CAc3F"}
|
package/dist/divide.js
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { blockRanges, headingLines } from './blocks.js';
|
|
2
|
+
import { projectionInput, rangeText } from './project.js';
|
|
3
|
+
import { refusal } from './refuse.js';
|
|
4
|
+
const SMALLEST_BUDGET = 2;
|
|
5
|
+
function node(draft) {
|
|
6
|
+
return {
|
|
7
|
+
start: draft.start,
|
|
8
|
+
end: draft.end,
|
|
9
|
+
bodyStart: draft.bodyStart,
|
|
10
|
+
heading: draft.heading,
|
|
11
|
+
children: draft.children.map(node),
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function forest(state, range) {
|
|
15
|
+
const content = state.content;
|
|
16
|
+
const headings = headingLines(content, range.start, range.end);
|
|
17
|
+
const roots = [];
|
|
18
|
+
const open = [];
|
|
19
|
+
const first = headings[0]?.start ?? range.end;
|
|
20
|
+
if (first > range.start) {
|
|
21
|
+
roots.push({
|
|
22
|
+
level: 0,
|
|
23
|
+
start: range.start,
|
|
24
|
+
end: first,
|
|
25
|
+
bodyStart: range.start,
|
|
26
|
+
heading: '',
|
|
27
|
+
children: [],
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
for (const heading of headings) {
|
|
31
|
+
while ((open[open.length - 1]?.level ?? 0) >= heading.level) {
|
|
32
|
+
open.pop().end = heading.start;
|
|
33
|
+
}
|
|
34
|
+
const draft = {
|
|
35
|
+
level: heading.level,
|
|
36
|
+
start: heading.start,
|
|
37
|
+
end: range.end,
|
|
38
|
+
bodyStart: heading.next,
|
|
39
|
+
heading: `${textOf(state, { start: heading.start, end: heading.textEnd })}\n\n`,
|
|
40
|
+
children: [],
|
|
41
|
+
};
|
|
42
|
+
(open[open.length - 1]?.children ?? roots).push(draft);
|
|
43
|
+
open.push(draft);
|
|
44
|
+
}
|
|
45
|
+
return roots.map(node);
|
|
46
|
+
}
|
|
47
|
+
function isSpace(character) {
|
|
48
|
+
return character === ' ' || character === '\t' || character === '\n' || character === '\r';
|
|
49
|
+
}
|
|
50
|
+
const TERMINATORS = new Set(['.', '!', '?', '…', '。', '!', '?']);
|
|
51
|
+
function isTerminator(character) {
|
|
52
|
+
return TERMINATORS.has(character);
|
|
53
|
+
}
|
|
54
|
+
const CLOSERS = new Set(['"', "'", ')', ']', '»', '”']);
|
|
55
|
+
function isCloser(character) {
|
|
56
|
+
return CLOSERS.has(character);
|
|
57
|
+
}
|
|
58
|
+
function sentenceBounds(text) {
|
|
59
|
+
const bounds = [0];
|
|
60
|
+
let i = 0;
|
|
61
|
+
while (i < text.length) {
|
|
62
|
+
if (!isTerminator(text[i])) {
|
|
63
|
+
i += 1;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
let after = i + 1;
|
|
67
|
+
while (after < text.length && isCloser(text[after]))
|
|
68
|
+
after += 1;
|
|
69
|
+
if (after >= text.length || !isSpace(text[after])) {
|
|
70
|
+
i = after + 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
while (after < text.length && isSpace(text[after]))
|
|
74
|
+
after += 1;
|
|
75
|
+
if (after < text.length)
|
|
76
|
+
bounds.push(after);
|
|
77
|
+
i = after;
|
|
78
|
+
}
|
|
79
|
+
bounds.push(text.length);
|
|
80
|
+
return bounds;
|
|
81
|
+
}
|
|
82
|
+
function isTrailingSurrogate(text, index) {
|
|
83
|
+
const code = text.charCodeAt(index);
|
|
84
|
+
return code >= 0xdc00 && code <= 0xdfff;
|
|
85
|
+
}
|
|
86
|
+
function characterLength(text, index) {
|
|
87
|
+
return isTrailingSurrogate(text, index + 1) ? 2 : 1;
|
|
88
|
+
}
|
|
89
|
+
function boundOf(cutting, from, to, budget) {
|
|
90
|
+
const limit = from + budget;
|
|
91
|
+
if (limit >= to)
|
|
92
|
+
return to;
|
|
93
|
+
for (let index = limit; index > from + 1; index -= 1) {
|
|
94
|
+
if (isSpace(cutting.text[index]))
|
|
95
|
+
return index;
|
|
96
|
+
}
|
|
97
|
+
const inside = cutting.masks.find((mask) => limit > mask.start && limit < mask.end);
|
|
98
|
+
if (inside !== undefined)
|
|
99
|
+
return inside.start > from ? inside.start : Math.min(inside.end, to);
|
|
100
|
+
return isTrailingSurrogate(cutting.text, limit) ? limit - 1 : limit;
|
|
101
|
+
}
|
|
102
|
+
function utf8Size(code) {
|
|
103
|
+
if (code < 0x80)
|
|
104
|
+
return 1;
|
|
105
|
+
if (code < 0x800)
|
|
106
|
+
return 2;
|
|
107
|
+
if (code < 0x10000)
|
|
108
|
+
return 3;
|
|
109
|
+
return 4;
|
|
110
|
+
}
|
|
111
|
+
function byteBounds(content, spans) {
|
|
112
|
+
const marks = [...new Set(spans.flatMap((span) => [span.start, span.end]))].sort((left, right) => left - right);
|
|
113
|
+
const bytes = new Map();
|
|
114
|
+
let index = 0;
|
|
115
|
+
let count = 0;
|
|
116
|
+
for (const mark of marks) {
|
|
117
|
+
while (index < mark) {
|
|
118
|
+
const code = content.codePointAt(index);
|
|
119
|
+
count += utf8Size(code);
|
|
120
|
+
index += code > 0xffff ? 2 : 1;
|
|
121
|
+
}
|
|
122
|
+
bytes.set(mark, count);
|
|
123
|
+
}
|
|
124
|
+
return spans.map((span) => ({
|
|
125
|
+
...span,
|
|
126
|
+
start: bytes.get(span.start),
|
|
127
|
+
end: bytes.get(span.end),
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
function textOf(state, extent) {
|
|
131
|
+
return rangeText(state.content, extent, state.edits);
|
|
132
|
+
}
|
|
133
|
+
function sourceCutting(state, extent) {
|
|
134
|
+
let text = state.content.slice(extent.start, extent.end);
|
|
135
|
+
const masks = [];
|
|
136
|
+
for (const edit of state.edits) {
|
|
137
|
+
if (edit.start < extent.start || edit.end > extent.end)
|
|
138
|
+
continue;
|
|
139
|
+
const from = edit.start - extent.start;
|
|
140
|
+
const to = edit.end - extent.start;
|
|
141
|
+
text = `${text.slice(0, from)}${'x'.repeat(to - from)}${text.slice(to)}`;
|
|
142
|
+
masks.push({ start: from, end: to });
|
|
143
|
+
}
|
|
144
|
+
return {
|
|
145
|
+
text,
|
|
146
|
+
masks,
|
|
147
|
+
piece: (from, to) => {
|
|
148
|
+
const cut = { start: extent.start + from, end: extent.start + to };
|
|
149
|
+
return { ...cut, text: textOf(state, cut) };
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
function valueCutting(value) {
|
|
154
|
+
return {
|
|
155
|
+
text: value.text,
|
|
156
|
+
masks: [],
|
|
157
|
+
piece: (from, to) => ({ start: value.start, end: value.end, text: value.text.slice(from, to) }),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
function prefixOf(state, body) {
|
|
161
|
+
if (body.emitted === 0 || body.heading.length >= state.budget)
|
|
162
|
+
return '';
|
|
163
|
+
return body.heading;
|
|
164
|
+
}
|
|
165
|
+
function available(state, body) {
|
|
166
|
+
return state.budget - prefixOf(state, body).length;
|
|
167
|
+
}
|
|
168
|
+
function emit(state, body, piece, bare = false) {
|
|
169
|
+
if (piece.text.trim() === '')
|
|
170
|
+
return;
|
|
171
|
+
const text = (bare ? '' : prefixOf(state, body)) + piece.text;
|
|
172
|
+
state.spans.push({ start: piece.start, end: piece.end, text });
|
|
173
|
+
body.emitted += 1;
|
|
174
|
+
}
|
|
175
|
+
function merge(run) {
|
|
176
|
+
return {
|
|
177
|
+
start: Math.min(...run.map((unit) => unit.start)),
|
|
178
|
+
end: Math.max(...run.map((unit) => unit.end)),
|
|
179
|
+
text: run.map((unit) => unit.text).join(''),
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
function divideUnits(state, body, units) {
|
|
183
|
+
let run = [];
|
|
184
|
+
let length = 0;
|
|
185
|
+
const flush = () => {
|
|
186
|
+
if (run.length === 0)
|
|
187
|
+
return;
|
|
188
|
+
emit(state, body, merge(run));
|
|
189
|
+
run = [];
|
|
190
|
+
length = 0;
|
|
191
|
+
};
|
|
192
|
+
for (const unit of units) {
|
|
193
|
+
if (run.length > 0 && length + unit.text.length > available(state, body))
|
|
194
|
+
flush();
|
|
195
|
+
if (unit.text.length > available(state, body)) {
|
|
196
|
+
flush();
|
|
197
|
+
unit.descend();
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
run.push(unit);
|
|
201
|
+
length += unit.text.length;
|
|
202
|
+
}
|
|
203
|
+
flush();
|
|
204
|
+
}
|
|
205
|
+
function divideBound(state, body, cutting, range) {
|
|
206
|
+
let start = range.start;
|
|
207
|
+
while (start < range.end) {
|
|
208
|
+
const bare = available(state, body) < characterLength(cutting.text, start);
|
|
209
|
+
const room = bare ? state.budget : available(state, body);
|
|
210
|
+
const stop = boundOf(cutting, start, range.end, room);
|
|
211
|
+
const piece = cutting.piece(start, stop);
|
|
212
|
+
if (cutting.masks.length === 0 || piece.text.length <= room) {
|
|
213
|
+
emit(state, body, piece, bare);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
divideBound(state, body, valueCutting(piece), { start: 0, end: piece.text.length });
|
|
217
|
+
}
|
|
218
|
+
start = stop;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
function divideSentences(state, body, cutting) {
|
|
222
|
+
const cut = cutting.piece;
|
|
223
|
+
const bounds = sentenceBounds(cutting.text);
|
|
224
|
+
let index = 0;
|
|
225
|
+
while (index + 1 < bounds.length) {
|
|
226
|
+
const alone = { start: bounds[index], end: bounds[index + 1] };
|
|
227
|
+
if (cut(alone.start, alone.end).text.length > available(state, body)) {
|
|
228
|
+
divideBound(state, body, cutting, alone);
|
|
229
|
+
index += 1;
|
|
230
|
+
continue;
|
|
231
|
+
}
|
|
232
|
+
const carried = bounds[Math.max(index - 1, 0)];
|
|
233
|
+
const from = cut(carried, alone.end).text.length <= available(state, body) ? carried : alone.start;
|
|
234
|
+
let last = index;
|
|
235
|
+
while (last + 2 < bounds.length &&
|
|
236
|
+
cut(from, bounds[last + 2]).text.length <= available(state, body)) {
|
|
237
|
+
last += 1;
|
|
238
|
+
}
|
|
239
|
+
emit(state, body, cut(from, bounds[last + 1]));
|
|
240
|
+
index = last + 1;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function blockUnit(state, body, block) {
|
|
244
|
+
return {
|
|
245
|
+
start: block.start,
|
|
246
|
+
end: block.end,
|
|
247
|
+
text: textOf(state, block),
|
|
248
|
+
descend: () => divideSentences(state, body, sourceCutting(state, block)),
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
function valueUnit(state, body, value) {
|
|
252
|
+
return {
|
|
253
|
+
start: value.start,
|
|
254
|
+
end: value.end,
|
|
255
|
+
text: value.text,
|
|
256
|
+
descend: () => divideSentences(state, body, valueCutting(value)),
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
function nodeUnit(state, subject) {
|
|
260
|
+
return {
|
|
261
|
+
start: subject.start,
|
|
262
|
+
end: subject.end,
|
|
263
|
+
text: textOf(state, subject),
|
|
264
|
+
descend: () => divideNode(state, subject),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
function ownBlocks(subject, end, blocks) {
|
|
268
|
+
const first = blocks[0];
|
|
269
|
+
return first === undefined
|
|
270
|
+
? [{ start: subject.start, end }]
|
|
271
|
+
: [{ start: subject.start, end: first.end }, ...blocks.slice(1)];
|
|
272
|
+
}
|
|
273
|
+
function divideNode(state, subject) {
|
|
274
|
+
const end = subject.children[0]?.start ?? subject.end;
|
|
275
|
+
const blocks = blockRanges(state.content, subject.bodyStart, end);
|
|
276
|
+
const children = { heading: '', emitted: 0 };
|
|
277
|
+
if (blocks.length === 0 && subject.children.length > 0) {
|
|
278
|
+
const [first, ...rest] = subject.children;
|
|
279
|
+
const led = [{ ...first, start: subject.start }, ...rest];
|
|
280
|
+
divideUnits(state, children, led.map((child) => nodeUnit(state, child)));
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const body = { heading: subject.heading, emitted: 0 };
|
|
284
|
+
const own = ownBlocks(subject, end, blocks);
|
|
285
|
+
divideUnits(state, body, own.map((block) => blockUnit(state, body, block)));
|
|
286
|
+
divideUnits(state, children, subject.children.map((child) => nodeUnit(state, child)));
|
|
287
|
+
}
|
|
288
|
+
function divideInput(state, input) {
|
|
289
|
+
const body = { heading: '', emitted: 0 };
|
|
290
|
+
divideUnits(state, body, [
|
|
291
|
+
...input.values.map((value) => valueUnit(state, body, value)),
|
|
292
|
+
...input.ranges.flatMap((range) => forest(state, range).map((subject) => nodeUnit(state, subject))),
|
|
293
|
+
]);
|
|
294
|
+
}
|
|
295
|
+
export function divide(document, file, context) {
|
|
296
|
+
if (!Number.isInteger(context.budget) || context.budget < SMALLEST_BUDGET) {
|
|
297
|
+
return { ok: false, refusal: refusal(file, 'division-budget') };
|
|
298
|
+
}
|
|
299
|
+
const result = projectionInput(document, file, context);
|
|
300
|
+
if (!result.ok)
|
|
301
|
+
return { ok: false, refusal: result.refusal };
|
|
302
|
+
const state = {
|
|
303
|
+
content: document.content,
|
|
304
|
+
edits: result.input.edits,
|
|
305
|
+
budget: context.budget,
|
|
306
|
+
spans: [],
|
|
307
|
+
};
|
|
308
|
+
divideInput(state, result.input);
|
|
309
|
+
return { ok: true, spans: byteBounds(document.content, state.spans) };
|
|
310
|
+
}
|
package/dist/document.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { ApplyResult, Change, Document, Link, ParseResult } from './types.js';
|
|
2
|
+
import { type YamlMap } from './yaml.js';
|
|
2
3
|
export declare function parse(content: string, file?: string): ParseResult;
|
|
3
4
|
export declare function links(document: Document, file: string): readonly Link[];
|
|
4
5
|
export declare function apply(document: Document, change: Change): ApplyResult;
|
|
5
6
|
export declare function serialize(document: Document): string;
|
|
7
|
+
export declare function frontmatter(document: Document): YamlMap | null;
|
|
6
8
|
//# sourceMappingURL=document.d.ts.map
|
package/dist/document.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"document.d.ts","sourceRoot":"","sources":["../src/document.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnF,OAAO,EAYL,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAwCnB,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,WAAW,CAkD7D;AAkHD,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,SAAS,IAAI,EAAE,CAWvE;AAED,wBAAgB,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,GAAG,WAAW,CAarE;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,QAAQ,GAAG,MAAM,CAEpD;AAED,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,GAAG,IAAI,CAE9D"}
|