@agentshouse/mdmodel 0.1.0-alpha.1 → 0.1.0-alpha.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +220 -7
- package/dist/blocks.d.ts +11 -0
- package/dist/blocks.d.ts.map +1 -0
- package/dist/blocks.js +63 -0
- package/dist/blocks.js.map +1 -0
- package/dist/definition.d.ts +8 -6
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js +44 -38
- package/dist/definition.js.map +1 -1
- package/dist/divide.d.ts +3 -0
- package/dist/divide.d.ts.map +1 -0
- package/dist/divide.js +363 -0
- package/dist/divide.js.map +1 -0
- package/dist/document.d.ts +4 -1
- package/dist/document.d.ts.map +1 -1
- package/dist/document.js +95 -4
- package/dist/document.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +25 -1
- package/dist/links.d.ts.map +1 -1
- package/dist/links.js +289 -48
- package/dist/links.js.map +1 -1
- package/dist/paths.d.ts +1 -0
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +5 -0
- package/dist/paths.js.map +1 -1
- package/dist/profile.js.map +1 -1
- package/dist/project.d.ts +21 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +158 -0
- package/dist/project.js.map +1 -0
- package/dist/refuse.js.map +1 -1
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +16 -38
- package/dist/schema.js.map +1 -1
- package/dist/sections.d.ts.map +1 -1
- package/dist/sections.js +14 -47
- package/dist/sections.js.map +1 -1
- package/dist/types.d.ts +44 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/validate.d.ts +2 -2
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +17 -8
- package/dist/validate.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.d.ts.map +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/dist/yaml.d.ts +1 -0
- package/dist/yaml.d.ts.map +1 -1
- package/dist/yaml.js +6 -4
- package/dist/yaml.js.map +1 -1
- package/fixtures/README.md +87 -27
- package/fixtures/cases/any-without-type/context.json +1 -0
- package/fixtures/cases/binary-any-reference/context.json +5 -0
- package/fixtures/cases/binary-any-reference/expected.json +7 -0
- package/fixtures/cases/binary-any-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-any-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-document-collision/context.json +5 -0
- package/fixtures/cases/binary-document-collision/expected.json +6 -0
- package/fixtures/cases/binary-document-collision/library/notes/draft.md +3 -0
- package/fixtures/cases/binary-document-collision/library/types/note.md +3 -0
- package/fixtures/cases/binary-link-outside-collection/context.json +6 -0
- package/fixtures/cases/binary-link-outside-collection/expected.json +6 -0
- package/fixtures/cases/binary-link-outside-collection/library/notes/draft.md +5 -0
- package/fixtures/cases/binary-link-outside-collection/library/types/note.md +3 -0
- package/fixtures/cases/binary-prototype-reference/context.json +1 -0
- package/fixtures/cases/binary-prototype-reference/expected.json +7 -0
- package/fixtures/cases/binary-prototype-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-prototype-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-typed-reference/context.json +5 -0
- package/fixtures/cases/binary-typed-reference/expected.json +7 -0
- package/fixtures/cases/binary-typed-reference/library/notes/draft.md +6 -0
- package/fixtures/cases/binary-typed-reference/library/types/note.md +5 -0
- package/fixtures/cases/binary-typed-reference/library/types/person.md +3 -0
- package/fixtures/cases/bracketed-link-definition/context.json +1 -0
- package/fixtures/cases/bracketed-link-definition/expected.json +1 -0
- package/fixtures/cases/bracketed-link-definition/library/item.md +10 -0
- package/fixtures/cases/bracketed-link-definition/library/types/task.md +7 -0
- package/fixtures/cases/declared-binary-links/context.json +6 -0
- package/fixtures/cases/declared-binary-links/expected.json +1 -0
- package/fixtures/cases/declared-binary-links/library/notes/draft.md +7 -0
- package/fixtures/cases/declared-binary-links/library/types/note.md +3 -0
- package/fixtures/cases/duplicate-link-definition/context.json +1 -0
- package/fixtures/cases/duplicate-link-definition/expected.json +1 -0
- package/fixtures/cases/duplicate-link-definition/library/item.md +11 -0
- package/fixtures/cases/duplicate-link-definition/library/types/task.md +7 -0
- package/fixtures/cases/fenced-link-definition/context.json +1 -0
- package/fixtures/cases/fenced-link-definition/expected.json +1 -0
- package/fixtures/cases/fenced-link-definition/library/item.md +12 -0
- package/fixtures/cases/fenced-link-definition/library/types/task.md +7 -0
- package/fixtures/cases/field-enum/context.json +1 -0
- package/fixtures/cases/interrupted-link-definition/context.json +1 -0
- package/fixtures/cases/interrupted-link-definition/expected.json +1 -0
- package/fixtures/cases/interrupted-link-definition/library/notes/draft.md +8 -0
- package/fixtures/cases/interrupted-link-definition/library/types/note.md +3 -0
- package/fixtures/cases/long-fence-link-definition/context.json +1 -0
- package/fixtures/cases/long-fence-link-definition/expected.json +1 -0
- package/fixtures/cases/long-fence-link-definition/library/notes/draft.md +9 -0
- package/fixtures/cases/long-fence-link-definition/library/types/note.md +3 -0
- package/fixtures/cases/malformed-definition/context.json +1 -0
- package/fixtures/cases/missing-binary-image/context.json +6 -0
- package/fixtures/cases/missing-binary-image/expected.json +6 -0
- package/fixtures/cases/missing-binary-image/library/notes/draft.md +5 -0
- package/fixtures/cases/missing-binary-image/library/types/note.md +3 -0
- package/fixtures/cases/missing-binary-link/context.json +6 -0
- package/fixtures/cases/missing-binary-link/expected.json +6 -0
- package/fixtures/cases/missing-binary-link/library/notes/draft.md +5 -0
- package/fixtures/cases/missing-binary-link/library/types/note.md +3 -0
- package/fixtures/cases/missing-required-field/context.json +1 -0
- package/fixtures/cases/missing-section-item-kind/context.json +1 -0
- package/fixtures/cases/missing-section-item-kind/expected.json +7 -0
- package/fixtures/cases/missing-section-item-kind/library/types/task.md +7 -0
- package/fixtures/cases/paragraph-link-definition/context.json +5 -0
- package/fixtures/cases/paragraph-link-definition/expected.json +1 -0
- package/fixtures/cases/paragraph-link-definition/library/notes/draft.md +10 -0
- package/fixtures/cases/paragraph-link-definition/library/types/note.md +3 -0
- package/fixtures/cases/prd-definition/context.json +1 -0
- package/fixtures/cases/prd-definition/library/types/task.md +2 -1
- package/fixtures/cases/prototype-field/context.json +1 -0
- package/fixtures/cases/prototype-field/expected.json +7 -0
- package/fixtures/cases/prototype-field/library/item.md +9 -0
- package/fixtures/cases/prototype-field/library/types/task.md +7 -0
- package/fixtures/cases/quoted-link-definition/context.json +1 -0
- package/fixtures/cases/quoted-link-definition/expected.json +6 -0
- package/fixtures/cases/quoted-link-definition/library/notes/draft.md +7 -0
- package/fixtures/cases/quoted-link-definition/library/types/note.md +3 -0
- package/fixtures/cases/referenced-missing-file/context.json +1 -0
- package/fixtures/cases/structured-section/context.json +1 -0
- package/fixtures/cases/structured-section/library/types/task.md +1 -1
- package/fixtures/cases/truncated-link-definition/context.json +1 -0
- package/fixtures/cases/truncated-link-definition/expected.json +6 -0
- package/fixtures/cases/truncated-link-definition/library/notes/draft.md +7 -0
- package/fixtures/cases/truncated-link-definition/library/notes/other.md +5 -0
- package/fixtures/cases/truncated-link-definition/library/types/note.md +3 -0
- package/fixtures/cases/unclosed-frontmatter/context.json +1 -0
- package/fixtures/cases/undeclared-field/context.json +1 -0
- package/fixtures/cases/undeclared-field/expected.json +7 -0
- package/fixtures/cases/undeclared-field/library/item.md +9 -0
- package/fixtures/cases/undeclared-field/library/types/task.md +7 -0
- package/fixtures/cases/unresolved-link/context.json +1 -0
- package/fixtures/cases/valid-typed-document/context.json +1 -0
- package/fixtures/cases/valid-typed-document/library/tasks/one.md +1 -0
- package/fixtures/cases/valid-typed-document/library/types/task.md +2 -1
- package/fixtures/cases/wide-item-fence-link/context.json +1 -0
- package/fixtures/cases/wide-item-fence-link/expected.json +1 -0
- package/fixtures/cases/wide-item-fence-link/library/notes/draft.md +7 -0
- package/fixtures/cases/wide-item-fence-link/library/types/note.md +3 -0
- package/fixtures/division.json +415 -0
- package/fixtures/preamble.json +107 -0
- package/fixtures/projection.json +186 -0
- package/package.json +4 -5
package/dist/project.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { readDefinition } from './definition.js';
|
|
2
|
+
import { frontmatter, parse } from './document.js';
|
|
3
|
+
import { linkInventory } from './links.js';
|
|
4
|
+
import { classifyHref } from './paths.js';
|
|
5
|
+
import { refusal } from './refuse.js';
|
|
6
|
+
import { headingSpans } from './sections.js';
|
|
7
|
+
import { bodyStartOf, mapEntry } from './yaml.js';
|
|
8
|
+
function internalEdits(content, bodyStart, file, documentTargets) {
|
|
9
|
+
const inventory = linkInventory(content.slice(bodyStart));
|
|
10
|
+
const internal = new Set();
|
|
11
|
+
const edits = [];
|
|
12
|
+
for (const use of inventory.uses){
|
|
13
|
+
const resolved = classifyHref(file, use.destination.href);
|
|
14
|
+
if (resolved.kind !== 'path' || !documentTargets.has(resolved.path)) continue;
|
|
15
|
+
internal.add(use.destination.start);
|
|
16
|
+
edits.push({
|
|
17
|
+
start: bodyStart + use.start,
|
|
18
|
+
end: bodyStart + use.end,
|
|
19
|
+
text: content.slice(bodyStart + use.labelStart, bodyStart + use.labelEnd)
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
for (const block of inventory.blocks){
|
|
23
|
+
if (!internal.has(block.destination.start)) continue;
|
|
24
|
+
edits.push({
|
|
25
|
+
start: bodyStart + block.start,
|
|
26
|
+
end: bodyStart + block.end,
|
|
27
|
+
text: ''
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
return edits.sort((left, right)=>left.start - right.start);
|
|
31
|
+
}
|
|
32
|
+
export function rangeText(content, range, edits) {
|
|
33
|
+
let text = '';
|
|
34
|
+
let cursor = range.start;
|
|
35
|
+
for (const edit of edits){
|
|
36
|
+
if (edit.start < cursor || edit.end > range.end) continue;
|
|
37
|
+
text += content.slice(cursor, edit.start) + edit.text;
|
|
38
|
+
cursor = edit.end;
|
|
39
|
+
}
|
|
40
|
+
return text + content.slice(cursor, range.end);
|
|
41
|
+
}
|
|
42
|
+
function structural(spec) {
|
|
43
|
+
return spec.kind === 'list' && spec.of.kind !== 'text';
|
|
44
|
+
}
|
|
45
|
+
function freeTextValues(definition, document) {
|
|
46
|
+
const root = frontmatter(document);
|
|
47
|
+
if (root === null) return [];
|
|
48
|
+
const values = [];
|
|
49
|
+
for (const [name, spec] of Object.entries(definition.fields)){
|
|
50
|
+
const entry = mapEntry(root, name);
|
|
51
|
+
if (entry === undefined) continue;
|
|
52
|
+
const node = entry.value;
|
|
53
|
+
if (spec.kind === 'text') {
|
|
54
|
+
if (node.kind === 'scalar' && typeof node.value === 'string') {
|
|
55
|
+
values.push({
|
|
56
|
+
start: node.start,
|
|
57
|
+
end: node.end,
|
|
58
|
+
text: `${node.value}\n\n`
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (spec.kind !== 'list' || spec.of.kind !== 'text' || node.kind !== 'seq') continue;
|
|
64
|
+
for (const item of node.items){
|
|
65
|
+
if (item.kind === 'scalar' && typeof item.value === 'string') {
|
|
66
|
+
values.push({
|
|
67
|
+
start: item.start,
|
|
68
|
+
end: item.end,
|
|
69
|
+
text: `${item.value}\n\n`
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return values;
|
|
75
|
+
}
|
|
76
|
+
export function projectionInput(document, file, context) {
|
|
77
|
+
const content = document.content;
|
|
78
|
+
const bodyStart = bodyStartOf(content);
|
|
79
|
+
const edits = internalEdits(content, bodyStart, file, new Set(context.documentTargets));
|
|
80
|
+
const declared = document.type;
|
|
81
|
+
if (declared === undefined || declared === 'any') {
|
|
82
|
+
return {
|
|
83
|
+
ok: true,
|
|
84
|
+
input: {
|
|
85
|
+
values: [],
|
|
86
|
+
ranges: [
|
|
87
|
+
{
|
|
88
|
+
start: bodyStart,
|
|
89
|
+
end: content.length
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
edits
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
const source = context.definition;
|
|
97
|
+
if (source === undefined) {
|
|
98
|
+
return {
|
|
99
|
+
ok: false,
|
|
100
|
+
refusal: refusal(file, 'unknown-type', {
|
|
101
|
+
location: 'type'
|
|
102
|
+
})
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const definitionFile = `types/${declared}.md`;
|
|
106
|
+
const parsed = parse(source, definitionFile);
|
|
107
|
+
if (!parsed.ok) return {
|
|
108
|
+
ok: false,
|
|
109
|
+
refusal: parsed.refusal
|
|
110
|
+
};
|
|
111
|
+
const definition = readDefinition(definitionFile, parsed.document);
|
|
112
|
+
if ('rule' in definition) return {
|
|
113
|
+
ok: false,
|
|
114
|
+
refusal: definition
|
|
115
|
+
};
|
|
116
|
+
const structure = new Set(Object.entries(definition.sections).flatMap(([name, spec])=>structural(spec) ? [
|
|
117
|
+
name
|
|
118
|
+
] : []));
|
|
119
|
+
const headings = headingSpans(content, bodyStart);
|
|
120
|
+
const ranges = [
|
|
121
|
+
{
|
|
122
|
+
start: bodyStart,
|
|
123
|
+
end: headings[0]?.headingStart ?? content.length
|
|
124
|
+
}
|
|
125
|
+
];
|
|
126
|
+
for (const heading of headings){
|
|
127
|
+
if (structure.has(heading.name)) continue;
|
|
128
|
+
ranges.push({
|
|
129
|
+
start: heading.headingStart,
|
|
130
|
+
end: heading.bodyEnd
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
ok: true,
|
|
135
|
+
input: {
|
|
136
|
+
values: freeTextValues(definition, document),
|
|
137
|
+
ranges,
|
|
138
|
+
edits
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export function project(document, file, context = {
|
|
143
|
+
documentTargets: []
|
|
144
|
+
}) {
|
|
145
|
+
const result = projectionInput(document, file, context);
|
|
146
|
+
if (!result.ok) return {
|
|
147
|
+
ok: false,
|
|
148
|
+
refusal: result.refusal
|
|
149
|
+
};
|
|
150
|
+
const { values, ranges, edits } = result.input;
|
|
151
|
+
const prose = ranges.map((range)=>rangeText(document.content, range, edits)).join('');
|
|
152
|
+
return {
|
|
153
|
+
ok: true,
|
|
154
|
+
text: values.map((value)=>value.text).join('') + prose
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/project.ts"],"sourcesContent":["import { readDefinition, type Definition, type SectionSpec } from './definition.js';\nimport { frontmatter, parse } from './document.js';\nimport { linkInventory } from './links.js';\nimport { classifyHref } from './paths.js';\nimport { refusal } from './refuse.js';\nimport { headingSpans } from './sections.js';\nimport type { Document, Extent, Projection, ProjectionContext, Refusal } from './types.js';\nimport { bodyStartOf, mapEntry } from './yaml.js';\n\nexport type Piece = Extent & { readonly text: string };\n\nexport type Edit = Piece;\n\nexport type Input = {\n readonly values: readonly Piece[];\n readonly ranges: readonly Extent[];\n readonly edits: readonly Edit[];\n};\n\nexport type InputResult =\n | { readonly ok: true; readonly input: Input }\n | { readonly ok: false; readonly refusal: Refusal };\n\nfunction internalEdits(\n content: string,\n bodyStart: number,\n file: string,\n documentTargets: ReadonlySet<string>,\n): Edit[] {\n const inventory = linkInventory(content.slice(bodyStart));\n const internal = new Set<number>();\n const edits: Edit[] = [];\n for (const use of inventory.uses) {\n const resolved = classifyHref(file, use.destination.href);\n if (resolved.kind !== 'path' || !documentTargets.has(resolved.path)) continue;\n internal.add(use.destination.start);\n edits.push({\n start: bodyStart + use.start,\n end: bodyStart + use.end,\n text: content.slice(bodyStart + use.labelStart, bodyStart + use.labelEnd),\n });\n }\n for (const block of inventory.blocks) {\n if (!internal.has(block.destination.start)) continue;\n edits.push({ start: bodyStart + block.start, end: bodyStart + block.end, text: '' });\n }\n return edits.sort((left, right) => left.start - right.start);\n}\n\nexport function rangeText(content: string, range: Extent, edits: readonly Edit[]): string {\n let text = '';\n let cursor = range.start;\n for (const edit of edits) {\n if (edit.start < cursor || edit.end > range.end) continue;\n text += content.slice(cursor, edit.start) + edit.text;\n cursor = edit.end;\n }\n return text + content.slice(cursor, range.end);\n}\n\nfunction structural(spec: SectionSpec): boolean {\n return spec.kind === 'list' && spec.of.kind !== 'text';\n}\n\nfunction freeTextValues(definition: Definition, document: Document): Piece[] {\n const root = frontmatter(document);\n if (root === null) return [];\n const values: Piece[] = [];\n for (const [name, spec] of Object.entries(definition.fields)) {\n const entry = mapEntry(root, name);\n if (entry === undefined) continue;\n const node = entry.value;\n if (spec.kind === 'text') {\n if (node.kind === 'scalar' && typeof node.value === 'string') {\n values.push({ start: node.start, end: node.end, text: `${node.value}\\n\\n` });\n }\n continue;\n }\n if (spec.kind !== 'list' || spec.of.kind !== 'text' || node.kind !== 'seq') continue;\n for (const item of node.items) {\n if (item.kind === 'scalar' && typeof item.value === 'string') {\n values.push({ start: item.start, end: item.end, text: `${item.value}\\n\\n` });\n }\n }\n }\n return values;\n}\n\nexport function projectionInput(\n document: Document,\n file: string,\n context: ProjectionContext,\n): InputResult {\n const content = document.content;\n const bodyStart = bodyStartOf(content);\n const edits = internalEdits(content, bodyStart, file, new Set(context.documentTargets));\n const declared = document.type;\n if (declared === undefined || declared === 'any') {\n return {\n ok: true,\n input: { values: [], ranges: [{ start: bodyStart, end: content.length }], edits },\n };\n }\n const source = context.definition;\n if (source === undefined) {\n return { ok: false, refusal: refusal(file, 'unknown-type', { location: 'type' }) };\n }\n const definitionFile = `types/${declared}.md`;\n const parsed = parse(source, definitionFile);\n if (!parsed.ok) return { ok: false, refusal: parsed.refusal };\n const definition = readDefinition(definitionFile, parsed.document);\n if ('rule' in definition) return { ok: false, refusal: definition };\n const structure = new Set(\n Object.entries(definition.sections).flatMap(([name, spec]) => (structural(spec) ? [name] : [])),\n );\n const headings = headingSpans(content, bodyStart);\n const ranges: Extent[] = [{ start: bodyStart, end: headings[0]?.headingStart ?? content.length }];\n for (const heading of headings) {\n if (structure.has(heading.name)) continue;\n ranges.push({ start: heading.headingStart, end: heading.bodyEnd });\n }\n return { ok: true, input: { values: freeTextValues(definition, document), ranges, edits } };\n}\n\nexport function project(\n document: Document,\n file: string,\n context: ProjectionContext = { documentTargets: [] },\n): Projection {\n const result = projectionInput(document, file, context);\n if (!result.ok) return { ok: false, refusal: result.refusal };\n const { values, ranges, edits } = result.input;\n const prose = ranges.map((range) => rangeText(document.content, range, edits)).join('');\n return { ok: true, text: values.map((value) => value.text).join('') + prose };\n}\n"],"names":["readDefinition","frontmatter","parse","linkInventory","classifyHref","refusal","headingSpans","bodyStartOf","mapEntry","internalEdits","content","bodyStart","file","documentTargets","inventory","slice","internal","Set","edits","use","uses","resolved","destination","href","kind","has","path","add","start","push","end","text","labelStart","labelEnd","block","blocks","sort","left","right","rangeText","range","cursor","edit","structural","spec","of","freeTextValues","definition","document","root","values","name","Object","entries","fields","entry","undefined","node","value","item","items","projectionInput","context","declared","type","ok","input","ranges","length","source","location","definitionFile","parsed","structure","sections","flatMap","headings","headingStart","heading","bodyEnd","project","result","prose","map","join"],"mappings":"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"}
|
package/dist/refuse.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/refuse.ts"],"sourcesContent":["import type { Refusal } from './types.js';\nimport { VERSION } from './version.js';\n\nexport function refusal(\n file: string,\n rule: string,\n extra?: { location?: string; referrers?: readonly string[] },\n): Refusal {\n return {\n file,\n rule,\n version: VERSION,\n ...(extra?.location === undefined ? {} : { location: extra.location }),\n ...(extra?.referrers === undefined ? {} : { referrers: extra.referrers }),\n };\n}\n"],"names":["VERSION","refusal","file","rule","extra","version","location","undefined","referrers"],"mappings":"AACA,SAASA,OAAO,QAAQ,eAAe;AAEvC,OAAO,SAASC,QACdC,IAAY,EACZC,IAAY,EACZC,KAA4D;IAE5D,OAAO;QACLF;QACAC;QACAE,SAASL;QACT,GAAII,OAAOE,aAAaC,YAAY,CAAC,IAAI;YAAED,UAAUF,MAAME,QAAQ;QAAC,CAAC;QACrE,GAAIF,OAAOI,cAAcD,YAAY,CAAC,IAAI;YAAEC,WAAWJ,MAAMI,SAAS;QAAC,CAAC;IAC1E;AACF"}
|
package/dist/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAC;AAmB7D,wBAAgB,cAAc,CAC5B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,EAC3C,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GACxC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,gBAAgB,GAAG,YAAY,GAAG,YAAY,CAAA;CAAE,GAAG,SAAS,CAUrF"}
|
package/dist/schema.js
CHANGED
|
@@ -1,16 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import formatsPlugin from 'ajv-formats';
|
|
3
|
-
const addFormats = formatsPlugin;
|
|
4
|
-
const ajv = new Ajv({
|
|
5
|
-
allErrors: true,
|
|
6
|
-
strict: false,
|
|
7
|
-
validateFormats: true
|
|
8
|
-
});
|
|
9
|
-
addFormats(ajv, [
|
|
10
|
-
'date'
|
|
11
|
-
]);
|
|
1
|
+
import { Validator } from '@cfworker/json-schema';
|
|
12
2
|
function scalarSchema(spec) {
|
|
13
|
-
if (spec.kind === 'string' || spec.kind === 'reference') return {
|
|
3
|
+
if (spec.kind === 'text' || spec.kind === 'string' || spec.kind === 'reference') return {
|
|
14
4
|
type: 'string'
|
|
15
5
|
};
|
|
16
6
|
if (spec.kind === 'number') return {
|
|
@@ -35,36 +25,24 @@ function fieldSchema(spec) {
|
|
|
35
25
|
return scalarSchema(spec);
|
|
36
26
|
}
|
|
37
27
|
function ruleFor(error) {
|
|
38
|
-
|
|
39
|
-
if (error.keyword === 'enum') return 'field-enum';
|
|
40
|
-
return 'field-kind';
|
|
41
|
-
}
|
|
42
|
-
function locationFor(error) {
|
|
43
|
-
if (error.keyword === 'required' && typeof error.params.missingProperty === 'string') {
|
|
44
|
-
return error.params.missingProperty;
|
|
45
|
-
}
|
|
46
|
-
const path = error.instancePath.replace(/^\//, '').split('/');
|
|
47
|
-
return path[0] ?? '';
|
|
28
|
+
return error.keyword === 'enum' ? 'field-enum' : 'field-kind';
|
|
48
29
|
}
|
|
49
30
|
export function validateFields(fields, values) {
|
|
50
|
-
const properties = {};
|
|
51
|
-
const required = [];
|
|
52
31
|
for (const [name, spec] of Object.entries(fields)){
|
|
53
|
-
|
|
54
|
-
|
|
32
|
+
if (spec.required && values[name] === undefined) return {
|
|
33
|
+
field: name,
|
|
34
|
+
rule: 'required-field'
|
|
35
|
+
};
|
|
55
36
|
}
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
65
|
-
field: locationFor(error),
|
|
66
|
-
rule: ruleFor(error)
|
|
67
|
-
};
|
|
37
|
+
for (const [name, spec] of Object.entries(fields)){
|
|
38
|
+
if (values[name] === undefined) continue;
|
|
39
|
+
const result = new Validator(fieldSchema(spec), '2020-12', false).validate(values[name]);
|
|
40
|
+
if (!result.valid) return {
|
|
41
|
+
field: name,
|
|
42
|
+
rule: ruleFor(result.errors[0])
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
68
46
|
}
|
|
69
47
|
|
|
70
48
|
//# sourceMappingURL=schema.js.map
|
package/dist/schema.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/schema.ts"],"sourcesContent":["import { Validator, type OutputUnit } from '@cfworker/json-schema';\nimport type { FieldSpec, ScalarSpec } from './definition.js';\n\nfunction scalarSchema(spec: ScalarSpec): Record<string, unknown> {\n if (spec.kind === 'text' || spec.kind === 'string' || spec.kind === 'reference')\n return { type: 'string' };\n if (spec.kind === 'number') return { type: 'number' };\n if (spec.kind === 'date') return { type: 'string', format: 'date' };\n return { type: 'string', enum: [...spec.values] };\n}\n\nfunction fieldSchema(spec: FieldSpec): Record<string, unknown> {\n if (spec.kind === 'list') return { type: 'array', items: scalarSchema(spec.of) };\n return scalarSchema(spec);\n}\n\nfunction ruleFor(error: OutputUnit): 'field-enum' | 'field-kind' {\n return error.keyword === 'enum' ? 'field-enum' : 'field-kind';\n}\n\nexport function validateFields(\n fields: Readonly<Record<string, FieldSpec>>,\n values: Readonly<Record<string, unknown>>,\n): { field: string; rule: 'required-field' | 'field-enum' | 'field-kind' } | undefined {\n for (const [name, spec] of Object.entries(fields)) {\n if (spec.required && values[name] === undefined) return { field: name, rule: 'required-field' };\n }\n for (const [name, spec] of Object.entries(fields)) {\n if (values[name] === undefined) continue;\n const result = new Validator(fieldSchema(spec), '2020-12', false).validate(values[name]);\n if (!result.valid) return { field: name, rule: ruleFor(result.errors[0]!) };\n }\n return undefined;\n}\n"],"names":["Validator","scalarSchema","spec","kind","type","format","enum","values","fieldSchema","items","of","ruleFor","error","keyword","validateFields","fields","name","Object","entries","required","undefined","field","rule","result","validate","valid","errors"],"mappings":"AAAA,SAASA,SAAS,QAAyB,wBAAwB;AAGnE,SAASC,aAAaC,IAAgB;IACpC,IAAIA,KAAKC,IAAI,KAAK,UAAUD,KAAKC,IAAI,KAAK,YAAYD,KAAKC,IAAI,KAAK,aAClE,OAAO;QAAEC,MAAM;IAAS;IAC1B,IAAIF,KAAKC,IAAI,KAAK,UAAU,OAAO;QAAEC,MAAM;IAAS;IACpD,IAAIF,KAAKC,IAAI,KAAK,QAAQ,OAAO;QAAEC,MAAM;QAAUC,QAAQ;IAAO;IAClE,OAAO;QAAED,MAAM;QAAUE,MAAM;eAAIJ,KAAKK,MAAM;SAAC;IAAC;AAClD;AAEA,SAASC,YAAYN,IAAe;IAClC,IAAIA,KAAKC,IAAI,KAAK,QAAQ,OAAO;QAAEC,MAAM;QAASK,OAAOR,aAAaC,KAAKQ,EAAE;IAAE;IAC/E,OAAOT,aAAaC;AACtB;AAEA,SAASS,QAAQC,KAAiB;IAChC,OAAOA,MAAMC,OAAO,KAAK,SAAS,eAAe;AACnD;AAEA,OAAO,SAASC,eACdC,MAA2C,EAC3CR,MAAyC;IAEzC,KAAK,MAAM,CAACS,MAAMd,KAAK,IAAIe,OAAOC,OAAO,CAACH,QAAS;QACjD,IAAIb,KAAKiB,QAAQ,IAAIZ,MAAM,CAACS,KAAK,KAAKI,WAAW,OAAO;YAAEC,OAAOL;YAAMM,MAAM;QAAiB;IAChG;IACA,KAAK,MAAM,CAACN,MAAMd,KAAK,IAAIe,OAAOC,OAAO,CAACH,QAAS;QACjD,IAAIR,MAAM,CAACS,KAAK,KAAKI,WAAW;QAChC,MAAMG,SAAS,IAAIvB,UAAUQ,YAAYN,OAAO,WAAW,OAAOsB,QAAQ,CAACjB,MAAM,CAACS,KAAK;QACvF,IAAI,CAACO,OAAOE,KAAK,EAAE,OAAO;YAAEJ,OAAOL;YAAMM,MAAMX,QAAQY,OAAOG,MAAM,CAAC,EAAE;QAAG;IAC5E;IACA,OAAON;AACT"}
|
package/dist/sections.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../src/sections.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B,CAAC;AAIF,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,EAAE,CAc9E;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,WAAW,EAAE,EAC7B,OAAO,EAAE,MAAM,GACd,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBtD"}
|
package/dist/sections.js
CHANGED
|
@@ -1,57 +1,24 @@
|
|
|
1
|
-
|
|
1
|
+
import { headingLines } from './blocks.js';
|
|
2
2
|
const ITEM = /^([ \t]*)([-*+]|\d+[.)])[ \t]+/;
|
|
3
|
-
function lineRange(content, from) {
|
|
4
|
-
const nl = content.indexOf('\n', from);
|
|
5
|
-
const end = nl === -1 ? content.length : nl;
|
|
6
|
-
let line = content.slice(from, end);
|
|
7
|
-
if (line.endsWith('\r')) line = line.slice(0, -1);
|
|
8
|
-
return {
|
|
9
|
-
line,
|
|
10
|
-
start: from,
|
|
11
|
-
next: nl === -1 ? content.length : nl + 1
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
|
-
function fenceMarker(line) {
|
|
15
|
-
let i = 0;
|
|
16
|
-
while(i < 3 && (line[i] === ' ' || line[i] === '\t'))i += 1;
|
|
17
|
-
if (line.startsWith('```', i)) return '```';
|
|
18
|
-
if (line.startsWith('~~~', i)) return '~~~';
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
3
|
export function headingSpans(content, bodyStart) {
|
|
22
4
|
const found = [];
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const name = match[1].trim();
|
|
36
|
-
if (found.length > 0) found[found.length - 1] = {
|
|
37
|
-
...found[found.length - 1],
|
|
38
|
-
bodyEnd: start
|
|
39
|
-
};
|
|
40
|
-
found.push({
|
|
41
|
-
name,
|
|
42
|
-
headingStart: start,
|
|
43
|
-
bodyStart: next,
|
|
44
|
-
bodyEnd: content.length
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (next === i) break;
|
|
49
|
-
i = next;
|
|
5
|
+
for (const heading of headingLines(content, bodyStart, content.length)){
|
|
6
|
+
if (heading.level !== 2) continue;
|
|
7
|
+
if (found.length > 0) found[found.length - 1] = {
|
|
8
|
+
...found[found.length - 1],
|
|
9
|
+
bodyEnd: heading.start
|
|
10
|
+
};
|
|
11
|
+
found.push({
|
|
12
|
+
name: heading.name,
|
|
13
|
+
headingStart: heading.start,
|
|
14
|
+
bodyStart: heading.next,
|
|
15
|
+
bodyEnd: content.length
|
|
16
|
+
});
|
|
50
17
|
}
|
|
51
18
|
return found;
|
|
52
19
|
}
|
|
53
20
|
export function sectionsRecord(spans, content) {
|
|
54
|
-
const record =
|
|
21
|
+
const record = Object.create(null);
|
|
55
22
|
for (const span of spans){
|
|
56
23
|
if (record[span.name] === undefined) record[span.name] = content.slice(span.bodyStart, span.bodyEnd);
|
|
57
24
|
}
|
package/dist/sections.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/sections.ts"],"sourcesContent":["import { headingLines } from './blocks.js';\n\nexport type SectionSpan = {\n readonly name: string;\n readonly headingStart: number;\n readonly bodyStart: number;\n readonly bodyEnd: number;\n};\n\nconst ITEM = /^([ \\t]*)([-*+]|\\d+[.)])[ \\t]+/;\n\nexport function headingSpans(content: string, bodyStart: number): SectionSpan[] {\n const found: SectionSpan[] = [];\n for (const heading of headingLines(content, bodyStart, content.length)) {\n if (heading.level !== 2) continue;\n if (found.length > 0)\n found[found.length - 1] = { ...found[found.length - 1]!, bodyEnd: heading.start };\n found.push({\n name: heading.name,\n headingStart: heading.start,\n bodyStart: heading.next,\n bodyEnd: content.length,\n });\n }\n return found;\n}\n\nexport function sectionsRecord(\n spans: readonly SectionSpan[],\n content: string,\n): Record<string, string> {\n const record: Record<string, string> = Object.create(null);\n for (const span of spans) {\n if (record[span.name] === undefined)\n record[span.name] = content.slice(span.bodyStart, span.bodyEnd);\n }\n return record;\n}\n\nexport function parseListSection(body: string): boolean {\n const lines = body.split(/\\r?\\n/);\n while (lines.length > 0 && lines[0]!.trim() === '') lines.shift();\n while (lines.length > 0 && lines[lines.length - 1]!.trim() === '') lines.pop();\n if (lines.length === 0) return true;\n const first = ITEM.exec(lines[0]!);\n if (first === null || first[1] === undefined) return false;\n const indent = first[1].length;\n for (const line of lines) {\n if (line.trim() === '') continue;\n const match = ITEM.exec(line);\n if (match !== null && match[1]?.length === indent) continue;\n const leading = /^\\s*/.exec(line)?.[0].length ?? 0;\n if (leading > indent) continue;\n return false;\n }\n return true;\n}\n"],"names":["headingLines","ITEM","headingSpans","content","bodyStart","found","heading","length","level","bodyEnd","start","push","name","headingStart","next","sectionsRecord","spans","record","Object","create","span","undefined","slice","parseListSection","body","lines","split","trim","shift","pop","first","exec","indent","line","match","leading"],"mappings":"AAAA,SAASA,YAAY,QAAQ,cAAc;AAS3C,MAAMC,OAAO;AAEb,OAAO,SAASC,aAAaC,OAAe,EAAEC,SAAiB;IAC7D,MAAMC,QAAuB,EAAE;IAC/B,KAAK,MAAMC,WAAWN,aAAaG,SAASC,WAAWD,QAAQI,MAAM,EAAG;QACtE,IAAID,QAAQE,KAAK,KAAK,GAAG;QACzB,IAAIH,MAAME,MAAM,GAAG,GACjBF,KAAK,CAACA,MAAME,MAAM,GAAG,EAAE,GAAG;YAAE,GAAGF,KAAK,CAACA,MAAME,MAAM,GAAG,EAAE;YAAGE,SAASH,QAAQI,KAAK;QAAC;QAClFL,MAAMM,IAAI,CAAC;YACTC,MAAMN,QAAQM,IAAI;YAClBC,cAAcP,QAAQI,KAAK;YAC3BN,WAAWE,QAAQQ,IAAI;YACvBL,SAASN,QAAQI,MAAM;QACzB;IACF;IACA,OAAOF;AACT;AAEA,OAAO,SAASU,eACdC,KAA6B,EAC7Bb,OAAe;IAEf,MAAMc,SAAiCC,OAAOC,MAAM,CAAC;IACrD,KAAK,MAAMC,QAAQJ,MAAO;QACxB,IAAIC,MAAM,CAACG,KAAKR,IAAI,CAAC,KAAKS,WACxBJ,MAAM,CAACG,KAAKR,IAAI,CAAC,GAAGT,QAAQmB,KAAK,CAACF,KAAKhB,SAAS,EAAEgB,KAAKX,OAAO;IAClE;IACA,OAAOQ;AACT;AAEA,OAAO,SAASM,iBAAiBC,IAAY;IAC3C,MAAMC,QAAQD,KAAKE,KAAK,CAAC;IACzB,MAAOD,MAAMlB,MAAM,GAAG,KAAKkB,KAAK,CAAC,EAAE,CAAEE,IAAI,OAAO,GAAIF,MAAMG,KAAK;IAC/D,MAAOH,MAAMlB,MAAM,GAAG,KAAKkB,KAAK,CAACA,MAAMlB,MAAM,GAAG,EAAE,CAAEoB,IAAI,OAAO,GAAIF,MAAMI,GAAG;IAC5E,IAAIJ,MAAMlB,MAAM,KAAK,GAAG,OAAO;IAC/B,MAAMuB,QAAQ7B,KAAK8B,IAAI,CAACN,KAAK,CAAC,EAAE;IAChC,IAAIK,UAAU,QAAQA,KAAK,CAAC,EAAE,KAAKT,WAAW,OAAO;IACrD,MAAMW,SAASF,KAAK,CAAC,EAAE,CAACvB,MAAM;IAC9B,KAAK,MAAM0B,QAAQR,MAAO;QACxB,IAAIQ,KAAKN,IAAI,OAAO,IAAI;QACxB,MAAMO,QAAQjC,KAAK8B,IAAI,CAACE;QACxB,IAAIC,UAAU,QAAQA,KAAK,CAAC,EAAE,EAAE3B,WAAWyB,QAAQ;QACnD,MAAMG,UAAU,OAAOJ,IAAI,CAACE,OAAO,CAAC,EAAE,CAAC1B,UAAU;QACjD,IAAI4B,UAAUH,QAAQ;QACtB,OAAO;IACT;IACA,OAAO;AACT"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
export type Library = Readonly<Record<string, string>>;
|
|
2
|
+
export type ValidationContext = {
|
|
3
|
+
readonly binaryTargets: readonly string[];
|
|
4
|
+
};
|
|
5
|
+
export type ProjectionContext = {
|
|
6
|
+
readonly documentTargets: readonly string[];
|
|
7
|
+
readonly definition?: string;
|
|
8
|
+
};
|
|
9
|
+
export type DivisionContext = ProjectionContext & {
|
|
10
|
+
readonly budget: number;
|
|
11
|
+
};
|
|
12
|
+
export type Extent = {
|
|
13
|
+
readonly start: number;
|
|
14
|
+
readonly end: number;
|
|
15
|
+
};
|
|
16
|
+
export type Span = Extent & {
|
|
17
|
+
readonly text: string;
|
|
18
|
+
};
|
|
2
19
|
export type Document = {
|
|
3
20
|
readonly content: string;
|
|
4
21
|
readonly type: string | undefined;
|
|
5
22
|
readonly fields: Readonly<Record<string, unknown>>;
|
|
23
|
+
readonly preamble: string;
|
|
6
24
|
readonly sections: Readonly<Record<string, string>>;
|
|
7
25
|
};
|
|
8
26
|
export type Refusal = {
|
|
@@ -17,6 +35,20 @@ export type Validation = {
|
|
|
17
35
|
} | ({
|
|
18
36
|
readonly verdict: 'refuse';
|
|
19
37
|
} & Refusal);
|
|
38
|
+
export type Projection = {
|
|
39
|
+
readonly ok: true;
|
|
40
|
+
readonly text: string;
|
|
41
|
+
} | {
|
|
42
|
+
readonly ok: false;
|
|
43
|
+
readonly refusal: Refusal;
|
|
44
|
+
};
|
|
45
|
+
export type Division = {
|
|
46
|
+
readonly ok: true;
|
|
47
|
+
readonly spans: readonly Span[];
|
|
48
|
+
} | {
|
|
49
|
+
readonly ok: false;
|
|
50
|
+
readonly refusal: Refusal;
|
|
51
|
+
};
|
|
20
52
|
export type ParseResult = {
|
|
21
53
|
readonly ok: true;
|
|
22
54
|
readonly document: Document;
|
|
@@ -24,6 +56,10 @@ export type ParseResult = {
|
|
|
24
56
|
readonly ok: false;
|
|
25
57
|
readonly refusal: Refusal;
|
|
26
58
|
};
|
|
59
|
+
export type Link = {
|
|
60
|
+
readonly href: string;
|
|
61
|
+
readonly target: string;
|
|
62
|
+
};
|
|
27
63
|
export type Change = {
|
|
28
64
|
readonly kind: 'field';
|
|
29
65
|
readonly name: string;
|
|
@@ -34,6 +70,14 @@ export type Change = {
|
|
|
34
70
|
readonly name: string;
|
|
35
71
|
readonly value: string;
|
|
36
72
|
readonly prior: string;
|
|
73
|
+
} | {
|
|
74
|
+
readonly kind: 'preamble';
|
|
75
|
+
readonly value: string;
|
|
76
|
+
readonly prior: string;
|
|
77
|
+
} | {
|
|
78
|
+
readonly kind: 'link';
|
|
79
|
+
readonly href: string;
|
|
80
|
+
readonly to: string;
|
|
37
81
|
};
|
|
38
82
|
export type ApplyResult = {
|
|
39
83
|
readonly outcome: 'applied';
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEvD,MAAM,MAAM,QAAQ,GAAG;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACnD,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAC9B,CAAC;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,GAAG,OAAO,CAAC,CAAC;AAE/C,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAClD;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,MAAM,GACd;IACE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;CACzB,GACD;IACE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB,CAAC;AAEN,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC5D;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,GAC1D;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/
|
|
1
|
+
{"version":3,"sources":["/workspace/packages/mdmodel/src/types.ts"],"sourcesContent":["export type Library = Readonly<Record<string, string>>;\n\nexport type ValidationContext = {\n readonly binaryTargets: readonly string[];\n};\n\nexport type ProjectionContext = {\n readonly documentTargets: readonly string[];\n readonly definition?: string;\n};\n\nexport type DivisionContext = ProjectionContext & {\n readonly budget: number;\n};\n\nexport type Extent = {\n readonly start: number;\n readonly end: number;\n};\n\nexport type Span = Extent & {\n readonly text: string;\n};\n\nexport type Document = {\n readonly content: string;\n readonly type: string | undefined;\n readonly fields: Readonly<Record<string, unknown>>;\n readonly preamble: string;\n readonly sections: Readonly<Record<string, string>>;\n};\n\nexport type Refusal = {\n readonly file: string;\n readonly rule: string;\n readonly version: string;\n readonly location?: string;\n readonly referrers?: readonly string[];\n};\n\nexport type Validation =\n | { readonly verdict: 'accept' }\n | ({ readonly verdict: 'refuse' } & Refusal);\n\nexport type Projection =\n | { readonly ok: true; readonly text: string }\n | { readonly ok: false; readonly refusal: Refusal };\n\nexport type Division =\n | { readonly ok: true; readonly spans: readonly Span[] }\n | { readonly ok: false; readonly refusal: Refusal };\n\nexport type ParseResult =\n | { readonly ok: true; readonly document: Document }\n | { readonly ok: false; readonly refusal: Refusal };\n\nexport type Link = {\n readonly href: string;\n readonly target: string;\n};\n\nexport type Change =\n | {\n readonly kind: 'field';\n readonly name: string;\n readonly value: unknown;\n readonly prior: unknown;\n }\n | {\n readonly kind: 'section';\n readonly name: string;\n readonly value: string;\n readonly prior: string;\n }\n | {\n readonly kind: 'preamble';\n readonly value: string;\n readonly prior: string;\n }\n | {\n readonly kind: 'link';\n readonly href: string;\n readonly to: string;\n };\n\nexport type ApplyResult =\n | { readonly outcome: 'applied'; readonly document: Document }\n | { readonly outcome: 'stale'; readonly document: Document }\n | { readonly outcome: 'refuse'; readonly refusal: Refusal };\n"],"names":[],"mappings":"AAqFA,WAG8D"}
|
package/dist/validate.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { Library, Validation } from './types.js';
|
|
2
|
-
export declare function validate(library: Library): Validation;
|
|
1
|
+
import type { Library, Validation, ValidationContext } from './types.js';
|
|
2
|
+
export declare function validate(library: Library, context?: ValidationContext): Validation;
|
|
3
3
|
//# sourceMappingURL=validate.d.ts.map
|
package/dist/validate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAY,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../src/validate.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAY,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAuCnF,wBAAgB,QAAQ,CACtB,OAAO,EAAE,OAAO,EAChB,OAAO,GAAE,iBAAyC,GACjD,UAAU,CAuHZ"}
|
package/dist/validate.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { readDefinition } from './definition.js';
|
|
2
2
|
import { parse } from './document.js';
|
|
3
|
-
import {
|
|
3
|
+
import { hrefOccurrences } from './links.js';
|
|
4
4
|
import { classifyHref, isTypesPath } from './paths.js';
|
|
5
5
|
import { refusal } from './refuse.js';
|
|
6
6
|
import { parseListSection } from './sections.js';
|
|
@@ -38,10 +38,14 @@ function declaredTypeOf(content) {
|
|
|
38
38
|
if (!parsed.ok) return undefined;
|
|
39
39
|
return parsed.document.type ?? 'any';
|
|
40
40
|
}
|
|
41
|
-
export function validate(library
|
|
41
|
+
export function validate(library, context = {
|
|
42
|
+
binaryTargets: []
|
|
43
|
+
}) {
|
|
44
|
+
const binaryTargets = new Set(context.binaryTargets);
|
|
42
45
|
const files = Object.keys(library).sort();
|
|
43
46
|
const documents = new Map();
|
|
44
47
|
for (const file of files){
|
|
48
|
+
if (binaryTargets.has(file)) return refuse(file, 'binary-target-document');
|
|
45
49
|
const parsed = parse(library[file], file);
|
|
46
50
|
documents.set(file, parsed);
|
|
47
51
|
if (!parsed.ok) return {
|
|
@@ -86,6 +90,11 @@ export function validate(library) {
|
|
|
86
90
|
location: fieldFailure.field
|
|
87
91
|
});
|
|
88
92
|
}
|
|
93
|
+
const declaredFields = new Set(Object.keys(definition.fields));
|
|
94
|
+
const undeclared = Object.keys(parsed.document.fields).find((name)=>name !== 'type' && !declaredFields.has(name));
|
|
95
|
+
if (undeclared !== undefined) return refuse(file, 'undeclared-field', {
|
|
96
|
+
location: undeclared
|
|
97
|
+
});
|
|
89
98
|
for (const [name, spec] of Object.entries(definition.sections)){
|
|
90
99
|
const body = parsed.document.sections[name];
|
|
91
100
|
if (body === undefined) {
|
|
@@ -114,10 +123,10 @@ export function validate(library) {
|
|
|
114
123
|
if (expected === null) continue;
|
|
115
124
|
for (const target of targets){
|
|
116
125
|
const resolved = classifyHref(file, target);
|
|
117
|
-
if (resolved.kind !== 'path') return refuse(file, 'unresolved-reference', {
|
|
126
|
+
if (resolved.kind !== 'path' || binaryTargets.has(resolved.path)) return refuse(file, 'unresolved-reference', {
|
|
118
127
|
location: name
|
|
119
128
|
});
|
|
120
|
-
if (!(resolved.path
|
|
129
|
+
if (!documents.has(resolved.path)) continue;
|
|
121
130
|
const targetType = declaredTypeOf(library[resolved.path]);
|
|
122
131
|
if (targetType !== expected) return refuse(file, 'unresolved-reference', {
|
|
123
132
|
location: name
|
|
@@ -125,10 +134,10 @@ export function validate(library) {
|
|
|
125
134
|
}
|
|
126
135
|
}
|
|
127
136
|
const body = bodyAfterFrontmatter(library[file]);
|
|
128
|
-
for (const
|
|
129
|
-
const resolved = classifyHref(file, href);
|
|
137
|
+
for (const occurrence of hrefOccurrences(body)){
|
|
138
|
+
const resolved = classifyHref(file, occurrence.href);
|
|
130
139
|
if (resolved.kind === 'skip') continue;
|
|
131
|
-
if (resolved.kind === 'invalid' || !(resolved.path
|
|
140
|
+
if (resolved.kind === 'invalid' || !documents.has(resolved.path) && !binaryTargets.has(resolved.path)) {
|
|
132
141
|
return refuse(file, 'unresolved-link');
|
|
133
142
|
}
|
|
134
143
|
}
|
|
@@ -147,7 +156,7 @@ export function validate(library) {
|
|
|
147
156
|
for (const target of referenceTargets(spec, parsed.document.fields[name])){
|
|
148
157
|
const resolved = classifyHref(file, target);
|
|
149
158
|
if (resolved.kind !== 'path') continue;
|
|
150
|
-
if (resolved.path
|
|
159
|
+
if (documents.has(resolved.path)) continue;
|
|
151
160
|
const referrers = missing.get(resolved.path) ?? [];
|
|
152
161
|
referrers.push(file);
|
|
153
162
|
missing.set(resolved.path, referrers);
|