@agentshouse/mdmodel 0.1.0-alpha.11 → 0.1.0-alpha.13

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 CHANGED
@@ -72,8 +72,9 @@ normalization from the source Document. A binary target supplies no Document
72
72
  or MD Type and cannot satisfy a typed reference, including one to `any`.
73
73
  The existing `any` Document rules are unchanged.
74
74
 
75
- A typed Document carries only the frontmatter fields its MD type declares, so
76
- any other field is refused as `undeclared-field` at that field name. A field
75
+ A typed Document carries the frontmatter fields its MD type declares, plus
76
+ `type`, `site`, and `received`; any other field is refused as
77
+ `undeclared-field` at that field name. A field
77
78
  name YAML carries to a record prototype, `__proto__` among them, is an ordinary
78
79
  undeclared field and is refused as one. A declared list section is validated as
79
80
  a list; its declared item kind governs projection eligibility rather than the
@@ -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;AACnF,OAAO,EAYL,KAAK,OAAO,EACb,MAAM,WAAW,CAAC;AAwCnB,wBAAgB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAK,GAAG,WAAW,CAkD7D;AAyGD,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"}
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"}
package/dist/document.js CHANGED
@@ -92,9 +92,13 @@ function applyField(document, name, value, prior) {
92
92
  const existing = mapEntry(internal.root, name);
93
93
  if (existing !== undefined) {
94
94
  nextContent = splice(document.content, existing.value.start, existing.value.end, serializeJs(value));
95
+ } else if (document.content[internal.root.start] === '{') {
96
+ nextContent = splice(document.content, internal.root.end - 1, internal.root.end - 1, `${internal.root.entries.length === 0 ? '' : ', '}${serializeKey(name)}: ${serializeJs(value)}`);
95
97
  } else {
96
98
  const nl = lineEnding(document.content);
97
- const line = `${serializeKey(name)}: ${serializeJs(value)}${nl}`;
99
+ const lineStart = document.content.lastIndexOf('\n', internal.root.start - 1) + 1;
100
+ const indent = document.content.slice(lineStart, internal.root.start);
101
+ const line = `${indent}${serializeKey(name)}: ${serializeJs(value)}${nl}`;
98
102
  const before = document.content.slice(0, internal.yamlEnd);
99
103
  const prefix = before.endsWith('\n') || before.endsWith('\r\n') ? '' : nl;
100
104
  nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdmodel/src/document.ts"],"sourcesContent":["import { hrefOccurrences } from './links.js';\nimport { classifyHref, hrefSuffix } from './paths.js';\nimport { headingSpans, sectionsRecord } from './sections.js';\nimport { refusal } from './refuse.js';\nimport type { ApplyResult, Change, Document, Link, ParseResult } from './types.js';\nimport {\n bodyStartAfterYaml,\n bodyStartOf,\n equalValue,\n extractFrontmatter,\n jsValue,\n lineEnding,\n mapEntry,\n parseYamlMapping,\n serializeJs,\n serializeKey,\n YamlError,\n type YamlMap,\n} from './yaml.js';\n\ntype Internal = {\n readonly root: YamlMap | null;\n readonly yamlEnd: number;\n readonly bodyStart: number;\n};\n\nconst internals = new WeakMap<Document, Internal>();\n\nfunction refuse(file: string, rule: string, location?: string) {\n return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });\n}\n\nfunction freezeDocument(\n content: string,\n type: string | undefined,\n fields: Record<string, unknown>,\n preamble: string,\n sections: Record<string, string>,\n internal: Internal,\n): Document {\n const document: Document = Object.freeze({\n content,\n type,\n fields: Object.freeze(fields),\n preamble,\n sections: Object.freeze(sections),\n });\n internals.set(document, internal);\n return document;\n}\n\nfunction declaredType(fields: Record<string, unknown>): string | undefined {\n const value = fields.type;\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string' || value === '') return undefined;\n return value;\n}\n\nexport function parse(content: string, file = ''): ParseResult {\n const fence = extractFrontmatter(content);\n if (fence.kind === 'none') {\n const spans = headingSpans(content, 0);\n return {\n ok: true,\n document: freezeDocument(\n content,\n undefined,\n {},\n content.slice(0, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root: null,\n yamlEnd: 0,\n bodyStart: 0,\n },\n ),\n };\n }\n if (fence.kind === 'unclosed') return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n try {\n const root = parseYamlMapping(content, fence.yamlStart, fence.yamlEnd);\n const fields = jsValue(root);\n if (fields === null || typeof fields !== 'object' || Array.isArray(fields)) {\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n }\n const bodyStart = bodyStartAfterYaml(content, fence.yamlEnd);\n const spans = headingSpans(content, bodyStart);\n const record = fields as Record<string, unknown>;\n return {\n ok: true,\n document: freezeDocument(\n content,\n declaredType(record),\n record,\n content.slice(bodyStart, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root,\n yamlEnd: fence.yamlEnd,\n bodyStart,\n },\n ),\n };\n } catch (error) {\n if (error instanceof YamlError)\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n throw error;\n }\n}\n\nfunction splice(content: string, start: number, end: number, insert: string): string {\n return content.slice(0, start) + insert + content.slice(end);\n}\n\nfunction applyField(document: Document, name: string, value: unknown, prior: unknown): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined || internal.root === null) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', name) };\n }\n if (!equalValue(document.fields[name], prior)) {\n return { outcome: 'stale', document };\n }\n let nextContent: string;\n const existing = mapEntry(internal.root, name);\n if (existing !== undefined) {\n nextContent = splice(\n document.content,\n existing.value.start,\n existing.value.end,\n serializeJs(value),\n );\n } else {\n const nl = lineEnding(document.content);\n const line = `${serializeKey(name)}: ${serializeJs(value)}${nl}`;\n const before = document.content.slice(0, internal.yamlEnd);\n const prefix = before.endsWith('\\n') || before.endsWith('\\r\\n') ? '' : nl;\n nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);\n }\n const parsed = parse(nextContent);\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applySection(document: Document, name: string, value: string, prior: string): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const spans = headingSpans(document.content, internal.bodyStart);\n const span = spans.find((item) => item.name === name);\n if (span === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const current = document.content.slice(span.bodyStart, span.bodyEnd);\n if (current !== prior) return { outcome: 'stale', document };\n const parsed = parse(splice(document.content, span.bodyStart, span.bodyEnd, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applyPreamble(document: Document, value: string, prior: string): ApplyResult {\n if (document.preamble !== prior) return { outcome: 'stale', document };\n const start = bodyStartOf(document.content);\n const parsed = parse(splice(document.content, start, start + document.preamble.length, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction fitsBare(to: string): boolean {\n if (to === '' || to.startsWith('<')) return false;\n let depth = 0;\n for (const character of to) {\n if (/[\\s\\u0000-\\u001f\\u007f]/.test(character)) return false;\n if (character === '(') depth += 1;\n else if (character === ')') {\n if (depth === 0) return false;\n depth -= 1;\n }\n }\n return depth === 0;\n}\n\nfunction fitsBrackets(to: string): boolean {\n return to !== '' && !/[<>\\n\\r]/.test(to);\n}\n\nfunction destinationText(to: string, bracketed: boolean): string | null {\n if (fitsBare(to)) return bracketed && fitsBrackets(to) ? `<${to}>` : to;\n if (fitsBrackets(to)) return `<${to}>`;\n return null;\n}\n\nfunction applyLink(document: Document, href: string, to: string): ApplyResult {\n const content = document.content;\n const bodyStart = bodyStartOf(content);\n const matches = hrefOccurrences(content.slice(bodyStart)).filter(\n (occurrence) => occurrence.href === href,\n );\n if (matches.length === 0) return { outcome: 'stale', document };\n const written = to + hrefSuffix(href);\n let rewritten = '';\n let cursor = 0;\n for (const match of matches) {\n const text = destinationText(written, match.bracketed);\n if (text === null)\n return { outcome: 'refuse', refusal: refuse('', 'unwritable-link', written) };\n rewritten += content.slice(cursor, bodyStart + match.start);\n rewritten += text;\n cursor = bodyStart + match.end;\n }\n const parsed = parse(rewritten + content.slice(cursor));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nexport function links(document: Document, file: string): readonly Link[] {\n const found: Link[] = [];\n const seen = new Set<string>();\n for (const occurrence of hrefOccurrences(document.content.slice(bodyStartOf(document.content)))) {\n if (seen.has(occurrence.href)) continue;\n const resolved = classifyHref(file, occurrence.href);\n if (resolved.kind !== 'path') continue;\n seen.add(occurrence.href);\n found.push({ href: occurrence.href, target: resolved.path });\n }\n return found;\n}\n\nexport function apply(document: Document, change: Change): ApplyResult {\n if (change.kind === 'link') return applyLink(document, change.href, change.to);\n if (change.kind === 'preamble') return applyPreamble(document, change.value, change.prior);\n try {\n if (change.kind === 'field')\n return applyField(document, change.name, change.value, change.prior);\n return applySection(document, change.name, change.value, change.prior);\n } catch (error) {\n if (error instanceof YamlError) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', change.name) };\n }\n throw error;\n }\n}\n\nexport function serialize(document: Document): string {\n return document.content;\n}\n\nexport function frontmatter(document: Document): YamlMap | null {\n return internals.get(document)?.root ?? null;\n}\n"],"names":["hrefOccurrences","classifyHref","hrefSuffix","headingSpans","sectionsRecord","refusal","bodyStartAfterYaml","bodyStartOf","equalValue","extractFrontmatter","jsValue","lineEnding","mapEntry","parseYamlMapping","serializeJs","serializeKey","YamlError","internals","WeakMap","refuse","file","rule","location","undefined","freezeDocument","content","type","fields","preamble","sections","internal","document","Object","freeze","set","declaredType","value","parse","fence","kind","spans","ok","slice","headingStart","root","yamlEnd","bodyStart","yamlStart","Array","isArray","record","error","splice","start","end","insert","applyField","name","prior","get","outcome","nextContent","existing","nl","line","before","prefix","endsWith","parsed","applySection","span","find","item","current","bodyEnd","applyPreamble","length","fitsBare","to","startsWith","depth","character","test","fitsBrackets","destinationText","bracketed","applyLink","href","matches","filter","occurrence","written","rewritten","cursor","match","text","links","found","seen","Set","has","resolved","add","push","target","path","apply","change","serialize","frontmatter"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdmodel/src/document.ts"],"sourcesContent":["import { hrefOccurrences } from './links.js';\nimport { classifyHref, hrefSuffix } from './paths.js';\nimport { headingSpans, sectionsRecord } from './sections.js';\nimport { refusal } from './refuse.js';\nimport type { ApplyResult, Change, Document, Link, ParseResult } from './types.js';\nimport {\n bodyStartAfterYaml,\n bodyStartOf,\n equalValue,\n extractFrontmatter,\n jsValue,\n lineEnding,\n mapEntry,\n parseYamlMapping,\n serializeJs,\n serializeKey,\n YamlError,\n type YamlMap,\n} from './yaml.js';\n\ntype Internal = {\n readonly root: YamlMap | null;\n readonly yamlEnd: number;\n readonly bodyStart: number;\n};\n\nconst internals = new WeakMap<Document, Internal>();\n\nfunction refuse(file: string, rule: string, location?: string) {\n return location === undefined ? refusal(file, rule) : refusal(file, rule, { location });\n}\n\nfunction freezeDocument(\n content: string,\n type: string | undefined,\n fields: Record<string, unknown>,\n preamble: string,\n sections: Record<string, string>,\n internal: Internal,\n): Document {\n const document: Document = Object.freeze({\n content,\n type,\n fields: Object.freeze(fields),\n preamble,\n sections: Object.freeze(sections),\n });\n internals.set(document, internal);\n return document;\n}\n\nfunction declaredType(fields: Record<string, unknown>): string | undefined {\n const value = fields.type;\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string' || value === '') return undefined;\n return value;\n}\n\nexport function parse(content: string, file = ''): ParseResult {\n const fence = extractFrontmatter(content);\n if (fence.kind === 'none') {\n const spans = headingSpans(content, 0);\n return {\n ok: true,\n document: freezeDocument(\n content,\n undefined,\n {},\n content.slice(0, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root: null,\n yamlEnd: 0,\n bodyStart: 0,\n },\n ),\n };\n }\n if (fence.kind === 'unclosed') return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n try {\n const root = parseYamlMapping(content, fence.yamlStart, fence.yamlEnd);\n const fields = jsValue(root);\n if (fields === null || typeof fields !== 'object' || Array.isArray(fields)) {\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n }\n const bodyStart = bodyStartAfterYaml(content, fence.yamlEnd);\n const spans = headingSpans(content, bodyStart);\n const record = fields as Record<string, unknown>;\n return {\n ok: true,\n document: freezeDocument(\n content,\n declaredType(record),\n record,\n content.slice(bodyStart, spans[0]?.headingStart),\n sectionsRecord(spans, content),\n {\n root,\n yamlEnd: fence.yamlEnd,\n bodyStart,\n },\n ),\n };\n } catch (error) {\n if (error instanceof YamlError)\n return { ok: false, refusal: refuse(file, 'frontmatter-fence') };\n throw error;\n }\n}\n\nfunction splice(content: string, start: number, end: number, insert: string): string {\n return content.slice(0, start) + insert + content.slice(end);\n}\n\nfunction applyField(document: Document, name: string, value: unknown, prior: unknown): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined || internal.root === null) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', name) };\n }\n if (!equalValue(document.fields[name], prior)) {\n return { outcome: 'stale', document };\n }\n let nextContent: string;\n const existing = mapEntry(internal.root, name);\n if (existing !== undefined) {\n nextContent = splice(\n document.content,\n existing.value.start,\n existing.value.end,\n serializeJs(value),\n );\n } else if (document.content[internal.root.start] === '{') {\n nextContent = splice(\n document.content,\n internal.root.end - 1,\n internal.root.end - 1,\n `${internal.root.entries.length === 0 ? '' : ', '}${serializeKey(name)}: ${serializeJs(value)}`,\n );\n } else {\n const nl = lineEnding(document.content);\n const lineStart = document.content.lastIndexOf('\\n', internal.root.start - 1) + 1;\n const indent = document.content.slice(lineStart, internal.root.start);\n const line = `${indent}${serializeKey(name)}: ${serializeJs(value)}${nl}`;\n const before = document.content.slice(0, internal.yamlEnd);\n const prefix = before.endsWith('\\n') || before.endsWith('\\r\\n') ? '' : nl;\n nextContent = splice(document.content, internal.yamlEnd, internal.yamlEnd, `${prefix}${line}`);\n }\n const parsed = parse(nextContent);\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applySection(document: Document, name: string, value: string, prior: string): ApplyResult {\n const internal = internals.get(document);\n if (internal === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const spans = headingSpans(document.content, internal.bodyStart);\n const span = spans.find((item) => item.name === name);\n if (span === undefined)\n return { outcome: 'refuse', refusal: refuse('', 'required-section', name) };\n const current = document.content.slice(span.bodyStart, span.bodyEnd);\n if (current !== prior) return { outcome: 'stale', document };\n const parsed = parse(splice(document.content, span.bodyStart, span.bodyEnd, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction applyPreamble(document: Document, value: string, prior: string): ApplyResult {\n if (document.preamble !== prior) return { outcome: 'stale', document };\n const start = bodyStartOf(document.content);\n const parsed = parse(splice(document.content, start, start + document.preamble.length, value));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nfunction fitsBare(to: string): boolean {\n if (to === '' || to.startsWith('<')) return false;\n let depth = 0;\n for (const character of to) {\n if (/[\\s\\u0000-\\u001f\\u007f]/.test(character)) return false;\n if (character === '(') depth += 1;\n else if (character === ')') {\n if (depth === 0) return false;\n depth -= 1;\n }\n }\n return depth === 0;\n}\n\nfunction fitsBrackets(to: string): boolean {\n return to !== '' && !/[<>\\n\\r]/.test(to);\n}\n\nfunction destinationText(to: string, bracketed: boolean): string | null {\n if (fitsBare(to)) return bracketed && fitsBrackets(to) ? `<${to}>` : to;\n if (fitsBrackets(to)) return `<${to}>`;\n return null;\n}\n\nfunction applyLink(document: Document, href: string, to: string): ApplyResult {\n const content = document.content;\n const bodyStart = bodyStartOf(content);\n const matches = hrefOccurrences(content.slice(bodyStart)).filter(\n (occurrence) => occurrence.href === href,\n );\n if (matches.length === 0) return { outcome: 'stale', document };\n const written = to + hrefSuffix(href);\n let rewritten = '';\n let cursor = 0;\n for (const match of matches) {\n const text = destinationText(written, match.bracketed);\n if (text === null)\n return { outcome: 'refuse', refusal: refuse('', 'unwritable-link', written) };\n rewritten += content.slice(cursor, bodyStart + match.start);\n rewritten += text;\n cursor = bodyStart + match.end;\n }\n const parsed = parse(rewritten + content.slice(cursor));\n if (!parsed.ok) return { outcome: 'refuse', refusal: parsed.refusal };\n return { outcome: 'applied', document: parsed.document };\n}\n\nexport function links(document: Document, file: string): readonly Link[] {\n const found: Link[] = [];\n const seen = new Set<string>();\n for (const occurrence of hrefOccurrences(document.content.slice(bodyStartOf(document.content)))) {\n if (seen.has(occurrence.href)) continue;\n const resolved = classifyHref(file, occurrence.href);\n if (resolved.kind !== 'path') continue;\n seen.add(occurrence.href);\n found.push({ href: occurrence.href, target: resolved.path });\n }\n return found;\n}\n\nexport function apply(document: Document, change: Change): ApplyResult {\n if (change.kind === 'link') return applyLink(document, change.href, change.to);\n if (change.kind === 'preamble') return applyPreamble(document, change.value, change.prior);\n try {\n if (change.kind === 'field')\n return applyField(document, change.name, change.value, change.prior);\n return applySection(document, change.name, change.value, change.prior);\n } catch (error) {\n if (error instanceof YamlError) {\n return { outcome: 'refuse', refusal: refuse('', 'frontmatter-fence', change.name) };\n }\n throw error;\n }\n}\n\nexport function serialize(document: Document): string {\n return document.content;\n}\n\nexport function frontmatter(document: Document): YamlMap | null {\n return internals.get(document)?.root ?? null;\n}\n"],"names":["hrefOccurrences","classifyHref","hrefSuffix","headingSpans","sectionsRecord","refusal","bodyStartAfterYaml","bodyStartOf","equalValue","extractFrontmatter","jsValue","lineEnding","mapEntry","parseYamlMapping","serializeJs","serializeKey","YamlError","internals","WeakMap","refuse","file","rule","location","undefined","freezeDocument","content","type","fields","preamble","sections","internal","document","Object","freeze","set","declaredType","value","parse","fence","kind","spans","ok","slice","headingStart","root","yamlEnd","bodyStart","yamlStart","Array","isArray","record","error","splice","start","end","insert","applyField","name","prior","get","outcome","nextContent","existing","entries","length","nl","lineStart","lastIndexOf","indent","line","before","prefix","endsWith","parsed","applySection","span","find","item","current","bodyEnd","applyPreamble","fitsBare","to","startsWith","depth","character","test","fitsBrackets","destinationText","bracketed","applyLink","href","matches","filter","occurrence","written","rewritten","cursor","match","text","links","found","seen","Set","has","resolved","add","push","target","path","apply","change","serialize","frontmatter"],"mappings":"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"}
package/dist/validate.js CHANGED
@@ -91,7 +91,11 @@ export function validate(library, context = {
91
91
  });
92
92
  }
93
93
  const declaredFields = new Set(Object.keys(definition.fields));
94
- const undeclared = Object.keys(parsed.document.fields).find((name)=>name !== 'type' && !declaredFields.has(name));
94
+ const undeclared = Object.keys(parsed.document.fields).find((name)=>![
95
+ 'type',
96
+ 'site',
97
+ 'received'
98
+ ].includes(name) && !declaredFields.has(name));
95
99
  if (undeclared !== undefined) return refuse(file, 'undeclared-field', {
96
100
  location: undeclared
97
101
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdmodel/src/validate.ts"],"sourcesContent":["import { readDefinition, type Definition, type FieldSpec } from './definition.js';\nimport { parse } from './document.js';\nimport { hrefOccurrences } from './links.js';\nimport { classifyHref, isTypesPath } from './paths.js';\nimport { refusal } from './refuse.js';\nimport { parseListSection } from './sections.js';\nimport { validateFields } from './schema.js';\nimport type { Document, Library, Validation, ValidationContext } from './types.js';\nimport { bodyAfterFrontmatter } from './yaml.js';\n\nfunction refuse(\n file: string,\n rule: string,\n extra?: { location?: string; referrers?: readonly string[] },\n): Validation {\n return { verdict: 'refuse', ...refusal(file, rule, extra) };\n}\n\nfunction instanceType(document: Document, file: string): 'any' | 'definition' | 'invalid' | string {\n if (isTypesPath(file)) return 'definition';\n const raw = document.fields.type;\n if (raw === undefined || raw === null) return 'any';\n if (typeof raw !== 'string' || raw === '') return 'invalid';\n return raw;\n}\n\nfunction referenceTargets(spec: FieldSpec, value: unknown): string[] {\n if (spec.kind === 'reference' && typeof value === 'string') return [value];\n if (spec.kind === 'list' && spec.of.kind === 'reference' && Array.isArray(value)) {\n return value.filter((item): item is string => typeof item === 'string');\n }\n return [];\n}\n\nfunction expectedReferenceType(spec: FieldSpec): string | null {\n if (spec.kind === 'reference') return spec.to;\n if (spec.kind === 'list' && spec.of.kind === 'reference') return spec.of.to;\n return null;\n}\n\nfunction declaredTypeOf(content: string): string | undefined {\n const parsed = parse(content);\n if (!parsed.ok) return undefined;\n return parsed.document.type ?? 'any';\n}\n\nexport function validate(\n library: Library,\n context: ValidationContext = { binaryTargets: [] },\n): Validation {\n const binaryTargets = new Set(context.binaryTargets);\n const files = Object.keys(library).sort();\n const documents = new Map<string, ReturnType<typeof parse>>();\n for (const file of files) {\n if (binaryTargets.has(file)) return refuse(file, 'binary-target-document');\n const parsed = parse(library[file]!, file);\n documents.set(file, parsed);\n if (!parsed.ok) return { verdict: 'refuse', ...parsed.refusal };\n }\n\n const definitions = new Map<string, Definition>();\n for (const file of files) {\n if (!isTypesPath(file)) continue;\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const definition = readDefinition(file, parsed.document);\n if ('rule' in definition) return { verdict: 'refuse', ...definition };\n const existing = definitions.get(definition.name);\n if (existing !== undefined)\n return refuse(file, 'definition-duplicate', { location: definition.name });\n definitions.set(definition.name, definition);\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any') continue;\n if (kind === 'invalid' || kind === 'definition') {\n if (kind === 'definition' && isTypesPath(file)) continue;\n return refuse(file, 'unknown-type', { location: 'type' });\n }\n const definition = definitions.get(kind);\n if (definition === undefined) return refuse(file, 'unknown-type', { location: 'type' });\n const fieldFailure = validateFields(definition.fields, parsed.document.fields);\n if (fieldFailure !== undefined) {\n return refuse(file, fieldFailure.rule, { location: fieldFailure.field });\n }\n const declaredFields = new Set(Object.keys(definition.fields));\n const undeclared = Object.keys(parsed.document.fields).find(\n (name) => name !== 'type' && !declaredFields.has(name),\n );\n if (undeclared !== undefined) return refuse(file, 'undeclared-field', { location: undeclared });\n for (const [name, spec] of Object.entries(definition.sections)) {\n const body = parsed.document.sections[name];\n if (body === undefined) {\n if (spec.required) return refuse(file, 'required-section', { location: name });\n continue;\n }\n if (spec.kind === 'list' && !parseListSection(body)) {\n return refuse(file, 'structured-section', { location: name });\n }\n }\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const targets = referenceTargets(spec, parsed.document.fields[name]);\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of targets) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path' || binaryTargets.has(resolved.path))\n return refuse(file, 'unresolved-reference', { location: name });\n if (!documents.has(resolved.path)) continue;\n const targetType = declaredTypeOf(library[resolved.path]!);\n if (targetType !== expected)\n return refuse(file, 'unresolved-reference', { location: name });\n }\n }\n const body = bodyAfterFrontmatter(library[file]!);\n for (const occurrence of hrefOccurrences(body)) {\n const resolved = classifyHref(file, occurrence.href);\n if (resolved.kind === 'skip') continue;\n if (\n resolved.kind === 'invalid' ||\n (!documents.has(resolved.path) && !binaryTargets.has(resolved.path))\n ) {\n return refuse(file, 'unresolved-link');\n }\n }\n }\n\n const missing = new Map<string, string[]>();\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of referenceTargets(spec, parsed.document.fields[name])) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path') continue;\n if (documents.has(resolved.path)) continue;\n const referrers = missing.get(resolved.path) ?? [];\n referrers.push(file);\n missing.set(resolved.path, referrers);\n }\n }\n }\n const missingPaths = [...missing.keys()].sort();\n if (missingPaths.length > 0) {\n const path = missingPaths[0]!;\n const referrers = [...new Set(missing.get(path) ?? [])].sort();\n return refuse(path, 'referenced-missing-file', { referrers });\n }\n\n return { verdict: 'accept' };\n}\n"],"names":["readDefinition","parse","hrefOccurrences","classifyHref","isTypesPath","refusal","parseListSection","validateFields","bodyAfterFrontmatter","refuse","file","rule","extra","verdict","instanceType","document","raw","fields","type","undefined","referenceTargets","spec","value","kind","of","Array","isArray","filter","item","expectedReferenceType","to","declaredTypeOf","content","parsed","ok","validate","library","context","binaryTargets","Set","files","Object","keys","sort","documents","Map","has","set","definitions","get","definition","existing","name","location","fieldFailure","field","declaredFields","undeclared","find","entries","sections","body","required","targets","expected","target","resolved","path","targetType","occurrence","href","missing","referrers","push","missingPaths","length"],"mappings":"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"}
1
+ {"version":3,"sources":["/workspace/packages/mdmodel/src/validate.ts"],"sourcesContent":["import { readDefinition, type Definition, type FieldSpec } from './definition.js';\nimport { parse } from './document.js';\nimport { hrefOccurrences } from './links.js';\nimport { classifyHref, isTypesPath } from './paths.js';\nimport { refusal } from './refuse.js';\nimport { parseListSection } from './sections.js';\nimport { validateFields } from './schema.js';\nimport type { Document, Library, Validation, ValidationContext } from './types.js';\nimport { bodyAfterFrontmatter } from './yaml.js';\n\nfunction refuse(\n file: string,\n rule: string,\n extra?: { location?: string; referrers?: readonly string[] },\n): Validation {\n return { verdict: 'refuse', ...refusal(file, rule, extra) };\n}\n\nfunction instanceType(document: Document, file: string): 'any' | 'definition' | 'invalid' | string {\n if (isTypesPath(file)) return 'definition';\n const raw = document.fields.type;\n if (raw === undefined || raw === null) return 'any';\n if (typeof raw !== 'string' || raw === '') return 'invalid';\n return raw;\n}\n\nfunction referenceTargets(spec: FieldSpec, value: unknown): string[] {\n if (spec.kind === 'reference' && typeof value === 'string') return [value];\n if (spec.kind === 'list' && spec.of.kind === 'reference' && Array.isArray(value)) {\n return value.filter((item): item is string => typeof item === 'string');\n }\n return [];\n}\n\nfunction expectedReferenceType(spec: FieldSpec): string | null {\n if (spec.kind === 'reference') return spec.to;\n if (spec.kind === 'list' && spec.of.kind === 'reference') return spec.of.to;\n return null;\n}\n\nfunction declaredTypeOf(content: string): string | undefined {\n const parsed = parse(content);\n if (!parsed.ok) return undefined;\n return parsed.document.type ?? 'any';\n}\n\nexport function validate(\n library: Library,\n context: ValidationContext = { binaryTargets: [] },\n): Validation {\n const binaryTargets = new Set(context.binaryTargets);\n const files = Object.keys(library).sort();\n const documents = new Map<string, ReturnType<typeof parse>>();\n for (const file of files) {\n if (binaryTargets.has(file)) return refuse(file, 'binary-target-document');\n const parsed = parse(library[file]!, file);\n documents.set(file, parsed);\n if (!parsed.ok) return { verdict: 'refuse', ...parsed.refusal };\n }\n\n const definitions = new Map<string, Definition>();\n for (const file of files) {\n if (!isTypesPath(file)) continue;\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const definition = readDefinition(file, parsed.document);\n if ('rule' in definition) return { verdict: 'refuse', ...definition };\n const existing = definitions.get(definition.name);\n if (existing !== undefined)\n return refuse(file, 'definition-duplicate', { location: definition.name });\n definitions.set(definition.name, definition);\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any') continue;\n if (kind === 'invalid' || kind === 'definition') {\n if (kind === 'definition' && isTypesPath(file)) continue;\n return refuse(file, 'unknown-type', { location: 'type' });\n }\n const definition = definitions.get(kind);\n if (definition === undefined) return refuse(file, 'unknown-type', { location: 'type' });\n const fieldFailure = validateFields(definition.fields, parsed.document.fields);\n if (fieldFailure !== undefined) {\n return refuse(file, fieldFailure.rule, { location: fieldFailure.field });\n }\n const declaredFields = new Set(Object.keys(definition.fields));\n const undeclared = Object.keys(parsed.document.fields).find(\n (name) => !['type', 'site', 'received'].includes(name) && !declaredFields.has(name),\n );\n if (undeclared !== undefined) return refuse(file, 'undeclared-field', { location: undeclared });\n for (const [name, spec] of Object.entries(definition.sections)) {\n const body = parsed.document.sections[name];\n if (body === undefined) {\n if (spec.required) return refuse(file, 'required-section', { location: name });\n continue;\n }\n if (spec.kind === 'list' && !parseListSection(body)) {\n return refuse(file, 'structured-section', { location: name });\n }\n }\n }\n\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const targets = referenceTargets(spec, parsed.document.fields[name]);\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of targets) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path' || binaryTargets.has(resolved.path))\n return refuse(file, 'unresolved-reference', { location: name });\n if (!documents.has(resolved.path)) continue;\n const targetType = declaredTypeOf(library[resolved.path]!);\n if (targetType !== expected)\n return refuse(file, 'unresolved-reference', { location: name });\n }\n }\n const body = bodyAfterFrontmatter(library[file]!);\n for (const occurrence of hrefOccurrences(body)) {\n const resolved = classifyHref(file, occurrence.href);\n if (resolved.kind === 'skip') continue;\n if (\n resolved.kind === 'invalid' ||\n (!documents.has(resolved.path) && !binaryTargets.has(resolved.path))\n ) {\n return refuse(file, 'unresolved-link');\n }\n }\n }\n\n const missing = new Map<string, string[]>();\n for (const file of files) {\n const parsed = documents.get(file);\n if (parsed === undefined || !parsed.ok) continue;\n const kind = instanceType(parsed.document, file);\n if (kind === 'any' || kind === 'definition' || kind === 'invalid') continue;\n const definition = definitions.get(kind);\n if (definition === undefined) continue;\n for (const [name, spec] of Object.entries(definition.fields)) {\n const expected = expectedReferenceType(spec);\n if (expected === null) continue;\n for (const target of referenceTargets(spec, parsed.document.fields[name])) {\n const resolved = classifyHref(file, target);\n if (resolved.kind !== 'path') continue;\n if (documents.has(resolved.path)) continue;\n const referrers = missing.get(resolved.path) ?? [];\n referrers.push(file);\n missing.set(resolved.path, referrers);\n }\n }\n }\n const missingPaths = [...missing.keys()].sort();\n if (missingPaths.length > 0) {\n const path = missingPaths[0]!;\n const referrers = [...new Set(missing.get(path) ?? [])].sort();\n return refuse(path, 'referenced-missing-file', { referrers });\n }\n\n return { verdict: 'accept' };\n}\n"],"names":["readDefinition","parse","hrefOccurrences","classifyHref","isTypesPath","refusal","parseListSection","validateFields","bodyAfterFrontmatter","refuse","file","rule","extra","verdict","instanceType","document","raw","fields","type","undefined","referenceTargets","spec","value","kind","of","Array","isArray","filter","item","expectedReferenceType","to","declaredTypeOf","content","parsed","ok","validate","library","context","binaryTargets","Set","files","Object","keys","sort","documents","Map","has","set","definitions","get","definition","existing","name","location","fieldFailure","field","declaredFields","undeclared","find","includes","entries","sections","body","required","targets","expected","target","resolved","path","targetType","occurrence","href","missing","referrers","push","missingPaths","length"],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.1.0-alpha.11";
1
+ export declare const VERSION = "0.1.0-alpha.13";
2
2
  //# sourceMappingURL=version.d.ts.map
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
- export const VERSION = '0.1.0-alpha.11';
1
+ export const VERSION = '0.1.0-alpha.13';
2
2
 
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["/workspace/packages/mdmodel/src/version.ts"],"sourcesContent":["export const VERSION = '0.1.0-alpha.11';\n"],"names":["VERSION"],"mappings":"AAAA,OAAO,MAAMA,UAAU,iBAAiB"}
1
+ {"version":3,"sources":["/workspace/packages/mdmodel/src/version.ts"],"sourcesContent":["export const VERSION = '0.1.0-alpha.13';\n"],"names":["VERSION"],"mappings":"AAAA,OAAO,MAAMA,UAAU,iBAAiB"}
@@ -0,0 +1 @@
1
+ { "binaryTargets": [] }
@@ -0,0 +1 @@
1
+ { "verdict": "accept" }
@@ -0,0 +1,8 @@
1
+ ---
2
+ type: note
3
+ title: Visitor
4
+ site: example
5
+ received: 2026-09-26T12:00:00.000Z
6
+ ---
7
+
8
+ Hello.
@@ -0,0 +1,5 @@
1
+ ---
2
+ type: definition
3
+ fields:
4
+ title: { kind: string, required: true }
5
+ ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentshouse/mdmodel",
3
- "version": "0.1.0-alpha.11",
3
+ "version": "0.1.0-alpha.13",
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",