docmeta 1.0.0 → 1.1.0
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.
|
@@ -981,7 +981,7 @@ async function runGet(opts) {
|
|
|
981
981
|
}
|
|
982
982
|
const extracted = extractor.extract(content, label);
|
|
983
983
|
const values = {};
|
|
984
|
-
for (const f of opts.fields) values[f] = extracted.data
|
|
984
|
+
for (const f of opts.fields) values[f] = resolveField(extracted.data, f);
|
|
985
985
|
out.push({ file: label, present: extracted.present, values });
|
|
986
986
|
};
|
|
987
987
|
if (usingStdin) {
|
|
@@ -998,6 +998,27 @@ async function runGet(opts) {
|
|
|
998
998
|
}
|
|
999
999
|
return out;
|
|
1000
1000
|
}
|
|
1001
|
+
function resolveField(data, field) {
|
|
1002
|
+
const segments = field.startsWith("/") ? parseJsonPointer(field) : field.split(".");
|
|
1003
|
+
let current = data;
|
|
1004
|
+
for (const segment of segments) {
|
|
1005
|
+
if (Array.isArray(current)) {
|
|
1006
|
+
if (!/^\d+$/.test(segment)) return void 0;
|
|
1007
|
+
current = current[Number(segment)];
|
|
1008
|
+
} else if (current !== null && typeof current === "object") {
|
|
1009
|
+
if (!Object.prototype.hasOwnProperty.call(current, segment)) {
|
|
1010
|
+
return void 0;
|
|
1011
|
+
}
|
|
1012
|
+
current = current[segment];
|
|
1013
|
+
} else {
|
|
1014
|
+
return void 0;
|
|
1015
|
+
}
|
|
1016
|
+
}
|
|
1017
|
+
return current;
|
|
1018
|
+
}
|
|
1019
|
+
function parseJsonPointer(pointer) {
|
|
1020
|
+
return pointer.split("/").slice(1).map((s) => s.replace(/~1/g, "/").replace(/~0/g, "~"));
|
|
1021
|
+
}
|
|
1001
1022
|
|
|
1002
1023
|
// src/commands/schemas.ts
|
|
1003
1024
|
function getSchemasInfo() {
|
|
@@ -1088,4 +1109,4 @@ export {
|
|
|
1088
1109
|
shouldColor,
|
|
1089
1110
|
render
|
|
1090
1111
|
};
|
|
1091
|
-
//# sourceMappingURL=chunk-
|
|
1112
|
+
//# sourceMappingURL=chunk-DLQ4BV2J.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts","../src/core/config.ts","../src/core/resolve-schema.ts","../src/core/schema-registry.ts","../src/schemas/okf/0.1.json","../src/core/validator.ts","../src/commands/validate.ts","../src/extractors/markdown.ts","../src/extractors/mdx.ts","../src/extractors/asciidoc.ts","../src/extractors/rst.ts","../src/extractors/xml.ts","../src/extractors/html.ts","../src/extractors/index.ts","../src/core/load-files.ts","../src/commands/get.ts","../src/commands/schemas.ts","../src/reporters/color.ts","../src/reporters/index.ts"],"sourcesContent":["/**\n * Shared types for docmeta.\n *\n * The pipeline is: load files -> extract metadata (format-specific) ->\n * resolve a schema set per file -> validate against each schema -> report.\n * Everything after extraction operates only on `ExtractedMetadata`, so new\n * input formats never touch validation, resolution, or reporting.\n */\n\n/** Result of pulling a metadata block out of a single document. */\nexport interface ExtractedMetadata {\n /** Parsed metadata key/values. `{}` when a block is present but empty. */\n data: Record<string, unknown>;\n /** Whether a metadata block was found at all. */\n present: boolean;\n /** Name of the extractor/format that produced this (e.g. \"markdown\"). */\n format: string;\n /**\n * Map a JSON Pointer (Ajv `instancePath`, e.g. \"/tags/0\") or a bare top-level\n * key to its 1-based source line, for precise annotations. Returns undefined\n * when no position is known.\n */\n lineFor(pointer: string): number | undefined;\n}\n\n/** A pluggable metadata extractor for one document format. */\nexport interface MetadataExtractor {\n /** Stable name, also used as `ExtractedMetadata.format`. */\n name: string;\n /** Lowercase file extensions this extractor handles, incl. dot (e.g. \".md\"). */\n extensions: string[];\n /** Whether this extractor is wired up (false for roadmap stubs). */\n implemented: boolean;\n /** Extract metadata from raw file content. */\n extract(content: string, filePath: string): ExtractedMetadata;\n}\n\n/** A single schema violation for one file, attributed to one schema. */\nexport interface FieldError {\n /** Schema id/ref that produced this error (e.g. \"google:okf:0.1\"). */\n schema: string;\n /** Ajv instancePath, e.g. \"/tags/0\" or \"\" for the root. */\n instancePath: string;\n /** Human-readable message. */\n message: string;\n /** 1-based source line, when known. */\n line?: number;\n /** 1-based column, when known. */\n col?: number;\n}\n\n/** Validation outcome for a single file. */\nexport interface ValidationResult {\n /** Absolute or cwd-relative path of the file. */\n file: string;\n /** Extractor/format used. */\n format: string;\n /** Whether validation passed against every schema in the set. */\n ok: boolean;\n /** Schema ids/refs the file was validated against. */\n schemas: string[];\n /** All violations, across every schema in the set. */\n errors: FieldError[];\n}\n\n/** Aggregate run summary. */\nexport interface RunSummary {\n files: number;\n passed: number;\n failed: number;\n errors: number;\n}\n\n/** An operational/usage failure that should map to exit code 2. */\nexport class DocmetaError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DocmetaError\";\n }\n}\n","/**\n * Optional lightweight YAML config (`docmeta.config.yaml`). Supplies default\n * targets, excludes, the default schema set, and optional per-glob overrides,\n * so CI can run a bare `docmeta validate`.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { DocmetaError } from \"../types.js\";\n\nexport interface SchemaOverride {\n files: string;\n schemas: string[];\n}\n\nexport interface DocmetaConfig {\n paths?: string[];\n exclude?: string[];\n schemas?: string[];\n overrides?: SchemaOverride[];\n}\n\nconst CONFIG_NAMES = [\"docmeta.config.yaml\", \"docmeta.config.yml\"];\n\nfunction asStringList(value: unknown, field: string, source: string): string[] {\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\")) {\n throw new DocmetaError(\n `${source}: \"${field}\" must be a list of strings.`,\n );\n }\n return value as string[];\n}\n\n/** Parse and validate config YAML text. */\nexport function parseConfig(text: string, source: string): DocmetaConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (err) {\n throw new DocmetaError(\n `${source}: invalid YAML: ${(err as Error).message}`,\n );\n }\n if (raw == null) return {};\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocmetaError(`${source}: top level must be a mapping.`);\n }\n const obj = raw as Record<string, unknown>;\n const config: DocmetaConfig = {};\n\n if (obj.paths !== undefined) config.paths = asStringList(obj.paths, \"paths\", source);\n if (obj.exclude !== undefined)\n config.exclude = asStringList(obj.exclude, \"exclude\", source);\n if (obj.schemas !== undefined)\n config.schemas = asStringList(obj.schemas, \"schemas\", source);\n\n if (obj.overrides !== undefined) {\n if (!Array.isArray(obj.overrides)) {\n throw new DocmetaError(`${source}: \"overrides\" must be a list.`);\n }\n config.overrides = obj.overrides.map((entry, i) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw new DocmetaError(`${source}: overrides[${i}] must be a mapping.`);\n }\n const e = entry as Record<string, unknown>;\n if (typeof e.files !== \"string\") {\n throw new DocmetaError(\n `${source}: overrides[${i}].files must be a string glob.`,\n );\n }\n return {\n files: e.files,\n schemas: asStringList(e.schemas, `overrides[${i}].schemas`, source),\n };\n });\n }\n\n return config;\n}\n\n/**\n * Load config from an explicit path (error if missing) or by discovery in cwd.\n * Returns null when no config is found via discovery.\n */\nexport async function loadConfig(\n explicitPath?: string,\n cwd: string = process.cwd(),\n): Promise<{ config: DocmetaConfig; path: string } | null> {\n if (explicitPath) {\n let text: string;\n try {\n text = await readFile(explicitPath, \"utf8\");\n } catch {\n throw new DocmetaError(`Config file not found: \"${explicitPath}\".`);\n }\n return { config: parseConfig(text, explicitPath), path: explicitPath };\n }\n\n for (const name of CONFIG_NAMES) {\n const p = resolve(cwd, name);\n try {\n const text = await readFile(p, \"utf8\");\n return { config: parseConfig(text, name), path: p };\n } catch {\n // not found; try next\n }\n }\n return null;\n}\n","/**\n * Resolve the schema *set* for a single file by precedence:\n * 1. CLI --schema overrides (apply to all files)\n * 2. $schema in the file's metadata (string or list)\n * 3. first matching config override (by glob)\n * 4. config default schemas\n * 5. built-in default (google:okf:0.1)\n */\nimport picomatch from \"picomatch\";\nimport type { DocmetaConfig } from \"./config.js\";\n\nexport const DEFAULT_SCHEMA = \"google:okf:0.1\";\nexport const FILE_SCHEMA_KEY = \"$schema\";\n\nexport interface ResolveParams {\n /** File path (relative is fine) used for override glob matching. */\n filePath: string;\n /** `$schema` value pulled from the file's metadata. */\n fileSchema?: unknown;\n /** Repeatable `--schema` values; non-empty means override. */\n cliSchemas?: string[];\n /** Loaded config, if any. */\n config?: DocmetaConfig | null;\n}\n\nconst matcherCache = new Map<string, (p: string) => boolean>();\nfunction matches(glob: string, filePath: string): boolean {\n let m = matcherCache.get(glob);\n if (!m) {\n m = picomatch(glob, { dot: true });\n matcherCache.set(glob, m);\n }\n // Normalize Windows separators so globs written with `/` still match.\n return m(filePath.replace(/\\\\/g, \"/\"));\n}\n\nfunction coerceFileSchema(value: unknown): string[] | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return [value];\n if (Array.isArray(value) && value.every((v) => typeof v === \"string\")) {\n return value as string[];\n }\n throw new Error(\n `Invalid \"${FILE_SCHEMA_KEY}\": must be a string or a list of strings.`,\n );\n}\n\nfunction dedupe(refs: string[]): string[] {\n return [...new Set(refs)];\n}\n\nexport function resolveSchemaSet(params: ResolveParams): string[] {\n const { filePath, fileSchema, cliSchemas, config } = params;\n\n if (cliSchemas && cliSchemas.length > 0) return dedupe(cliSchemas);\n\n const fromFile = coerceFileSchema(fileSchema);\n if (fromFile && fromFile.length > 0) return dedupe(fromFile);\n\n if (config?.overrides) {\n for (const ov of config.overrides) {\n if (matches(ov.files, filePath) && ov.schemas.length > 0) {\n return dedupe(ov.schemas);\n }\n }\n }\n\n if (config?.schemas && config.schemas.length > 0) return dedupe(config.schemas);\n\n return [DEFAULT_SCHEMA];\n}\n","/**\n * Source of truth for schemas. Holds the built-in schemas (addressed by\n * `vendor:name:version` ids) and knows how to load any schema reference —\n * a built-in id, a local `.json` path, or an `http(s)` URL.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { DocmetaError } from \"../types.js\";\n\nimport okf01 from \"../schemas/okf/0.1.json\" with { type: \"json\" };\n\nexport interface BuiltinInfo {\n id: string;\n title: string;\n description: string;\n}\n\n/** Built-in schemas keyed by `vendor:name:version` id. */\nconst BUILTINS = new Map<string, Record<string, unknown>>([\n [\"google:okf:0.1\", okf01 as Record<string, unknown>],\n]);\n\nexport function listBuiltins(): BuiltinInfo[] {\n return [...BUILTINS.entries()].map(([id, schema]) => ({\n id,\n title: typeof schema.title === \"string\" ? schema.title : id,\n description:\n typeof schema.description === \"string\" ? schema.description : \"\",\n }));\n}\n\nexport type RefKind = \"builtin\" | \"file\" | \"url\";\n\n/**\n * A built-in id looks like `seg(:seg)+` using only [a-z0-9._-] segments, with\n * no path separators and not ending in `.json`. This deliberately excludes\n * Windows paths (`C:\\...`), URLs, and `.json` files so a typo'd built-in is\n * reported as an unknown id rather than silently treated as a missing file.\n */\nconst BUILTIN_ID = /^[a-z0-9][a-z0-9._-]*(?::[a-z0-9][a-z0-9._-]*)+$/i;\n\nexport function classifyRef(ref: string): { kind: RefKind; ref: string } {\n if (/^https?:\\/\\//i.test(ref)) return { kind: \"url\", ref };\n if (\n !ref.includes(\"/\") &&\n !ref.includes(\"\\\\\") &&\n !ref.toLowerCase().endsWith(\".json\") &&\n BUILTIN_ID.test(ref)\n ) {\n return { kind: \"builtin\", ref };\n }\n return { kind: \"file\", ref };\n}\n\nconst urlCache = new Map<string, Record<string, unknown>>();\n\n/** Default network timeout for fetching a remote (`http(s)`) schema. */\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface LoadSchemaOptions {\n /** Abort a remote fetch after this many ms (default 10_000). */\n timeoutMs?: number;\n}\n\n/** Load and return the JSON Schema object for a reference. */\nexport async function loadSchema(\n ref: string,\n options: LoadSchemaOptions = {},\n): Promise<Record<string, unknown>> {\n const { kind } = classifyRef(ref);\n\n if (kind === \"builtin\") {\n const schema = BUILTINS.get(ref);\n if (!schema) {\n const available = [...BUILTINS.keys()].join(\", \");\n throw new DocmetaError(\n `Unknown built-in schema \"${ref}\". Available: ${available || \"(none)\"}.`,\n );\n }\n return schema;\n }\n\n if (kind === \"url\") {\n const cached = urlCache.get(ref);\n if (cached) return cached;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n let res: Response;\n try {\n res = await fetch(ref, { signal: AbortSignal.timeout(timeoutMs) });\n } catch (err) {\n const e = err as Error;\n if (e.name === \"TimeoutError\" || e.name === \"AbortError\") {\n throw new DocmetaError(\n `Failed to fetch schema \"${ref}\": timed out after ${timeoutMs}ms.`,\n );\n }\n throw new DocmetaError(`Failed to fetch schema \"${ref}\": ${e.message}`);\n }\n if (!res.ok) {\n throw new DocmetaError(\n `Failed to fetch schema \"${ref}\": HTTP ${res.status}.`,\n );\n }\n let json: Record<string, unknown>;\n try {\n json = (await res.json()) as Record<string, unknown>;\n } catch (err) {\n throw new DocmetaError(\n `Schema \"${ref}\" did not return valid JSON: ${(err as Error).message}`,\n );\n }\n urlCache.set(ref, json);\n return json;\n }\n\n // file\n let raw: string;\n try {\n raw = await readFile(ref, \"utf8\");\n } catch {\n throw new DocmetaError(`Schema file not found: \"${ref}\".`);\n }\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n throw new DocmetaError(\n `Schema file \"${ref}\" is not valid JSON: ${(err as Error).message}`,\n );\n }\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"google:okf:0.1\",\n \"title\": \"Open Knowledge Format (OKF) v0.1\",\n \"description\": \"Frontmatter schema for OKF v0.1 concept files. OKF requires only `type`; all other fields are recommended, and unknown keys are explicitly tolerated. See https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md\",\n \"type\": \"object\",\n \"required\": [\"type\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"A short string identifying the kind of concept. Used for routing, filtering, and presentation.\"\n },\n \"title\": {\n \"type\": \"string\",\n \"description\": \"Human-readable display name. If omitted, consumers MAY derive a title from the filename.\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Single-sentence summary used for indexing and previews.\"\n },\n \"resource\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"description\": \"A URI uniquely identifying the underlying asset. Absent for abstract concepts.\"\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Short strings for categorization.\"\n },\n \"timestamp\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"description\": \"ISO 8601 datetime of last meaningful change.\"\n }\n }\n}\n","/**\n * JSON Schema validation engine. Compiles and caches an Ajv validator per\n * schema reference, validates extracted metadata against each schema in a set,\n * and maps every violation to a {schema, instancePath, line} FieldError.\n */\nimport * as AjvDraft07Ns from \"ajv\";\nimport * as Ajv2019Ns from \"ajv/dist/2019.js\";\nimport * as Ajv2020Ns from \"ajv/dist/2020.js\";\nimport * as AjvDraft04Ns from \"ajv-draft-04\";\nimport * as addFormatsNs from \"ajv-formats\";\nimport { createRequire } from \"node:module\";\nimport type { ErrorObject, ValidateFunction } from \"ajv/dist/2020.js\";\nimport { DocmetaError, type FieldError } from \"../types.js\";\n\n// ajv ships its meta-schema refs as JSON. A static JSON import survives\n// bundling as a bare ESM import without the required `type: json` attribute, so\n// load it through `require` instead (ajv is an external dep at runtime).\nconst draft06MetaSchema = createRequire(import.meta.url)(\n \"ajv/dist/refs/json-schema-draft-06.json\",\n) as Record<string, unknown>;\n\n// ajv and ajv-formats are CommonJS with a default export; under NodeNext the\n// callable/constructable value lives on `.default`. Cast through the named\n// default types so tsc sees a constructor / callable. The per-dialect builds\n// expose the same shape, so we treat them all as the 2020 constructor type.\ntype AjvCtor = typeof import(\"ajv/dist/2020.js\").default;\nconst AjvDraft07 = AjvDraft07Ns.default as unknown as AjvCtor;\nconst Ajv2019 = Ajv2019Ns.default as unknown as AjvCtor;\nconst Ajv2020 = Ajv2020Ns.default as unknown as AjvCtor;\nconst AjvDraft04 = AjvDraft04Ns.default as unknown as AjvCtor;\nconst addFormats =\n addFormatsNs.default as unknown as typeof import(\"ajv-formats\").default;\nimport { loadSchema } from \"./schema-registry.js\";\nimport { FILE_SCHEMA_KEY } from \"./resolve-schema.js\";\n\ntype Dialect = \"2020\" | \"2019\" | \"draft7\" | \"draft4\";\n\n/**\n * Pick a JSON Schema dialect from a schema's own `$schema` meta-schema URI.\n * Remote schemas commonly target draft-07/draft-04, which the 2020 build can't\n * compile, so each dialect gets its own Ajv. A missing or unrecognized\n * `$schema` falls back to 2020 (the dialect of the built-ins).\n */\nfunction dialectOf(schema: Record<string, unknown>): Dialect {\n const meta = typeof schema.$schema === \"string\" ? schema.$schema : \"\";\n if (meta.includes(\"2019-09\")) return \"2019\";\n // draft-06 shares the draft-07 build (its meta-schema is registered there).\n if (\n meta.includes(\"draft-07\") ||\n meta.includes(\"draft/7\") ||\n meta.includes(\"draft-06\") ||\n meta.includes(\"draft/6\")\n ) {\n return \"draft7\";\n }\n if (meta.includes(\"draft-04\") || meta.includes(\"draft/4\")) return \"draft4\";\n return \"2020\";\n}\n\nfunction buildAjv(dialect: Dialect): InstanceType<AjvCtor> {\n // strict: false so user-supplied schemas with lax metadata still compile.\n const opts = { allErrors: true, strict: false } as const;\n const ajv =\n dialect === \"2019\"\n ? new Ajv2019(opts)\n : dialect === \"draft7\"\n ? new AjvDraft07(opts)\n : dialect === \"draft4\"\n ? new AjvDraft04(opts)\n : new Ajv2020(opts);\n addFormats(ajv);\n // draft-06 shares the draft-07 build; register its meta-schema so draft-06\n // schemas compile too rather than erroring on an unknown `$schema`.\n if (dialect === \"draft7\") ajv.addMetaSchema(draft06MetaSchema);\n return ajv;\n}\n\nexport class Validator {\n private ajvByDialect = new Map<Dialect, InstanceType<AjvCtor>>();\n private cache = new Map<string, ValidateFunction>();\n\n private ajvFor(dialect: Dialect): InstanceType<AjvCtor> {\n let ajv = this.ajvByDialect.get(dialect);\n if (!ajv) {\n ajv = buildAjv(dialect);\n this.ajvByDialect.set(dialect, ajv);\n }\n return ajv;\n }\n\n private async compile(ref: string): Promise<ValidateFunction> {\n const cached = this.cache.get(ref);\n if (cached) return cached;\n const schema = await loadSchema(ref);\n let fn: ValidateFunction;\n try {\n fn = this.ajvFor(dialectOf(schema)).compile(schema);\n } catch (err) {\n throw new DocmetaError(\n `Schema \"${ref}\" failed to compile: ${(err as Error).message}`,\n );\n }\n this.cache.set(ref, fn);\n return fn;\n }\n\n /**\n * Validate `data` against every schema in `refs`. Returns all violations,\n * each tagged with the schema that produced it and a source line via\n * `lineFor`.\n */\n async validate(\n data: Record<string, unknown>,\n refs: string[],\n lineFor: (pointer: string) => number | undefined,\n ): Promise<FieldError[]> {\n // `$schema` is a docmeta directive, not part of the document's metadata —\n // strip it so schemas with additionalProperties:false don't flag it.\n const { [FILE_SCHEMA_KEY]: _omit, ...subject } = data;\n void _omit;\n\n const errors: FieldError[] = [];\n for (const ref of refs) {\n const fn = await this.compile(ref);\n const ok = fn(subject);\n if (ok) continue;\n for (const e of fn.errors ?? []) {\n errors.push(toFieldError(ref, e, lineFor));\n }\n }\n return errors;\n }\n}\n\nfunction toFieldError(\n schema: string,\n e: ErrorObject,\n lineFor: (pointer: string) => number | undefined,\n): FieldError {\n const instancePath = e.instancePath;\n // For `required`, point at the parent object but name the missing property.\n let message = e.message ?? \"is invalid\";\n if (e.keyword === \"required\" && e.params && \"missingProperty\" in e.params) {\n message = `must have required property '${String(e.params.missingProperty)}'`;\n } else if (\n e.keyword === \"additionalProperties\" &&\n e.params &&\n \"additionalProperty\" in e.params\n ) {\n message = `must NOT have additional property '${String(e.params.additionalProperty)}'`;\n }\n const line = lineFor(instancePath);\n return { schema, instancePath, message, ...(line != null ? { line } : {}) };\n}\n","/**\n * `validate` command core. Resolves targets, extracts metadata, resolves a\n * schema set per file, validates, and returns structured results. Kept free of\n * CLI/IO plumbing so it can be tested directly.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve, extname } from \"node:path\";\nimport {\n DocmetaError,\n type FieldError,\n type RunSummary,\n type ValidationResult,\n} from \"../types.js\";\nimport {\n extractorByName,\n extractorForExtension,\n supportedExtensions,\n} from \"../extractors/index.js\";\nimport { resolveTargets, STDIN_TOKEN } from \"../core/load-files.js\";\nimport { loadConfig, type DocmetaConfig } from \"../core/config.js\";\nimport { resolveSchemaSet, FILE_SCHEMA_KEY } from \"../core/resolve-schema.js\";\nimport { Validator } from \"../core/validator.js\";\n\nexport interface ValidateOptions {\n inputs: string[];\n cliSchemas?: string[];\n exts?: string[];\n exclude?: string[];\n /** `--as` format override (extractor name). */\n as?: string;\n configPath?: string;\n cwd?: string;\n /** Content for the `-` (stdin) input, injected by the CLI/tests. */\n stdinContent?: string;\n}\n\nexport interface ValidateRun {\n results: ValidationResult[];\n summary: RunSummary;\n}\n\nfunction parseErrorResult(\n file: string,\n format: string,\n message: string,\n): ValidationResult {\n const err: FieldError = { schema: \"(parse)\", instancePath: \"\", message };\n return { file, format, ok: false, schemas: [], errors: [err] };\n}\n\nexport async function runValidate(\n opts: ValidateOptions,\n): Promise<ValidateRun> {\n const cwd = opts.cwd ?? process.cwd();\n\n const loaded = await loadConfig(opts.configPath, cwd);\n const config: DocmetaConfig | null = loaded?.config ?? null;\n\n // Determine inputs: explicit CLI inputs win, else config.paths.\n const inputs =\n opts.inputs.length > 0 ? opts.inputs : (config?.paths ?? []);\n const usingStdin = inputs.includes(STDIN_TOKEN);\n\n if (inputs.length === 0) {\n throw new DocmetaError(\n \"No files to validate. Pass paths/globs, or add `paths:` to docmeta.config.yaml.\",\n );\n }\n\n // Pick an explicit extractor for `--as`, validating it up front.\n const forcedExtractor = opts.as ? extractorByName(opts.as) : undefined;\n if (opts.as && !forcedExtractor) {\n throw new DocmetaError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n\n const exts =\n opts.exts ?? (forcedExtractor ? forcedExtractor.extensions : undefined);\n\n const fileInputs = inputs.filter((i) => i !== STDIN_TOKEN);\n const files = await resolveTargets({\n inputs: fileInputs,\n exts,\n exclude: [...(config?.exclude ?? []), ...(opts.exclude ?? [])],\n cwd,\n });\n\n const validator = new Validator();\n const results: ValidationResult[] = [];\n\n const processOne = async (\n label: string,\n content: string,\n extension: string,\n ): Promise<void> => {\n const extractor =\n forcedExtractor ?? extractorForExtension(extension);\n if (!extractor) {\n throw new DocmetaError(\n `Unsupported file type \"${extension}\" for \"${label}\". Supported: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n );\n }\n\n let extracted;\n try {\n extracted = extractor.extract(content, label);\n } catch (err) {\n if (err instanceof DocmetaError) throw err; // operational (stub/unsupported)\n results.push(parseErrorResult(label, extractor.name, (err as Error).message));\n return;\n }\n\n let schemaSet: string[];\n try {\n schemaSet = resolveSchemaSet({\n filePath: label,\n fileSchema: extracted.data[FILE_SCHEMA_KEY],\n cliSchemas: opts.cliSchemas,\n config,\n });\n } catch (err) {\n results.push(parseErrorResult(label, extractor.name, (err as Error).message));\n return;\n }\n\n const errors = await validator.validate(\n extracted.data,\n schemaSet,\n extracted.lineFor,\n );\n results.push({\n file: label,\n format: extractor.name,\n ok: errors.length === 0,\n schemas: schemaSet,\n errors,\n });\n };\n\n if (usingStdin) {\n const content = opts.stdinContent ?? \"\";\n if (!forcedExtractor) {\n throw new DocmetaError(\n \"Reading from stdin (`-`) requires --as <format> to choose an extractor.\",\n );\n }\n await processOne(\"<stdin>\", content, forcedExtractor.extensions[0] ?? \"\");\n }\n\n for (const file of files) {\n const content = await readFile(resolve(cwd, file), \"utf8\");\n await processOne(file, content, extname(file));\n }\n\n const failed = results.filter((r) => !r.ok).length;\n const summary: RunSummary = {\n files: results.length,\n passed: results.length - failed,\n failed,\n errors: results.reduce((n, r) => n + r.errors.length, 0),\n };\n\n return { results, summary };\n}\n","/**\n * Markdown frontmatter extractor. Splits the leading YAML frontmatter block\n * ourselves (deterministic offsets) and parses it with the `yaml` AST + a\n * LineCounter to recover a JSON-Pointer -> source-line map for annotations.\n */\nimport { parseDocument, LineCounter, isMap, isSeq, isScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\nconst OPENING = /^---\\r?\\n/;\n\ninterface Block {\n /** Raw YAML between the delimiters (no leading/trailing newline). */\n raw: string;\n /** 1-based file line of the first YAML content line. */\n firstYamlLine: number;\n}\n\n/** Locate the leading `--- ... ---` frontmatter block, if any. */\nfunction splitFrontmatter(content: string): Block | null {\n // A BOM stays part of line 1; it doesn't shift line numbers.\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (!OPENING.test(body)) return null;\n\n const lines = body.split(/\\r?\\n/);\n let close = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i] === \"---\" || lines[i] === \"...\") {\n close = i;\n break;\n }\n }\n if (close === -1) return null;\n\n return { raw: lines.slice(1, close).join(\"\\n\"), firstYamlLine: 2 };\n}\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Build a JSON-Pointer -> 1-based file line map from a parsed YAML block. */\nfunction buildLineMap(\n doc: ReturnType<typeof parseDocument>,\n lc: LineCounter,\n prefixLines: number,\n): Map<string, number> {\n const map = new Map<string, number>();\n // Root pointer maps to the opening `---` line (block start).\n map.set(\"\", 1);\n\n const lineAt = (offset: number | undefined): number | undefined =>\n offset == null ? undefined : lc.linePos(offset).line + prefixLines;\n\n const walk = (node: unknown, pointer: string): void => {\n if (isMap(node)) {\n for (const pair of node.items) {\n const key = isScalar(pair.key)\n ? String(pair.key.value)\n : String(pair.key);\n const ptr = `${pointer}/${escapePointerSegment(key)}`;\n const line = lineAt(\n (pair.key as { range?: [number, number, number] })?.range?.[0],\n );\n if (line != null) map.set(ptr, line);\n if (pair.value) walk(pair.value, ptr);\n }\n } else if (isSeq(node)) {\n node.items.forEach((item, i) => {\n const ptr = `${pointer}/${i}`;\n const line = lineAt(\n (item as { range?: [number, number, number] })?.range?.[0],\n );\n if (line != null) map.set(ptr, line);\n walk(item, ptr);\n });\n }\n };\n\n if (doc.contents) walk(doc.contents, \"\");\n return map;\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/** Core frontmatter extraction shared by the markdown and mdx extractors. */\nexport function extractFrontmatter(\n content: string,\n format: string,\n): ExtractedMetadata {\n const block = splitFrontmatter(content);\n if (!block) {\n return { data: {}, present: false, format, lineFor: () => undefined };\n }\n\n const lc = new LineCounter();\n const doc = parseDocument(block.raw, { lineCounter: lc });\n if (doc.errors.length > 0) {\n const e = doc.errors[0];\n // Surface as a thrown error; the command layer records it as a per-file\n // failure so the rest of the run continues.\n throw new Error(`Invalid YAML frontmatter: ${e?.message ?? \"parse error\"}`);\n }\n\n const js = doc.toJS({ maxAliasCount: 100 }) as unknown;\n const data =\n js && typeof js === \"object\" && !Array.isArray(js)\n ? (js as Record<string, unknown>)\n : {};\n\n const map = buildLineMap(doc, lc, block.firstYamlLine - 1);\n return { data, present: true, format, lineFor: lineForFactory(map) };\n}\n\nexport const markdownExtractor: MetadataExtractor = {\n name: \"markdown\",\n extensions: [\".md\", \".markdown\"],\n implemented: true,\n extract: (content) => extractFrontmatter(content, \"markdown\"),\n};\n","/**\n * MDX extractor. MDX frontmatter is identical to Markdown's YAML block, so we\n * reuse the same logic. Parsing `export const meta = {...}` is future work.\n */\nimport { extractFrontmatter } from \"./markdown.js\";\nimport type { MetadataExtractor } from \"../types.js\";\n\nexport const mdxExtractor: MetadataExtractor = {\n name: \"mdx\",\n extensions: [\".mdx\"],\n implemented: true,\n extract: (content) => extractFrontmatter(content, \"mdx\"),\n};\n","/**\n * AsciiDoc metadata extractor.\n *\n * Two metadata styles are accepted:\n * 1. A leading YAML frontmatter block (`--- … ---`), as some static-site\n * generators use. This delegates to the shared `extractFrontmatter` so the\n * values are typed and the line map comes for free.\n * 2. The native AsciiDoc document header: the `= Title` line plus `:key: value`\n * attribute entries, running from the first line until the first blank line.\n * Attribute values are parsed as YAML scalars so `2` -> number, `true` ->\n * boolean, etc., consistent with frontmatter typing.\n */\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\nimport { extractFrontmatter } from \"./markdown.js\";\n\nconst OPENING = /^---\\r?\\n/;\nconst TITLE = /^=\\s+(.+?)\\s*$/;\n// `:!name:` or `:name!:` — an unset attribute.\nconst UNSET = /^:(?:!([^:\\s]+)|([^:\\s]+)!):\\s*$/;\n// `:name:` or `:name: value` — a set attribute (value optional).\nconst SET = /^:([^:\\s!][^:\\s]*):(?:\\s+(.*\\S))?\\s*$/;\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw attribute value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // A YAML-typed value can be an array/object, so Ajv may report nested\n // pointers like \"/tags/0\". Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/** Parse the native AsciiDoc document header (title + attribute entries). */\nfunction extractHeader(content: string): ExtractedMetadata {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const lines = body.split(/\\r?\\n/);\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n map.set(\"\", 1);\n\n const setKey = (key: string, value: unknown, line: number): void => {\n data[key] = value;\n map.set(`/${escapePointerSegment(key)}`, line);\n };\n\n for (const [i, line] of lines.entries()) {\n // The header ends at the first blank line.\n if (line.trim() === \"\") break;\n\n if (i === 0) {\n const title = TITLE.exec(line);\n if (title?.[1] != null) {\n setKey(\"title\", title[1], i + 1);\n continue;\n }\n }\n\n const unset = UNSET.exec(line);\n if (unset) {\n const name = unset[1] ?? unset[2];\n if (name != null) setKey(name, false, i + 1);\n continue;\n }\n\n const set = SET.exec(line);\n if (set?.[1] != null) {\n const value = set[2] === undefined ? true : typeValue(set[2]);\n setKey(set[1], value, i + 1);\n continue;\n }\n // Non-attribute header lines (e.g. author/revision) are ignored.\n }\n\n const present = Object.keys(data).length > 0;\n return {\n data,\n present,\n format: \"asciidoc\",\n lineFor: lineForFactory(map),\n };\n}\n\nexport const asciidocExtractor: MetadataExtractor = {\n name: \"asciidoc\",\n extensions: [\".adoc\", \".asciidoc\"],\n implemented: true,\n extract(content) {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (OPENING.test(body)) {\n // Delegate only when a complete frontmatter block is actually present;\n // a stray opening `---` with no closing delimiter should not shadow a\n // native AsciiDoc header that follows.\n const fm = extractFrontmatter(content, \"asciidoc\");\n if (fm.present) return fm;\n }\n return extractHeader(content);\n },\n};\n","/**\n * reStructuredText metadata extractor.\n *\n * Two metadata styles are accepted:\n * 1. A leading YAML frontmatter block (`--- … ---`), as some static-site\n * generators (e.g. MyST) use. This delegates to the shared\n * `extractFrontmatter` so the values are typed and the line map comes for\n * free.\n * 2. The native reStructuredText docinfo field list: the run of `:name: value`\n * entries at the top of the document, optionally preceded by a section\n * title (which we skip — only page-level metadata is extracted, not\n * headings). Field values are parsed as YAML scalars so `2` -> number,\n * `[a, b]` -> array, etc., consistent with frontmatter typing.\n */\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\nimport { extractFrontmatter } from \"./markdown.js\";\n\nconst OPENING = /^---\\r?\\n/;\n// `:name:` or `:name: value` — a docinfo field (value optional). The name may\n// contain spaces but not a colon; the value (if any) may.\nconst FIELD = /^:([^:]+):(?:\\s+(.*\\S))?\\s*$/;\n// A section-title adornment: a line of two or more identical punctuation chars.\nconst ADORN = /^([=\\-~:.'\"*+#_^<>])\\1+$/;\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw field value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // A YAML-typed value can be an array/object, so Ajv may report nested\n // pointers like \"/tags/0\". Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/**\n * Detect a leading section title — a text line underlined with punctuation,\n * optionally also overlined — after any blank lines. The title is collected as\n * page metadata; `next` is the index where docinfo field-list parsing resumes.\n */\ninterface TitleInfo {\n /** Title text, when a leading section title is present. */\n title?: string;\n /** 1-based source line of the title text. */\n line?: number;\n /** Index of the first line after the title (and its adornment lines). */\n next: number;\n}\n\n/** A run of identical title-adornment punctuation, or null for any other line. */\nfunction adornment(line: string): { char: string; length: number } | null {\n const m = ADORN.exec(line);\n return m && m[1] != null ? { char: m[1], length: line.length } : null;\n}\n\nfunction parseTitle(lines: string[]): TitleInfo {\n let i = 0;\n while (i < lines.length && (lines[i] ?? \"\").trim() === \"\") i++;\n if (i >= lines.length) return { next: i };\n\n const first = lines[i] ?? \"\";\n // A field line starts the docinfo block, not a title.\n if (FIELD.test(first)) return { next: i };\n\n const over = adornment(first);\n if (over) {\n // Over- and under-lined: adornment / title text / matching adornment. RST\n // requires the over- and underline to use the same character and length,\n // and to be at least as long as the title text.\n const text = lines[i + 1] ?? \"\";\n const under = adornment(lines[i + 2] ?? \"\");\n if (\n text.trim() !== \"\" &&\n !FIELD.test(text) &&\n under != null &&\n under.char === over.char &&\n under.length === over.length &&\n over.length >= text.trim().length\n ) {\n return { title: text.trim(), line: i + 2, next: i + 3 };\n }\n // A lone adornment that isn't a valid overlined title — not metadata.\n return { next: i };\n }\n\n // Underlined: title text / adornment at least as long as the title.\n const under = adornment(lines[i + 1] ?? \"\");\n if (under != null && under.length >= first.trim().length) {\n return { title: first.trim(), line: i + 1, next: i + 2 };\n }\n\n return { next: i };\n}\n\n/**\n * Parse the native reStructuredText page metadata: a leading section title\n * (collected as `title`) followed by the docinfo field list. An explicit\n * `:title:` field takes precedence over the heading.\n */\nfunction extractDocinfo(content: string): ExtractedMetadata {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const lines = body.split(/\\r?\\n/);\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n // First source line of the metadata block (title or, failing that, a field).\n let blockStart = -1;\n\n const titleInfo = parseTitle(lines);\n if (titleInfo.title != null && titleInfo.line != null) {\n data.title = titleInfo.title;\n map.set(\"/title\", titleInfo.line);\n blockStart = titleInfo.line;\n }\n\n // Skip blank lines between the title and the field list.\n let i = titleInfo.next;\n while (i < lines.length && (lines[i] ?? \"\").trim() === \"\") i++;\n\n for (; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n // The field list ends at the first blank or non-field line.\n if (line.trim() === \"\") break;\n const field = FIELD.exec(line);\n if (!field || field[1] == null) break;\n\n const name = field[1].trim();\n const value = field[2] === undefined ? true : typeValue(field[2]);\n if (blockStart === -1) blockStart = i + 1;\n data[name] = value;\n map.set(`/${escapePointerSegment(name)}`, i + 1);\n }\n\n const present = blockStart !== -1;\n // Root pointer maps to the block start. When no metadata is present we record\n // nothing, so `lineFor` reports unknown rather than misleadingly annotating\n // missing-metadata errors at line 1.\n if (present) map.set(\"\", blockStart);\n\n return {\n data,\n present,\n format: \"rst\",\n lineFor: lineForFactory(map),\n };\n}\n\nexport const rstExtractor: MetadataExtractor = {\n name: \"rst\",\n extensions: [\".rst\"],\n implemented: true,\n extract(content) {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (OPENING.test(body)) {\n // Delegate only when a complete frontmatter block is actually present;\n // a stray opening `---` with no closing delimiter should not shadow a\n // native docinfo field list that follows.\n const fm = extractFrontmatter(content, \"rst\");\n if (fm.present) return fm;\n }\n return extractDocinfo(content);\n },\n};\n","/**\n * XML metadata extractor.\n *\n * Reads metadata from the document's root-element attributes, e.g.\n * `<document type=\"concept\" version=\"2\">` yields `{ type: \"concept\", version: 2 }`.\n * Attribute values are parsed as YAML scalars so `\"2\"` -> number and `\"true\"` ->\n * boolean, consistent with the AsciiDoc header extractor. Namespace declarations\n * (`xmlns`, `xmlns:*`) are dropped as transport noise. Per-node line numbers from\n * the parser give a JSON-Pointer -> source-line map for precise annotations.\n *\n * Malformed XML is surfaced as a thrown error; the command layer records it as a\n * per-file failure so the rest of the run continues (mirroring frontmatter).\n */\nimport { DOMParser } from \"@xmldom/xmldom\";\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw attribute value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n // An explicitly empty attribute (`title=\"\"`) is the empty string, not the\n // YAML `null` that parsing \"\" would yield.\n if (raw === \"\") return \"\";\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor (e.g. a nested Ajv pointer).\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\nexport const xmlExtractor: MetadataExtractor = {\n name: \"xml\",\n extensions: [\".xml\"],\n implemented: true,\n extract(content): ExtractedMetadata {\n // A BOM stays part of line 1; it doesn't shift line numbers.\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n\n const errors: string[] = [];\n const doc = new DOMParser({\n onError: (level, msg) => {\n if (level === \"error\" || level === \"fatalError\") errors.push(msg);\n },\n }).parseFromString(body, \"text/xml\");\n\n if (errors.length > 0) {\n throw new Error(`Invalid XML: ${errors[0] ?? \"parse error\"}`);\n }\n\n const root = doc.documentElement;\n if (!root) {\n return { data: {}, present: false, format: \"xml\", lineFor: () => undefined };\n }\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n const rootLine = root.lineNumber ?? 1;\n map.set(\"\", rootLine);\n\n const attrs = root.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const attr = attrs.item(i);\n if (!attr) continue;\n const name = attr.name;\n // Namespace declarations describe the document, not its metadata.\n if (name === \"xmlns\" || name.startsWith(\"xmlns:\")) continue;\n data[name] = typeValue(attr.value);\n map.set(`/${escapePointerSegment(name)}`, attr.lineNumber ?? rootLine);\n }\n\n const present = Object.keys(data).length > 0;\n return { data, present, format: \"xml\", lineFor: lineForFactory(map) };\n },\n};\n","/**\n * HTML metadata extractor.\n *\n * Reads document metadata from `<meta>` tags and `<title>`:\n * - `<title>…</title>` -> `title` (the text content, kept verbatim).\n * - `<meta name=\"X\" content=\"Y\">` (or `property=\"X\"` for OpenGraph-style tags)\n * -> `X: Y`. `content` values are parsed as YAML scalars so `\"2\"` -> number\n * and `\"true\"` -> boolean, consistent with the AsciiDoc/XML extractors.\n *\n * Tags with neither `name` nor `property` (e.g. `charset`, `http-equiv`) carry no\n * document metadata and are skipped. Duplicate keys: last tag wins; the first\n * `<title>` wins. The parser (parse5) decodes HTML entities and recovers from\n * malformed markup, so extraction never throws. Per-node line numbers give a\n * JSON-Pointer -> source-line map for annotations.\n */\nimport { parse, defaultTreeAdapter, type DefaultTreeAdapterMap } from \"parse5\";\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\ntype ChildNode = DefaultTreeAdapterMap[\"childNode\"];\ntype Element = DefaultTreeAdapterMap[\"element\"];\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n // Empty meta content (`content=\"\"`) is the empty string, not the YAML `null`\n // that parsing \"\" would yield.\n if (raw === \"\") return \"\";\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor (e.g. a nested Ajv pointer).\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\nfunction attrValue(el: Element, name: string): string | undefined {\n return el.attrs.find((a) => a.name === name)?.value;\n}\n\nexport const htmlExtractor: MetadataExtractor = {\n name: \"html\",\n extensions: [\".html\", \".htm\"],\n implemented: true,\n extract(content): ExtractedMetadata {\n const doc = parse(content, { sourceCodeLocationInfo: true });\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n // The document node has no location; anchor the root pointer at line 1.\n map.set(\"\", 1);\n\n const setKey = (key: string, value: unknown, line: number | undefined): void => {\n data[key] = value;\n if (line != null) map.set(`/${escapePointerSegment(key)}`, line);\n };\n\n const visit = (node: ChildNode): void => {\n if (defaultTreeAdapter.isElementNode(node)) {\n const line = node.sourceCodeLocation?.startLine;\n if (node.tagName === \"title\") {\n // The first <title> wins; later ones (e.g. in SVG) are ignored.\n if (data.title === undefined) {\n const first = node.childNodes[0];\n const text =\n first && defaultTreeAdapter.isTextNode(first) ? first.value : \"\";\n setKey(\"title\", text, line);\n }\n } else if (node.tagName === \"meta\") {\n const key = attrValue(node, \"name\") ?? attrValue(node, \"property\");\n const value = attrValue(node, \"content\");\n if (key != null && value != null) {\n setKey(key, typeValue(value), line);\n }\n }\n }\n if (defaultTreeAdapter.isElementNode(node)) {\n for (const child of node.childNodes) visit(child);\n }\n };\n\n for (const child of doc.childNodes) visit(child);\n\n const present = Object.keys(data).length > 0;\n return { data, present, format: \"html\", lineFor: lineForFactory(map) };\n },\n};\n","/**\n * Extractor registry. Maps file extensions to extractors and resolves an\n * extractor by name (for the `--as` override). Roadmap stubs are registered so\n * detection can report them clearly, but only implemented extractors count as\n * \"supported\" for directory walks.\n */\nimport type { MetadataExtractor } from \"../types.js\";\nimport { markdownExtractor } from \"./markdown.js\";\nimport { mdxExtractor } from \"./mdx.js\";\nimport { asciidocExtractor } from \"./asciidoc.js\";\nimport { rstExtractor } from \"./rst.js\";\nimport { xmlExtractor } from \"./xml.js\";\nimport { htmlExtractor } from \"./html.js\";\n\nexport const EXTRACTORS: MetadataExtractor[] = [\n markdownExtractor,\n mdxExtractor,\n asciidocExtractor,\n rstExtractor,\n xmlExtractor,\n htmlExtractor,\n];\n\nconst byExtension = new Map<string, MetadataExtractor>();\nconst byName = new Map<string, MetadataExtractor>();\nfor (const ex of EXTRACTORS) {\n byName.set(ex.name, ex);\n for (const ext of ex.extensions) byExtension.set(ext.toLowerCase(), ex);\n}\n\n/** Resolve an implemented extractor for a file extension (incl. dot). */\nexport function extractorForExtension(\n ext: string,\n): MetadataExtractor | undefined {\n const ex = byExtension.get(ext.toLowerCase());\n return ex?.implemented ? ex : undefined;\n}\n\n/** Resolve an extractor by its `--as` name (implemented or not). */\nexport function extractorByName(name: string): MetadataExtractor | undefined {\n return byName.get(name.toLowerCase());\n}\n\n/** Extensions handled by implemented extractors (used for directory walks). */\nexport function supportedExtensions(): string[] {\n return EXTRACTORS.filter((e) => e.implemented).flatMap((e) => e.extensions);\n}\n\n/** All registered format names, with their implemented status. */\nexport function listFormats(): { name: string; extensions: string[]; implemented: boolean }[] {\n return EXTRACTORS.map((e) => ({\n name: e.name,\n extensions: e.extensions,\n implemented: e.implemented,\n }));\n}\n","/**\n * Resolve a mix of explicit files, directories, and globs into a concrete,\n * de-duplicated, sorted list of file paths (posix-style, relative to cwd).\n * Directory and glob expansion is restricted to the given extensions; explicit\n * file arguments are always included so the user can target any single file.\n */\nimport { stat } from \"node:fs/promises\";\nimport { extname, relative, resolve } from \"node:path\";\nimport fg from \"fast-glob\";\nimport { supportedExtensions } from \"../extractors/index.js\";\n\nconst DEFAULT_IGNORE = [\"**/node_modules/**\", \"**/.git/**\"];\n\nexport const STDIN_TOKEN = \"-\";\n\nfunction toPosix(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\nasync function statOrNull(p: string) {\n try {\n return await stat(p);\n } catch {\n return null;\n }\n}\n\nexport interface ResolveOptions {\n /** Positional inputs: files, directories, or globs. `-` is ignored here. */\n inputs: string[];\n /** Extensions to keep during dir/glob expansion (default: supported). */\n exts?: string[];\n /** Extra exclude globs (added to node_modules/.git defaults). */\n exclude?: string[];\n cwd?: string;\n}\n\nexport async function resolveTargets(opts: ResolveOptions): Promise<string[]> {\n const cwd = opts.cwd ?? process.cwd();\n const exts = (opts.exts ?? supportedExtensions()).map((e) =>\n e.toLowerCase().startsWith(\".\") ? e.toLowerCase() : `.${e.toLowerCase()}`,\n );\n const ignore = [...DEFAULT_IGNORE, ...(opts.exclude ?? [])];\n const out = new Set<string>();\n\n const keepByExt = (file: string): boolean =>\n exts.includes(extname(file).toLowerCase());\n\n for (const input of opts.inputs) {\n if (input === STDIN_TOKEN) continue;\n\n const abs = resolve(cwd, input);\n const st = await statOrNull(abs);\n\n if (st?.isFile()) {\n out.add(toPosix(relative(cwd, abs)));\n continue;\n }\n\n if (st?.isDirectory()) {\n const found = await fg(`${toPosix(input)}/**/*`, {\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n });\n for (const f of found) if (keepByExt(f)) out.add(f);\n continue;\n }\n\n // Treat as a glob pattern.\n const found = await fg(toPosix(input), {\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n });\n for (const f of found) if (keepByExt(f)) out.add(f);\n }\n\n return [...out].sort();\n}\n","/**\n * `get` command core. Prints one or more metadata field values from each file.\n * Input handling (positional paths, globs, directories, `-` for stdin, and\n * config `paths:` fallback) mirrors `validate` so the two commands behave\n * identically.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve, extname } from \"node:path\";\nimport { DocmetaError } from \"../types.js\";\nimport {\n extractorByName,\n extractorForExtension,\n supportedExtensions,\n} from \"../extractors/index.js\";\nimport { resolveTargets, STDIN_TOKEN } from \"../core/load-files.js\";\nimport { loadConfig, type DocmetaConfig } from \"../core/config.js\";\n\nexport interface GetOptions {\n fields: string[];\n inputs: string[];\n as?: string;\n exclude?: string[];\n exts?: string[];\n configPath?: string;\n cwd?: string;\n /** Content for the `-` (stdin) input, injected by the CLI/tests. */\n stdinContent?: string;\n}\n\nexport interface GetFileResult {\n file: string;\n present: boolean;\n values: Record<string, unknown>;\n}\n\nexport async function runGet(opts: GetOptions): Promise<GetFileResult[]> {\n const cwd = opts.cwd ?? process.cwd();\n if (opts.fields.length === 0) {\n throw new DocmetaError(\"Specify at least one field to get.\");\n }\n\n const loaded = await loadConfig(opts.configPath, cwd);\n const config: DocmetaConfig | null = loaded?.config ?? null;\n\n // Determine inputs: explicit CLI inputs win, else config.paths.\n const inputs = opts.inputs.length > 0 ? opts.inputs : (config?.paths ?? []);\n const usingStdin = inputs.includes(STDIN_TOKEN);\n\n if (inputs.length === 0) {\n throw new DocmetaError(\n \"No files to read. Pass paths/globs, or add `paths:` to docmeta.config.yaml.\",\n );\n }\n\n const forced = opts.as ? extractorByName(opts.as) : undefined;\n if (opts.as && !forced) {\n throw new DocmetaError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n\n const exts = opts.exts ?? (forced ? forced.extensions : undefined);\n const fileInputs = inputs.filter((i) => i !== STDIN_TOKEN);\n const files = await resolveTargets({\n inputs: fileInputs,\n exts,\n exclude: [...(config?.exclude ?? []), ...(opts.exclude ?? [])],\n cwd,\n });\n\n const out: GetFileResult[] = [];\n\n const readOne = (label: string, content: string, extension: string): void => {\n const extractor = forced ?? extractorForExtension(extension);\n if (!extractor) {\n throw new DocmetaError(\n `Unsupported file type \"${extension}\" for \"${label}\". Supported: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n );\n }\n const extracted = extractor.extract(content, label);\n const values: Record<string, unknown> = {};\n for (const f of opts.fields) values[f] = extracted.data[f];\n out.push({ file: label, present: extracted.present, values });\n };\n\n if (usingStdin) {\n if (!forced) {\n throw new DocmetaError(\n \"Reading from stdin (`-`) requires --as <format> to choose an extractor.\",\n );\n }\n readOne(\"<stdin>\", opts.stdinContent ?? \"\", forced.extensions[0] ?? \"\");\n }\n\n for (const file of files) {\n const content = await readFile(resolve(cwd, file), \"utf8\");\n readOne(file, content, extname(file));\n }\n\n return out;\n}\n","/**\n * `schemas` command core. Reports built-in schemas and supported input formats.\n */\nimport { listBuiltins, type BuiltinInfo } from \"../core/schema-registry.js\";\nimport { listFormats } from \"../extractors/index.js\";\n\nexport interface SchemasInfo {\n builtins: BuiltinInfo[];\n formats: { name: string; extensions: string[]; implemented: boolean }[];\n}\n\nexport function getSchemasInfo(): SchemasInfo {\n return { builtins: listBuiltins(), formats: listFormats() };\n}\n","import pc from \"picocolors\";\n\nexport type Colors = ReturnType<typeof pc.createColors>;\n\n/** Build a picocolors palette with color explicitly on or off. */\nexport function palette(enabled: boolean): Colors {\n return pc.createColors(enabled);\n}\n\n/**\n * Decide whether to emit ANSI color: off when `--no-color`/`NO_COLOR`, on only\n * for a TTY otherwise. `forced` (from `--color`) overrides detection.\n */\nexport function shouldColor(opts: {\n noColor?: boolean;\n isTTY?: boolean;\n env?: NodeJS.ProcessEnv;\n}): boolean {\n const env = opts.env ?? process.env;\n if (opts.noColor) return false;\n if (env.NO_COLOR != null && env.NO_COLOR !== \"\") return false;\n return Boolean(opts.isTTY);\n}\n","/**\n * Reporters render validation results to a string. The command layer writes\n * the result to stdout; diagnostics go to stderr separately.\n */\nimport type { RunSummary, ValidationResult } from \"../types.js\";\nimport { palette } from \"./color.js\";\n\nexport type ReportFormat = \"pretty\" | \"json\" | \"github\";\n\nexport interface ReportOptions {\n color?: boolean;\n /** In pretty output, omit passing files. */\n quiet?: boolean;\n}\n\nfunction fieldLabel(instancePath: string): string {\n return instancePath === \"\" ? \"(root)\" : instancePath;\n}\n\nexport function renderPretty(\n results: ValidationResult[],\n summary: RunSummary,\n opts: ReportOptions = {},\n): string {\n const c = palette(opts.color ?? false);\n const lines: string[] = [];\n\n for (const r of results) {\n if (r.ok) {\n if (!opts.quiet) lines.push(`${c.green(\"✓\")} ${r.file}`);\n continue;\n }\n lines.push(`${c.red(\"✗\")} ${r.file}`);\n for (const e of r.errors) {\n const loc = e.line != null ? c.dim(` (line ${e.line})`) : \"\";\n lines.push(\n ` ${c.cyan(fieldLabel(e.instancePath))} ${e.message}${loc} ${c.dim(\n `[${e.schema}]`,\n )}`,\n );\n }\n }\n\n const summaryText = `${summary.files} file${summary.files === 1 ? \"\" : \"s\"} checked, ${summary.passed} passed, ${summary.failed} failed, ${summary.errors} error${summary.errors === 1 ? \"\" : \"s\"}`;\n if (lines.length > 0) lines.push(\"\");\n lines.push(summary.failed > 0 ? c.red(summaryText) : c.green(summaryText));\n return lines.join(\"\\n\");\n}\n\nexport function renderJson(\n results: ValidationResult[],\n summary: RunSummary,\n): string {\n return JSON.stringify({ summary, results }, null, 2);\n}\n\nexport function renderGithub(results: ValidationResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n for (const e of r.errors) {\n const params = [`file=${r.file}`];\n if (e.line != null) params.push(`line=${e.line}`);\n if (e.col != null) params.push(`col=${e.col}`);\n const msg = `[${e.schema}] ${fieldLabel(e.instancePath)} ${e.message}`;\n lines.push(`::error ${params.join(\",\")}::${msg}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\nexport function render(\n format: ReportFormat,\n results: ValidationResult[],\n summary: RunSummary,\n opts: ReportOptions = {},\n): string {\n switch (format) {\n case \"json\":\n return renderJson(results, summary);\n case \"github\":\n return renderGithub(results);\n case \"pretty\":\n default:\n return renderPretty(results, summary, opts);\n }\n}\n"],"mappings":";;;AA0EO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;;;AC1EA,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,SAAS,iBAAiB;AAenC,IAAM,eAAe,CAAC,uBAAuB,oBAAoB;AAEjE,SAAS,aAAa,OAAgB,OAAe,QAA0B;AAC7E,MAAI,CAAC,MAAM,QAAQ,KAAK,KAAK,MAAM,KAAK,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG;AACrE,UAAM,IAAI;AAAA,MACR,GAAG,MAAM,MAAM,KAAK;AAAA,IACtB;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,YAAY,MAAc,QAA+B;AACvE,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,IAAI;AAAA,EACtB,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,GAAG,MAAM,mBAAoB,IAAc,OAAO;AAAA,IACpD;AAAA,EACF;AACA,MAAI,OAAO,KAAM,QAAO,CAAC;AACzB,MAAI,OAAO,QAAQ,YAAY,MAAM,QAAQ,GAAG,GAAG;AACjD,UAAM,IAAI,aAAa,GAAG,MAAM,gCAAgC;AAAA,EAClE;AACA,QAAM,MAAM;AACZ,QAAM,SAAwB,CAAC;AAE/B,MAAI,IAAI,UAAU,OAAW,QAAO,QAAQ,aAAa,IAAI,OAAO,SAAS,MAAM;AACnF,MAAI,IAAI,YAAY;AAClB,WAAO,UAAU,aAAa,IAAI,SAAS,WAAW,MAAM;AAC9D,MAAI,IAAI,YAAY;AAClB,WAAO,UAAU,aAAa,IAAI,SAAS,WAAW,MAAM;AAE9D,MAAI,IAAI,cAAc,QAAW;AAC/B,QAAI,CAAC,MAAM,QAAQ,IAAI,SAAS,GAAG;AACjC,YAAM,IAAI,aAAa,GAAG,MAAM,+BAA+B;AAAA,IACjE;AACA,WAAO,YAAY,IAAI,UAAU,IAAI,CAAC,OAAO,MAAM;AACjD,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,cAAM,IAAI,aAAa,GAAG,MAAM,eAAe,CAAC,sBAAsB;AAAA,MACxE;AACA,YAAM,IAAI;AACV,UAAI,OAAO,EAAE,UAAU,UAAU;AAC/B,cAAM,IAAI;AAAA,UACR,GAAG,MAAM,eAAe,CAAC;AAAA,QAC3B;AAAA,MACF;AACA,aAAO;AAAA,QACL,OAAO,EAAE;AAAA,QACT,SAAS,aAAa,EAAE,SAAS,aAAa,CAAC,aAAa,MAAM;AAAA,MACpE;AAAA,IACF,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAMA,eAAsB,WACpB,cACA,MAAc,QAAQ,IAAI,GAC+B;AACzD,MAAI,cAAc;AAChB,QAAI;AACJ,QAAI;AACF,aAAO,MAAM,SAAS,cAAc,MAAM;AAAA,IAC5C,QAAQ;AACN,YAAM,IAAI,aAAa,2BAA2B,YAAY,IAAI;AAAA,IACpE;AACA,WAAO,EAAE,QAAQ,YAAY,MAAM,YAAY,GAAG,MAAM,aAAa;AAAA,EACvE;AAEA,aAAW,QAAQ,cAAc;AAC/B,UAAM,IAAI,QAAQ,KAAK,IAAI;AAC3B,QAAI;AACF,YAAM,OAAO,MAAM,SAAS,GAAG,MAAM;AACrC,aAAO,EAAE,QAAQ,YAAY,MAAM,IAAI,GAAG,MAAM,EAAE;AAAA,IACpD,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;;;ACpGA,OAAO,eAAe;AAGf,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAa/B,IAAM,eAAe,oBAAI,IAAoC;AAC7D,SAAS,QAAQ,MAAc,UAA2B;AACxD,MAAI,IAAI,aAAa,IAAI,IAAI;AAC7B,MAAI,CAAC,GAAG;AACN,QAAI,UAAU,MAAM,EAAE,KAAK,KAAK,CAAC;AACjC,iBAAa,IAAI,MAAM,CAAC;AAAA,EAC1B;AAEA,SAAO,EAAE,SAAS,QAAQ,OAAO,GAAG,CAAC;AACvC;AAEA,SAAS,iBAAiB,OAAsC;AAC9D,MAAI,UAAU,UAAa,UAAU,KAAM,QAAO;AAClD,MAAI,OAAO,UAAU,SAAU,QAAO,CAAC,KAAK;AAC5C,MAAI,MAAM,QAAQ,KAAK,KAAK,MAAM,MAAM,CAAC,MAAM,OAAO,MAAM,QAAQ,GAAG;AACrE,WAAO;AAAA,EACT;AACA,QAAM,IAAI;AAAA,IACR,YAAY,eAAe;AAAA,EAC7B;AACF;AAEA,SAAS,OAAO,MAA0B;AACxC,SAAO,CAAC,GAAG,IAAI,IAAI,IAAI,CAAC;AAC1B;AAEO,SAAS,iBAAiB,QAAiC;AAChE,QAAM,EAAE,UAAU,YAAY,YAAY,OAAO,IAAI;AAErD,MAAI,cAAc,WAAW,SAAS,EAAG,QAAO,OAAO,UAAU;AAEjE,QAAM,WAAW,iBAAiB,UAAU;AAC5C,MAAI,YAAY,SAAS,SAAS,EAAG,QAAO,OAAO,QAAQ;AAE3D,MAAI,QAAQ,WAAW;AACrB,eAAW,MAAM,OAAO,WAAW;AACjC,UAAI,QAAQ,GAAG,OAAO,QAAQ,KAAK,GAAG,QAAQ,SAAS,GAAG;AACxD,eAAO,OAAO,GAAG,OAAO;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,WAAW,OAAO,QAAQ,SAAS,EAAG,QAAO,OAAO,OAAO,OAAO;AAE9E,SAAO,CAAC,cAAc;AACxB;;;ACjEA,SAAS,YAAAA,iBAAgB;;;ACLzB;AAAA,EACE,SAAW;AAAA,EACX,KAAO;AAAA,EACP,OAAS;AAAA,EACT,aAAe;AAAA,EACf,MAAQ;AAAA,EACR,UAAY,CAAC,MAAM;AAAA,EACnB,sBAAwB;AAAA,EACxB,YAAc;AAAA,IACZ,MAAQ;AAAA,MACN,MAAQ;AAAA,MACR,WAAa;AAAA,MACb,aAAe;AAAA,IACjB;AAAA,IACA,OAAS;AAAA,MACP,MAAQ;AAAA,MACR,aAAe;AAAA,IACjB;AAAA,IACA,aAAe;AAAA,MACb,MAAQ;AAAA,MACR,aAAe;AAAA,IACjB;AAAA,IACA,UAAY;AAAA,MACV,MAAQ;AAAA,MACR,QAAU;AAAA,MACV,aAAe;AAAA,IACjB;AAAA,IACA,MAAQ;AAAA,MACN,MAAQ;AAAA,MACR,OAAS,EAAE,MAAQ,SAAS;AAAA,MAC5B,aAAe;AAAA,IACjB;AAAA,IACA,WAAa;AAAA,MACX,MAAQ;AAAA,MACR,QAAU;AAAA,MACV,aAAe;AAAA,IACjB;AAAA,EACF;AACF;;;ADrBA,IAAM,WAAW,oBAAI,IAAqC;AAAA,EACxD,CAAC,kBAAkB,SAAgC;AACrD,CAAC;AAEM,SAAS,eAA8B;AAC5C,SAAO,CAAC,GAAG,SAAS,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,MAAM,OAAO;AAAA,IACpD;AAAA,IACA,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,IACzD,aACE,OAAO,OAAO,gBAAgB,WAAW,OAAO,cAAc;AAAA,EAClE,EAAE;AACJ;AAUA,IAAM,aAAa;AAEZ,SAAS,YAAY,KAA6C;AACvE,MAAI,gBAAgB,KAAK,GAAG,EAAG,QAAO,EAAE,MAAM,OAAO,IAAI;AACzD,MACE,CAAC,IAAI,SAAS,GAAG,KACjB,CAAC,IAAI,SAAS,IAAI,KAClB,CAAC,IAAI,YAAY,EAAE,SAAS,OAAO,KACnC,WAAW,KAAK,GAAG,GACnB;AACA,WAAO,EAAE,MAAM,WAAW,IAAI;AAAA,EAChC;AACA,SAAO,EAAE,MAAM,QAAQ,IAAI;AAC7B;AAEA,IAAM,WAAW,oBAAI,IAAqC;AAG1D,IAAM,qBAAqB;AAQ3B,eAAsB,WACpB,KACA,UAA6B,CAAC,GACI;AAClC,QAAM,EAAE,KAAK,IAAI,YAAY,GAAG;AAEhC,MAAI,SAAS,WAAW;AACtB,UAAM,SAAS,SAAS,IAAI,GAAG;AAC/B,QAAI,CAAC,QAAQ;AACX,YAAM,YAAY,CAAC,GAAG,SAAS,KAAK,CAAC,EAAE,KAAK,IAAI;AAChD,YAAM,IAAI;AAAA,QACR,4BAA4B,GAAG,iBAAiB,aAAa,QAAQ;AAAA,MACvE;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,MAAI,SAAS,OAAO;AAClB,UAAM,SAAS,SAAS,IAAI,GAAG;AAC/B,QAAI,OAAQ,QAAO;AACnB,UAAM,YAAY,QAAQ,aAAa;AACvC,QAAI;AACJ,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,EAAE,QAAQ,YAAY,QAAQ,SAAS,EAAE,CAAC;AAAA,IACnE,SAAS,KAAK;AACZ,YAAM,IAAI;AACV,UAAI,EAAE,SAAS,kBAAkB,EAAE,SAAS,cAAc;AACxD,cAAM,IAAI;AAAA,UACR,2BAA2B,GAAG,sBAAsB,SAAS;AAAA,QAC/D;AAAA,MACF;AACA,YAAM,IAAI,aAAa,2BAA2B,GAAG,MAAM,EAAE,OAAO,EAAE;AAAA,IACxE;AACA,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI;AAAA,QACR,2BAA2B,GAAG,WAAW,IAAI,MAAM;AAAA,MACrD;AAAA,IACF;AACA,QAAI;AACJ,QAAI;AACF,aAAQ,MAAM,IAAI,KAAK;AAAA,IACzB,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,WAAW,GAAG,gCAAiC,IAAc,OAAO;AAAA,MACtE;AAAA,IACF;AACA,aAAS,IAAI,KAAK,IAAI;AACtB,WAAO;AAAA,EACT;AAGA,MAAI;AACJ,MAAI;AACF,UAAM,MAAMC,UAAS,KAAK,MAAM;AAAA,EAClC,QAAQ;AACN,UAAM,IAAI,aAAa,2BAA2B,GAAG,IAAI;AAAA,EAC3D;AACA,MAAI;AACF,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,gBAAgB,GAAG,wBAAyB,IAAc,OAAO;AAAA,IACnE;AAAA,EACF;AACF;;;AE3HA,YAAY,kBAAkB;AAC9B,YAAY,eAAe;AAC3B,YAAY,eAAe;AAC3B,YAAY,kBAAkB;AAC9B,YAAY,kBAAkB;AAC9B,SAAS,qBAAqB;AAO9B,IAAM,oBAAoB,cAAc,YAAY,GAAG;AAAA,EACrD;AACF;AAOA,IAAM,aAA0B;AAChC,IAAM,UAAoB;AAC1B,IAAM,UAAoB;AAC1B,IAAM,aAA0B;AAChC,IAAM,aACS;AAYf,SAAS,UAAU,QAA0C;AAC3D,QAAM,OAAO,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AACnE,MAAI,KAAK,SAAS,SAAS,EAAG,QAAO;AAErC,MACE,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,SAAS,KACvB,KAAK,SAAS,UAAU,KACxB,KAAK,SAAS,SAAS,GACvB;AACA,WAAO;AAAA,EACT;AACA,MAAI,KAAK,SAAS,UAAU,KAAK,KAAK,SAAS,SAAS,EAAG,QAAO;AAClE,SAAO;AACT;AAEA,SAAS,SAAS,SAAyC;AAEzD,QAAM,OAAO,EAAE,WAAW,MAAM,QAAQ,MAAM;AAC9C,QAAM,MACJ,YAAY,SACR,IAAI,QAAQ,IAAI,IAChB,YAAY,WACV,IAAI,WAAW,IAAI,IACnB,YAAY,WACV,IAAI,WAAW,IAAI,IACnB,IAAI,QAAQ,IAAI;AAC1B,aAAW,GAAG;AAGd,MAAI,YAAY,SAAU,KAAI,cAAc,iBAAiB;AAC7D,SAAO;AACT;AAEO,IAAM,YAAN,MAAgB;AAAA,EACb,eAAe,oBAAI,IAAoC;AAAA,EACvD,QAAQ,oBAAI,IAA8B;AAAA,EAE1C,OAAO,SAAyC;AACtD,QAAI,MAAM,KAAK,aAAa,IAAI,OAAO;AACvC,QAAI,CAAC,KAAK;AACR,YAAM,SAAS,OAAO;AACtB,WAAK,aAAa,IAAI,SAAS,GAAG;AAAA,IACpC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,QAAQ,KAAwC;AAC5D,UAAM,SAAS,KAAK,MAAM,IAAI,GAAG;AACjC,QAAI,OAAQ,QAAO;AACnB,UAAM,SAAS,MAAM,WAAW,GAAG;AACnC,QAAI;AACJ,QAAI;AACF,WAAK,KAAK,OAAO,UAAU,MAAM,CAAC,EAAE,QAAQ,MAAM;AAAA,IACpD,SAAS,KAAK;AACZ,YAAM,IAAI;AAAA,QACR,WAAW,GAAG,wBAAyB,IAAc,OAAO;AAAA,MAC9D;AAAA,IACF;AACA,SAAK,MAAM,IAAI,KAAK,EAAE;AACtB,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,SACJ,MACA,MACA,SACuB;AAGvB,UAAM,EAAE,CAAC,eAAe,GAAG,OAAO,GAAG,QAAQ,IAAI;AACjD,SAAK;AAEL,UAAM,SAAuB,CAAC;AAC9B,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,MAAM,KAAK,QAAQ,GAAG;AACjC,YAAM,KAAK,GAAG,OAAO;AACrB,UAAI,GAAI;AACR,iBAAW,KAAK,GAAG,UAAU,CAAC,GAAG;AAC/B,eAAO,KAAK,aAAa,KAAK,GAAG,OAAO,CAAC;AAAA,MAC3C;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAEA,SAAS,aACP,QACA,GACA,SACY;AACZ,QAAM,eAAe,EAAE;AAEvB,MAAI,UAAU,EAAE,WAAW;AAC3B,MAAI,EAAE,YAAY,cAAc,EAAE,UAAU,qBAAqB,EAAE,QAAQ;AACzE,cAAU,gCAAgC,OAAO,EAAE,OAAO,eAAe,CAAC;AAAA,EAC5E,WACE,EAAE,YAAY,0BACd,EAAE,UACF,wBAAwB,EAAE,QAC1B;AACA,cAAU,sCAAsC,OAAO,EAAE,OAAO,kBAAkB,CAAC;AAAA,EACrF;AACA,QAAM,OAAO,QAAQ,YAAY;AACjC,SAAO,EAAE,QAAQ,cAAc,SAAS,GAAI,QAAQ,OAAO,EAAE,KAAK,IAAI,CAAC,EAAG;AAC5E;;;ACpJA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,WAAAC,UAAS,WAAAC,gBAAe;;;ACDjC,SAAS,eAAe,aAAa,OAAO,OAAO,gBAAgB;AAGnE,IAAM,UAAU;AAUhB,SAAS,iBAAiB,SAA+B;AAEvD,QAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AACnE,MAAI,CAAC,QAAQ,KAAK,IAAI,EAAG,QAAO;AAEhC,QAAM,QAAQ,KAAK,MAAM,OAAO;AAChC,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,MAAM,OAAO;AAC5C,cAAQ;AACR;AAAA,IACF;AAAA,EACF;AACA,MAAI,UAAU,GAAI,QAAO;AAEzB,SAAO,EAAE,KAAK,MAAM,MAAM,GAAG,KAAK,EAAE,KAAK,IAAI,GAAG,eAAe,EAAE;AACnE;AAEA,SAAS,qBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;AAGA,SAAS,aACP,KACA,IACA,aACqB;AACrB,QAAM,MAAM,oBAAI,IAAoB;AAEpC,MAAI,IAAI,IAAI,CAAC;AAEb,QAAM,SAAS,CAAC,WACd,UAAU,OAAO,SAAY,GAAG,QAAQ,MAAM,EAAE,OAAO;AAEzD,QAAM,OAAO,CAAC,MAAe,YAA0B;AACrD,QAAI,MAAM,IAAI,GAAG;AACf,iBAAW,QAAQ,KAAK,OAAO;AAC7B,cAAM,MAAM,SAAS,KAAK,GAAG,IACzB,OAAO,KAAK,IAAI,KAAK,IACrB,OAAO,KAAK,GAAG;AACnB,cAAM,MAAM,GAAG,OAAO,IAAI,qBAAqB,GAAG,CAAC;AACnD,cAAM,OAAO;AAAA,UACV,KAAK,KAA8C,QAAQ,CAAC;AAAA,QAC/D;AACA,YAAI,QAAQ,KAAM,KAAI,IAAI,KAAK,IAAI;AACnC,YAAI,KAAK,MAAO,MAAK,KAAK,OAAO,GAAG;AAAA,MACtC;AAAA,IACF,WAAW,MAAM,IAAI,GAAG;AACtB,WAAK,MAAM,QAAQ,CAAC,MAAM,MAAM;AAC9B,cAAM,MAAM,GAAG,OAAO,IAAI,CAAC;AAC3B,cAAM,OAAO;AAAA,UACV,MAA+C,QAAQ,CAAC;AAAA,QAC3D;AACA,YAAI,QAAQ,KAAM,KAAI,IAAI,KAAK,IAAI;AACnC,aAAK,MAAM,GAAG;AAAA,MAChB,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,IAAI,SAAU,MAAK,IAAI,UAAU,EAAE;AACvC,SAAO;AACT;AAEA,SAAS,eACP,KACyC;AACzC,SAAO,CAAC,YAAoB;AAE1B,UAAM,QACJ,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,IACrC,IAAI,qBAAqB,OAAO,CAAC,KACjC;AACN,QAAI,IAAI,IAAI,KAAK,EAAG,QAAO,IAAI,IAAI,KAAK;AAExC,QAAI,IAAI;AACR,WAAO,EAAE,SAAS,GAAG;AACnB,YAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,UAAI,MAAM,EAAG;AACb,UAAI,EAAE,MAAM,GAAG,GAAG;AAClB,UAAI,IAAI,IAAI,CAAC,EAAG,QAAO,IAAI,IAAI,CAAC;AAAA,IAClC;AACA,WAAO,IAAI,IAAI,EAAE;AAAA,EACnB;AACF;AAGO,SAAS,mBACd,SACA,QACmB;AACnB,QAAM,QAAQ,iBAAiB,OAAO;AACtC,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,MAAM,CAAC,GAAG,SAAS,OAAO,QAAQ,SAAS,MAAM,OAAU;AAAA,EACtE;AAEA,QAAM,KAAK,IAAI,YAAY;AAC3B,QAAM,MAAM,cAAc,MAAM,KAAK,EAAE,aAAa,GAAG,CAAC;AACxD,MAAI,IAAI,OAAO,SAAS,GAAG;AACzB,UAAM,IAAI,IAAI,OAAO,CAAC;AAGtB,UAAM,IAAI,MAAM,6BAA6B,GAAG,WAAW,aAAa,EAAE;AAAA,EAC5E;AAEA,QAAM,KAAK,IAAI,KAAK,EAAE,eAAe,IAAI,CAAC;AAC1C,QAAM,OACJ,MAAM,OAAO,OAAO,YAAY,CAAC,MAAM,QAAQ,EAAE,IAC5C,KACD,CAAC;AAEP,QAAM,MAAM,aAAa,KAAK,IAAI,MAAM,gBAAgB,CAAC;AACzD,SAAO,EAAE,MAAM,SAAS,MAAM,QAAQ,SAAS,eAAe,GAAG,EAAE;AACrE;AAEO,IAAM,oBAAuC;AAAA,EAClD,MAAM;AAAA,EACN,YAAY,CAAC,OAAO,WAAW;AAAA,EAC/B,aAAa;AAAA,EACb,SAAS,CAAC,YAAY,mBAAmB,SAAS,UAAU;AAC9D;;;ACnIO,IAAM,eAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,YAAY,CAAC,MAAM;AAAA,EACnB,aAAa;AAAA,EACb,SAAS,CAAC,YAAY,mBAAmB,SAAS,KAAK;AACzD;;;ACAA,SAAS,SAAS,uBAAuB;AAIzC,IAAMC,WAAU;AAChB,IAAM,QAAQ;AAEd,IAAM,QAAQ;AAEd,IAAM,MAAM;AAEZ,SAASC,sBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;AAGA,SAAS,UAAU,KAAsB;AACvC,MAAI;AACF,WAAO,gBAAgB,GAAG;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASC,gBACP,KACyC;AACzC,SAAO,CAAC,YAAoB;AAE1B,UAAM,QACJ,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,IACrC,IAAID,sBAAqB,OAAO,CAAC,KACjC;AACN,QAAI,IAAI,IAAI,KAAK,EAAG,QAAO,IAAI,IAAI,KAAK;AAGxC,QAAI,IAAI;AACR,WAAO,EAAE,SAAS,GAAG;AACnB,YAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,UAAI,MAAM,EAAG;AACb,UAAI,EAAE,MAAM,GAAG,GAAG;AAClB,UAAI,IAAI,IAAI,CAAC,EAAG,QAAO,IAAI,IAAI,CAAC;AAAA,IAClC;AACA,WAAO,IAAI,IAAI,EAAE;AAAA,EACnB;AACF;AAGA,SAAS,cAAc,SAAoC;AACzD,QAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AACnE,QAAM,QAAQ,KAAK,MAAM,OAAO;AAEhC,QAAM,OAAgC,CAAC;AACvC,QAAM,MAAM,oBAAI,IAAoB;AACpC,MAAI,IAAI,IAAI,CAAC;AAEb,QAAM,SAAS,CAAC,KAAa,OAAgB,SAAuB;AAClE,SAAK,GAAG,IAAI;AACZ,QAAI,IAAI,IAAIA,sBAAqB,GAAG,CAAC,IAAI,IAAI;AAAA,EAC/C;AAEA,aAAW,CAAC,GAAG,IAAI,KAAK,MAAM,QAAQ,GAAG;AAEvC,QAAI,KAAK,KAAK,MAAM,GAAI;AAExB,QAAI,MAAM,GAAG;AACX,YAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,UAAI,QAAQ,CAAC,KAAK,MAAM;AACtB,eAAO,SAAS,MAAM,CAAC,GAAG,IAAI,CAAC;AAC/B;AAAA,MACF;AAAA,IACF;AAEA,UAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,QAAI,OAAO;AACT,YAAM,OAAO,MAAM,CAAC,KAAK,MAAM,CAAC;AAChC,UAAI,QAAQ,KAAM,QAAO,MAAM,OAAO,IAAI,CAAC;AAC3C;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,KAAK,IAAI;AACzB,QAAI,MAAM,CAAC,KAAK,MAAM;AACpB,YAAM,QAAQ,IAAI,CAAC,MAAM,SAAY,OAAO,UAAU,IAAI,CAAC,CAAC;AAC5D,aAAO,IAAI,CAAC,GAAG,OAAO,IAAI,CAAC;AAC3B;AAAA,IACF;AAAA,EAEF;AAEA,QAAM,UAAU,OAAO,KAAK,IAAI,EAAE,SAAS;AAC3C,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,SAASC,gBAAe,GAAG;AAAA,EAC7B;AACF;AAEO,IAAM,oBAAuC;AAAA,EAClD,MAAM;AAAA,EACN,YAAY,CAAC,SAAS,WAAW;AAAA,EACjC,aAAa;AAAA,EACb,QAAQ,SAAS;AACf,UAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AACnE,QAAIF,SAAQ,KAAK,IAAI,GAAG;AAItB,YAAM,KAAK,mBAAmB,SAAS,UAAU;AACjD,UAAI,GAAG,QAAS,QAAO;AAAA,IACzB;AACA,WAAO,cAAc,OAAO;AAAA,EAC9B;AACF;;;AC/GA,SAAS,SAASG,wBAAuB;AAIzC,IAAMC,WAAU;AAGhB,IAAM,QAAQ;AAEd,IAAM,QAAQ;AAEd,SAASC,sBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;AAGA,SAASC,WAAU,KAAsB;AACvC,MAAI;AACF,WAAOC,iBAAgB,GAAG;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASC,gBACP,KACyC;AACzC,SAAO,CAAC,YAAoB;AAE1B,UAAM,QACJ,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,IACrC,IAAIH,sBAAqB,OAAO,CAAC,KACjC;AACN,QAAI,IAAI,IAAI,KAAK,EAAG,QAAO,IAAI,IAAI,KAAK;AAGxC,QAAI,IAAI;AACR,WAAO,EAAE,SAAS,GAAG;AACnB,YAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,UAAI,MAAM,EAAG;AACb,UAAI,EAAE,MAAM,GAAG,GAAG;AAClB,UAAI,IAAI,IAAI,CAAC,EAAG,QAAO,IAAI,IAAI,CAAC;AAAA,IAClC;AACA,WAAO,IAAI,IAAI,EAAE;AAAA,EACnB;AACF;AAiBA,SAAS,UAAU,MAAuD;AACxE,QAAM,IAAI,MAAM,KAAK,IAAI;AACzB,SAAO,KAAK,EAAE,CAAC,KAAK,OAAO,EAAE,MAAM,EAAE,CAAC,GAAG,QAAQ,KAAK,OAAO,IAAI;AACnE;AAEA,SAAS,WAAW,OAA4B;AAC9C,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,WAAW,MAAM,CAAC,KAAK,IAAI,KAAK,MAAM,GAAI;AAC3D,MAAI,KAAK,MAAM,OAAQ,QAAO,EAAE,MAAM,EAAE;AAExC,QAAM,QAAQ,MAAM,CAAC,KAAK;AAE1B,MAAI,MAAM,KAAK,KAAK,EAAG,QAAO,EAAE,MAAM,EAAE;AAExC,QAAM,OAAO,UAAU,KAAK;AAC5B,MAAI,MAAM;AAIR,UAAM,OAAO,MAAM,IAAI,CAAC,KAAK;AAC7B,UAAMI,SAAQ,UAAU,MAAM,IAAI,CAAC,KAAK,EAAE;AAC1C,QACE,KAAK,KAAK,MAAM,MAChB,CAAC,MAAM,KAAK,IAAI,KAChBA,UAAS,QACTA,OAAM,SAAS,KAAK,QACpBA,OAAM,WAAW,KAAK,UACtB,KAAK,UAAU,KAAK,KAAK,EAAE,QAC3B;AACA,aAAO,EAAE,OAAO,KAAK,KAAK,GAAG,MAAM,IAAI,GAAG,MAAM,IAAI,EAAE;AAAA,IACxD;AAEA,WAAO,EAAE,MAAM,EAAE;AAAA,EACnB;AAGA,QAAM,QAAQ,UAAU,MAAM,IAAI,CAAC,KAAK,EAAE;AAC1C,MAAI,SAAS,QAAQ,MAAM,UAAU,MAAM,KAAK,EAAE,QAAQ;AACxD,WAAO,EAAE,OAAO,MAAM,KAAK,GAAG,MAAM,IAAI,GAAG,MAAM,IAAI,EAAE;AAAA,EACzD;AAEA,SAAO,EAAE,MAAM,EAAE;AACnB;AAOA,SAAS,eAAe,SAAoC;AAC1D,QAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AACnE,QAAM,QAAQ,KAAK,MAAM,OAAO;AAEhC,QAAM,OAAgC,CAAC;AACvC,QAAM,MAAM,oBAAI,IAAoB;AAEpC,MAAI,aAAa;AAEjB,QAAM,YAAY,WAAW,KAAK;AAClC,MAAI,UAAU,SAAS,QAAQ,UAAU,QAAQ,MAAM;AACrD,SAAK,QAAQ,UAAU;AACvB,QAAI,IAAI,UAAU,UAAU,IAAI;AAChC,iBAAa,UAAU;AAAA,EACzB;AAGA,MAAI,IAAI,UAAU;AAClB,SAAO,IAAI,MAAM,WAAW,MAAM,CAAC,KAAK,IAAI,KAAK,MAAM,GAAI;AAE3D,SAAO,IAAI,MAAM,QAAQ,KAAK;AAC5B,UAAM,OAAO,MAAM,CAAC,KAAK;AAEzB,QAAI,KAAK,KAAK,MAAM,GAAI;AACxB,UAAM,QAAQ,MAAM,KAAK,IAAI;AAC7B,QAAI,CAAC,SAAS,MAAM,CAAC,KAAK,KAAM;AAEhC,UAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,UAAM,QAAQ,MAAM,CAAC,MAAM,SAAY,OAAOH,WAAU,MAAM,CAAC,CAAC;AAChE,QAAI,eAAe,GAAI,cAAa,IAAI;AACxC,SAAK,IAAI,IAAI;AACb,QAAI,IAAI,IAAID,sBAAqB,IAAI,CAAC,IAAI,IAAI,CAAC;AAAA,EACjD;AAEA,QAAM,UAAU,eAAe;AAI/B,MAAI,QAAS,KAAI,IAAI,IAAI,UAAU;AAEnC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,QAAQ;AAAA,IACR,SAASG,gBAAe,GAAG;AAAA,EAC7B;AACF;AAEO,IAAM,eAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,YAAY,CAAC,MAAM;AAAA,EACnB,aAAa;AAAA,EACb,QAAQ,SAAS;AACf,UAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AACnE,QAAIJ,SAAQ,KAAK,IAAI,GAAG;AAItB,YAAM,KAAK,mBAAmB,SAAS,KAAK;AAC5C,UAAI,GAAG,QAAS,QAAO;AAAA,IACzB;AACA,WAAO,eAAe,OAAO;AAAA,EAC/B;AACF;;;AC/KA,SAAS,iBAAiB;AAC1B,SAAS,SAASM,wBAAuB;AAGzC,SAASC,sBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;AAGA,SAASC,WAAU,KAAsB;AAGvC,MAAI,QAAQ,GAAI,QAAO;AACvB,MAAI;AACF,WAAOF,iBAAgB,GAAG;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASG,gBACP,KACyC;AACzC,SAAO,CAAC,YAAoB;AAE1B,UAAM,QACJ,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,IACrC,IAAIF,sBAAqB,OAAO,CAAC,KACjC;AACN,QAAI,IAAI,IAAI,KAAK,EAAG,QAAO,IAAI,IAAI,KAAK;AAExC,QAAI,IAAI;AACR,WAAO,EAAE,SAAS,GAAG;AACnB,YAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,UAAI,MAAM,EAAG;AACb,UAAI,EAAE,MAAM,GAAG,GAAG;AAClB,UAAI,IAAI,IAAI,CAAC,EAAG,QAAO,IAAI,IAAI,CAAC;AAAA,IAClC;AACA,WAAO,IAAI,IAAI,EAAE;AAAA,EACnB;AACF;AAEO,IAAM,eAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,YAAY,CAAC,MAAM;AAAA,EACnB,aAAa;AAAA,EACb,QAAQ,SAA4B;AAElC,UAAM,OAAO,QAAQ,WAAW,CAAC,MAAM,QAAS,QAAQ,MAAM,CAAC,IAAI;AAEnE,UAAM,SAAmB,CAAC;AAC1B,UAAM,MAAM,IAAI,UAAU;AAAA,MACxB,SAAS,CAAC,OAAO,QAAQ;AACvB,YAAI,UAAU,WAAW,UAAU,aAAc,QAAO,KAAK,GAAG;AAAA,MAClE;AAAA,IACF,CAAC,EAAE,gBAAgB,MAAM,UAAU;AAEnC,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,IAAI,MAAM,gBAAgB,OAAO,CAAC,KAAK,aAAa,EAAE;AAAA,IAC9D;AAEA,UAAM,OAAO,IAAI;AACjB,QAAI,CAAC,MAAM;AACT,aAAO,EAAE,MAAM,CAAC,GAAG,SAAS,OAAO,QAAQ,OAAO,SAAS,MAAM,OAAU;AAAA,IAC7E;AAEA,UAAM,OAAgC,CAAC;AACvC,UAAM,MAAM,oBAAI,IAAoB;AACpC,UAAM,WAAW,KAAK,cAAc;AACpC,QAAI,IAAI,IAAI,QAAQ;AAEpB,UAAM,QAAQ,KAAK;AACnB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,OAAO,MAAM,KAAK,CAAC;AACzB,UAAI,CAAC,KAAM;AACX,YAAM,OAAO,KAAK;AAElB,UAAI,SAAS,WAAW,KAAK,WAAW,QAAQ,EAAG;AACnD,WAAK,IAAI,IAAIC,WAAU,KAAK,KAAK;AACjC,UAAI,IAAI,IAAID,sBAAqB,IAAI,CAAC,IAAI,KAAK,cAAc,QAAQ;AAAA,IACvE;AAEA,UAAM,UAAU,OAAO,KAAK,IAAI,EAAE,SAAS;AAC3C,WAAO,EAAE,MAAM,SAAS,QAAQ,OAAO,SAASE,gBAAe,GAAG,EAAE;AAAA,EACtE;AACF;;;ACnFA,SAAS,OAAO,0BAAsD;AACtE,SAAS,SAASC,wBAAuB;AAMzC,SAASC,sBAAqB,KAAqB;AACjD,SAAO,IAAI,QAAQ,MAAM,IAAI,EAAE,QAAQ,OAAO,IAAI;AACpD;AAGA,SAASC,WAAU,KAAsB;AAGvC,MAAI,QAAQ,GAAI,QAAO;AACvB,MAAI;AACF,WAAOF,iBAAgB,GAAG;AAAA,EAC5B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAASG,gBACP,KACyC;AACzC,SAAO,CAAC,YAAoB;AAE1B,UAAM,QACJ,YAAY,MAAM,CAAC,QAAQ,WAAW,GAAG,IACrC,IAAIF,sBAAqB,OAAO,CAAC,KACjC;AACN,QAAI,IAAI,IAAI,KAAK,EAAG,QAAO,IAAI,IAAI,KAAK;AAExC,QAAI,IAAI;AACR,WAAO,EAAE,SAAS,GAAG;AACnB,YAAM,MAAM,EAAE,YAAY,GAAG;AAC7B,UAAI,MAAM,EAAG;AACb,UAAI,EAAE,MAAM,GAAG,GAAG;AAClB,UAAI,IAAI,IAAI,CAAC,EAAG,QAAO,IAAI,IAAI,CAAC;AAAA,IAClC;AACA,WAAO,IAAI,IAAI,EAAE;AAAA,EACnB;AACF;AAEA,SAAS,UAAU,IAAa,MAAkC;AAChE,SAAO,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,GAAG;AAChD;AAEO,IAAM,gBAAmC;AAAA,EAC9C,MAAM;AAAA,EACN,YAAY,CAAC,SAAS,MAAM;AAAA,EAC5B,aAAa;AAAA,EACb,QAAQ,SAA4B;AAClC,UAAM,MAAM,MAAM,SAAS,EAAE,wBAAwB,KAAK,CAAC;AAE3D,UAAM,OAAgC,CAAC;AACvC,UAAM,MAAM,oBAAI,IAAoB;AAEpC,QAAI,IAAI,IAAI,CAAC;AAEb,UAAM,SAAS,CAAC,KAAa,OAAgB,SAAmC;AAC9E,WAAK,GAAG,IAAI;AACZ,UAAI,QAAQ,KAAM,KAAI,IAAI,IAAIA,sBAAqB,GAAG,CAAC,IAAI,IAAI;AAAA,IACjE;AAEA,UAAM,QAAQ,CAAC,SAA0B;AACvC,UAAI,mBAAmB,cAAc,IAAI,GAAG;AAC1C,cAAM,OAAO,KAAK,oBAAoB;AACtC,YAAI,KAAK,YAAY,SAAS;AAE5B,cAAI,KAAK,UAAU,QAAW;AAC5B,kBAAM,QAAQ,KAAK,WAAW,CAAC;AAC/B,kBAAM,OACJ,SAAS,mBAAmB,WAAW,KAAK,IAAI,MAAM,QAAQ;AAChE,mBAAO,SAAS,MAAM,IAAI;AAAA,UAC5B;AAAA,QACF,WAAW,KAAK,YAAY,QAAQ;AAClC,gBAAM,MAAM,UAAU,MAAM,MAAM,KAAK,UAAU,MAAM,UAAU;AACjE,gBAAM,QAAQ,UAAU,MAAM,SAAS;AACvC,cAAI,OAAO,QAAQ,SAAS,MAAM;AAChC,mBAAO,KAAKC,WAAU,KAAK,GAAG,IAAI;AAAA,UACpC;AAAA,QACF;AAAA,MACF;AACA,UAAI,mBAAmB,cAAc,IAAI,GAAG;AAC1C,mBAAW,SAAS,KAAK,WAAY,OAAM,KAAK;AAAA,MAClD;AAAA,IACF;AAEA,eAAW,SAAS,IAAI,WAAY,OAAM,KAAK;AAE/C,UAAM,UAAU,OAAO,KAAK,IAAI,EAAE,SAAS;AAC3C,WAAO,EAAE,MAAM,SAAS,QAAQ,QAAQ,SAASC,gBAAe,GAAG,EAAE;AAAA,EACvE;AACF;;;AChGO,IAAM,aAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,cAAc,oBAAI,IAA+B;AACvD,IAAM,SAAS,oBAAI,IAA+B;AAClD,WAAW,MAAM,YAAY;AAC3B,SAAO,IAAI,GAAG,MAAM,EAAE;AACtB,aAAW,OAAO,GAAG,WAAY,aAAY,IAAI,IAAI,YAAY,GAAG,EAAE;AACxE;AAGO,SAAS,sBACd,KAC+B;AAC/B,QAAM,KAAK,YAAY,IAAI,IAAI,YAAY,CAAC;AAC5C,SAAO,IAAI,cAAc,KAAK;AAChC;AAGO,SAAS,gBAAgB,MAA6C;AAC3E,SAAO,OAAO,IAAI,KAAK,YAAY,CAAC;AACtC;AAGO,SAAS,sBAAgC;AAC9C,SAAO,WAAW,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,MAAM,EAAE,UAAU;AAC5E;AAGO,SAAS,cAA8E;AAC5F,SAAO,WAAW,IAAI,CAAC,OAAO;AAAA,IAC5B,MAAM,EAAE;AAAA,IACR,YAAY,EAAE;AAAA,IACd,aAAa,EAAE;AAAA,EACjB,EAAE;AACJ;;;ACjDA,SAAS,YAAY;AACrB,SAAS,SAAS,UAAU,WAAAC,gBAAe;AAC3C,OAAO,QAAQ;AAGf,IAAM,iBAAiB,CAAC,sBAAsB,YAAY;AAEnD,IAAM,cAAc;AAE3B,SAAS,QAAQ,GAAmB;AAClC,SAAO,EAAE,QAAQ,OAAO,GAAG;AAC7B;AAEA,eAAe,WAAW,GAAW;AACnC,MAAI;AACF,WAAO,MAAM,KAAK,CAAC;AAAA,EACrB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAYA,eAAsB,eAAe,MAAyC;AAC5E,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AACpC,QAAM,QAAQ,KAAK,QAAQ,oBAAoB,GAAG;AAAA,IAAI,CAAC,MACrD,EAAE,YAAY,EAAE,WAAW,GAAG,IAAI,EAAE,YAAY,IAAI,IAAI,EAAE,YAAY,CAAC;AAAA,EACzE;AACA,QAAM,SAAS,CAAC,GAAG,gBAAgB,GAAI,KAAK,WAAW,CAAC,CAAE;AAC1D,QAAM,MAAM,oBAAI,IAAY;AAE5B,QAAM,YAAY,CAAC,SACjB,KAAK,SAAS,QAAQ,IAAI,EAAE,YAAY,CAAC;AAE3C,aAAW,SAAS,KAAK,QAAQ;AAC/B,QAAI,UAAU,YAAa;AAE3B,UAAM,MAAMC,SAAQ,KAAK,KAAK;AAC9B,UAAM,KAAK,MAAM,WAAW,GAAG;AAE/B,QAAI,IAAI,OAAO,GAAG;AAChB,UAAI,IAAI,QAAQ,SAAS,KAAK,GAAG,CAAC,CAAC;AACnC;AAAA,IACF;AAEA,QAAI,IAAI,YAAY,GAAG;AACrB,YAAMC,SAAQ,MAAM,GAAG,GAAG,QAAQ,KAAK,CAAC,SAAS;AAAA,QAC/C;AAAA,QACA;AAAA,QACA,WAAW;AAAA,QACX,KAAK;AAAA,MACP,CAAC;AACD,iBAAW,KAAKA,OAAO,KAAI,UAAU,CAAC,EAAG,KAAI,IAAI,CAAC;AAClD;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM,GAAG,QAAQ,KAAK,GAAG;AAAA,MACrC;AAAA,MACA;AAAA,MACA,WAAW;AAAA,MACX,KAAK;AAAA,IACP,CAAC;AACD,eAAW,KAAK,MAAO,KAAI,UAAU,CAAC,EAAG,KAAI,IAAI,CAAC;AAAA,EACpD;AAEA,SAAO,CAAC,GAAG,GAAG,EAAE,KAAK;AACvB;;;ARxCA,SAAS,iBACP,MACA,QACA,SACkB;AAClB,QAAM,MAAkB,EAAE,QAAQ,WAAW,cAAc,IAAI,QAAQ;AACvE,SAAO,EAAE,MAAM,QAAQ,IAAI,OAAO,SAAS,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE;AAC/D;AAEA,eAAsB,YACpB,MACsB;AACtB,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AAEpC,QAAM,SAAS,MAAM,WAAW,KAAK,YAAY,GAAG;AACpD,QAAM,SAA+B,QAAQ,UAAU;AAGvD,QAAM,SACJ,KAAK,OAAO,SAAS,IAAI,KAAK,SAAU,QAAQ,SAAS,CAAC;AAC5D,QAAM,aAAa,OAAO,SAAS,WAAW;AAE9C,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAGA,QAAM,kBAAkB,KAAK,KAAK,gBAAgB,KAAK,EAAE,IAAI;AAC7D,MAAI,KAAK,MAAM,CAAC,iBAAiB;AAC/B,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,EAAE,4BAA4B,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,OACJ,KAAK,SAAS,kBAAkB,gBAAgB,aAAa;AAE/D,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,MAAM,WAAW;AACzD,QAAM,QAAQ,MAAM,eAAe;AAAA,IACjC,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,CAAC,GAAI,QAAQ,WAAW,CAAC,GAAI,GAAI,KAAK,WAAW,CAAC,CAAE;AAAA,IAC7D;AAAA,EACF,CAAC;AAED,QAAM,YAAY,IAAI,UAAU;AAChC,QAAM,UAA8B,CAAC;AAErC,QAAM,aAAa,OACjB,OACA,SACA,cACkB;AAClB,UAAM,YACJ,mBAAmB,sBAAsB,SAAS;AACpD,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,0BAA0B,SAAS,UAAU,KAAK,iBAAiB,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,MACrG;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,kBAAY,UAAU,QAAQ,SAAS,KAAK;AAAA,IAC9C,SAAS,KAAK;AACZ,UAAI,eAAe,aAAc,OAAM;AACvC,cAAQ,KAAK,iBAAiB,OAAO,UAAU,MAAO,IAAc,OAAO,CAAC;AAC5E;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AACF,kBAAY,iBAAiB;AAAA,QAC3B,UAAU;AAAA,QACV,YAAY,UAAU,KAAK,eAAe;AAAA,QAC1C,YAAY,KAAK;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH,SAAS,KAAK;AACZ,cAAQ,KAAK,iBAAiB,OAAO,UAAU,MAAO,IAAc,OAAO,CAAC;AAC5E;AAAA,IACF;AAEA,UAAM,SAAS,MAAM,UAAU;AAAA,MAC7B,UAAU;AAAA,MACV;AAAA,MACA,UAAU;AAAA,IACZ;AACA,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,QAAQ,UAAU;AAAA,MAClB,IAAI,OAAO,WAAW;AAAA,MACtB,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,YAAY;AACd,UAAM,UAAU,KAAK,gBAAgB;AACrC,QAAI,CAAC,iBAAiB;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,UAAM,WAAW,WAAW,SAAS,gBAAgB,WAAW,CAAC,KAAK,EAAE;AAAA,EAC1E;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,MAAMC,UAASC,SAAQ,KAAK,IAAI,GAAG,MAAM;AACzD,UAAM,WAAW,MAAM,SAASC,SAAQ,IAAI,CAAC;AAAA,EAC/C;AAEA,QAAM,SAAS,QAAQ,OAAO,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE;AAC5C,QAAM,UAAsB;AAAA,IAC1B,OAAO,QAAQ;AAAA,IACf,QAAQ,QAAQ,SAAS;AAAA,IACzB;AAAA,IACA,QAAQ,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,OAAO,QAAQ,CAAC;AAAA,EACzD;AAEA,SAAO,EAAE,SAAS,QAAQ;AAC5B;;;AS9JA,SAAS,YAAAC,iBAAgB;AACzB,SAAS,WAAAC,UAAS,WAAAC,gBAAe;AA4BjC,eAAsB,OAAO,MAA4C;AACvE,QAAM,MAAM,KAAK,OAAO,QAAQ,IAAI;AACpC,MAAI,KAAK,OAAO,WAAW,GAAG;AAC5B,UAAM,IAAI,aAAa,oCAAoC;AAAA,EAC7D;AAEA,QAAM,SAAS,MAAM,WAAW,KAAK,YAAY,GAAG;AACpD,QAAM,SAA+B,QAAQ,UAAU;AAGvD,QAAM,SAAS,KAAK,OAAO,SAAS,IAAI,KAAK,SAAU,QAAQ,SAAS,CAAC;AACzE,QAAM,aAAa,OAAO,SAAS,WAAW;AAE9C,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,KAAK,KAAK,gBAAgB,KAAK,EAAE,IAAI;AACpD,MAAI,KAAK,MAAM,CAAC,QAAQ;AACtB,UAAM,IAAI;AAAA,MACR,mBAAmB,KAAK,EAAE,4BAA4B,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,IACxF;AAAA,EACF;AAEA,QAAM,OAAO,KAAK,SAAS,SAAS,OAAO,aAAa;AACxD,QAAM,aAAa,OAAO,OAAO,CAAC,MAAM,MAAM,WAAW;AACzD,QAAM,QAAQ,MAAM,eAAe;AAAA,IACjC,QAAQ;AAAA,IACR;AAAA,IACA,SAAS,CAAC,GAAI,QAAQ,WAAW,CAAC,GAAI,GAAI,KAAK,WAAW,CAAC,CAAE;AAAA,IAC7D;AAAA,EACF,CAAC;AAED,QAAM,MAAuB,CAAC;AAE9B,QAAM,UAAU,CAAC,OAAe,SAAiB,cAA4B;AAC3E,UAAM,YAAY,UAAU,sBAAsB,SAAS;AAC3D,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR,0BAA0B,SAAS,UAAU,KAAK,iBAAiB,oBAAoB,EAAE,KAAK,IAAI,CAAC;AAAA,MACrG;AAAA,IACF;AACA,UAAM,YAAY,UAAU,QAAQ,SAAS,KAAK;AAClD,UAAM,SAAkC,CAAC;AACzC,eAAW,KAAK,KAAK,OAAQ,QAAO,CAAC,IAAI,UAAU,KAAK,CAAC;AACzD,QAAI,KAAK,EAAE,MAAM,OAAO,SAAS,UAAU,SAAS,OAAO,CAAC;AAAA,EAC9D;AAEA,MAAI,YAAY;AACd,QAAI,CAAC,QAAQ;AACX,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,YAAQ,WAAW,KAAK,gBAAgB,IAAI,OAAO,WAAW,CAAC,KAAK,EAAE;AAAA,EACxE;AAEA,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,MAAMC,UAASC,SAAQ,KAAK,IAAI,GAAG,MAAM;AACzD,YAAQ,MAAM,SAASC,SAAQ,IAAI,CAAC;AAAA,EACtC;AAEA,SAAO;AACT;;;ACzFO,SAAS,iBAA8B;AAC5C,SAAO,EAAE,UAAU,aAAa,GAAG,SAAS,YAAY,EAAE;AAC5D;;;ACbA,OAAO,QAAQ;AAKR,SAAS,QAAQ,SAA0B;AAChD,SAAO,GAAG,aAAa,OAAO;AAChC;AAMO,SAAS,YAAY,MAIhB;AACV,QAAM,MAAM,KAAK,OAAO,QAAQ;AAChC,MAAI,KAAK,QAAS,QAAO;AACzB,MAAI,IAAI,YAAY,QAAQ,IAAI,aAAa,GAAI,QAAO;AACxD,SAAO,QAAQ,KAAK,KAAK;AAC3B;;;ACPA,SAAS,WAAW,cAA8B;AAChD,SAAO,iBAAiB,KAAK,WAAW;AAC1C;AAEO,SAAS,aACd,SACA,SACA,OAAsB,CAAC,GACf;AACR,QAAM,IAAI,QAAQ,KAAK,SAAS,KAAK;AACrC,QAAM,QAAkB,CAAC;AAEzB,aAAW,KAAK,SAAS;AACvB,QAAI,EAAE,IAAI;AACR,UAAI,CAAC,KAAK,MAAO,OAAM,KAAK,GAAG,EAAE,MAAM,QAAG,CAAC,IAAI,EAAE,IAAI,EAAE;AACvD;AAAA,IACF;AACA,UAAM,KAAK,GAAG,EAAE,IAAI,QAAG,CAAC,IAAI,EAAE,IAAI,EAAE;AACpC,eAAW,KAAK,EAAE,QAAQ;AACxB,YAAM,MAAM,EAAE,QAAQ,OAAO,EAAE,IAAI,WAAW,EAAE,IAAI,GAAG,IAAI;AAC3D,YAAM;AAAA,QACJ,OAAO,EAAE,KAAK,WAAW,EAAE,YAAY,CAAC,CAAC,KAAK,EAAE,OAAO,GAAG,GAAG,KAAK,EAAE;AAAA,UAClE,IAAI,EAAE,MAAM;AAAA,QACd,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,GAAG,QAAQ,KAAK,QAAQ,QAAQ,UAAU,IAAI,KAAK,GAAG,aAAa,QAAQ,MAAM,YAAY,QAAQ,MAAM,YAAY,QAAQ,MAAM,SAAS,QAAQ,WAAW,IAAI,KAAK,GAAG;AACjM,MAAI,MAAM,SAAS,EAAG,OAAM,KAAK,EAAE;AACnC,QAAM,KAAK,QAAQ,SAAS,IAAI,EAAE,IAAI,WAAW,IAAI,EAAE,MAAM,WAAW,CAAC;AACzE,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,WACd,SACA,SACQ;AACR,SAAO,KAAK,UAAU,EAAE,SAAS,QAAQ,GAAG,MAAM,CAAC;AACrD;AAEO,SAAS,aAAa,SAAqC;AAChE,QAAM,QAAkB,CAAC;AACzB,aAAW,KAAK,SAAS;AACvB,eAAW,KAAK,EAAE,QAAQ;AACxB,YAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE;AAChC,UAAI,EAAE,QAAQ,KAAM,QAAO,KAAK,QAAQ,EAAE,IAAI,EAAE;AAChD,UAAI,EAAE,OAAO,KAAM,QAAO,KAAK,OAAO,EAAE,GAAG,EAAE;AAC7C,YAAM,MAAM,IAAI,EAAE,MAAM,KAAK,WAAW,EAAE,YAAY,CAAC,IAAI,EAAE,OAAO;AACpE,YAAM,KAAK,WAAW,OAAO,KAAK,GAAG,CAAC,KAAK,GAAG,EAAE;AAAA,IAClD;AAAA,EACF;AACA,SAAO,MAAM,KAAK,IAAI;AACxB;AAEO,SAAS,OACd,QACA,SACA,SACA,OAAsB,CAAC,GACf;AACR,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH,aAAO,WAAW,SAAS,OAAO;AAAA,IACpC,KAAK;AACH,aAAO,aAAa,OAAO;AAAA,IAC7B,KAAK;AAAA,IACL;AACE,aAAO,aAAa,SAAS,SAAS,IAAI;AAAA,EAC9C;AACF;","names":["readFile","readFile","readFile","resolve","extname","OPENING","escapePointerSegment","lineForFactory","parseYamlScalar","OPENING","escapePointerSegment","typeValue","parseYamlScalar","lineForFactory","under","parseYamlScalar","escapePointerSegment","typeValue","lineForFactory","parseYamlScalar","escapePointerSegment","typeValue","lineForFactory","resolve","resolve","found","readFile","resolve","extname","readFile","resolve","extname","readFile","resolve","extname"]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/core/config.ts","../src/core/resolve-schema.ts","../src/core/schema-registry.ts","../src/schemas/okf/0.1.json","../src/core/validator.ts","../src/commands/validate.ts","../src/extractors/markdown.ts","../src/extractors/mdx.ts","../src/extractors/asciidoc.ts","../src/extractors/rst.ts","../src/extractors/xml.ts","../src/extractors/html.ts","../src/extractors/index.ts","../src/core/load-files.ts","../src/commands/get.ts","../src/commands/schemas.ts","../src/reporters/color.ts","../src/reporters/index.ts"],"sourcesContent":["/**\n * Shared types for docmeta.\n *\n * The pipeline is: load files -> extract metadata (format-specific) ->\n * resolve a schema set per file -> validate against each schema -> report.\n * Everything after extraction operates only on `ExtractedMetadata`, so new\n * input formats never touch validation, resolution, or reporting.\n */\n\n/** Result of pulling a metadata block out of a single document. */\nexport interface ExtractedMetadata {\n /** Parsed metadata key/values. `{}` when a block is present but empty. */\n data: Record<string, unknown>;\n /** Whether a metadata block was found at all. */\n present: boolean;\n /** Name of the extractor/format that produced this (e.g. \"markdown\"). */\n format: string;\n /**\n * Map a JSON Pointer (Ajv `instancePath`, e.g. \"/tags/0\") or a bare top-level\n * key to its 1-based source line, for precise annotations. Returns undefined\n * when no position is known.\n */\n lineFor(pointer: string): number | undefined;\n}\n\n/** A pluggable metadata extractor for one document format. */\nexport interface MetadataExtractor {\n /** Stable name, also used as `ExtractedMetadata.format`. */\n name: string;\n /** Lowercase file extensions this extractor handles, incl. dot (e.g. \".md\"). */\n extensions: string[];\n /** Whether this extractor is wired up (false for roadmap stubs). */\n implemented: boolean;\n /** Extract metadata from raw file content. */\n extract(content: string, filePath: string): ExtractedMetadata;\n}\n\n/** A single schema violation for one file, attributed to one schema. */\nexport interface FieldError {\n /** Schema id/ref that produced this error (e.g. \"google:okf:0.1\"). */\n schema: string;\n /** Ajv instancePath, e.g. \"/tags/0\" or \"\" for the root. */\n instancePath: string;\n /** Human-readable message. */\n message: string;\n /** 1-based source line, when known. */\n line?: number;\n /** 1-based column, when known. */\n col?: number;\n}\n\n/** Validation outcome for a single file. */\nexport interface ValidationResult {\n /** Absolute or cwd-relative path of the file. */\n file: string;\n /** Extractor/format used. */\n format: string;\n /** Whether validation passed against every schema in the set. */\n ok: boolean;\n /** Schema ids/refs the file was validated against. */\n schemas: string[];\n /** All violations, across every schema in the set. */\n errors: FieldError[];\n}\n\n/** Aggregate run summary. */\nexport interface RunSummary {\n files: number;\n passed: number;\n failed: number;\n errors: number;\n}\n\n/** An operational/usage failure that should map to exit code 2. */\nexport class DocmetaError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DocmetaError\";\n }\n}\n","/**\n * Optional lightweight YAML config (`docmeta.config.yaml`). Supplies default\n * targets, excludes, the default schema set, and optional per-glob overrides,\n * so CI can run a bare `docmeta validate`.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { DocmetaError } from \"../types.js\";\n\nexport interface SchemaOverride {\n files: string;\n schemas: string[];\n}\n\nexport interface DocmetaConfig {\n paths?: string[];\n exclude?: string[];\n schemas?: string[];\n overrides?: SchemaOverride[];\n}\n\nconst CONFIG_NAMES = [\"docmeta.config.yaml\", \"docmeta.config.yml\"];\n\nfunction asStringList(value: unknown, field: string, source: string): string[] {\n if (!Array.isArray(value) || value.some((v) => typeof v !== \"string\")) {\n throw new DocmetaError(\n `${source}: \"${field}\" must be a list of strings.`,\n );\n }\n return value as string[];\n}\n\n/** Parse and validate config YAML text. */\nexport function parseConfig(text: string, source: string): DocmetaConfig {\n let raw: unknown;\n try {\n raw = parseYaml(text);\n } catch (err) {\n throw new DocmetaError(\n `${source}: invalid YAML: ${(err as Error).message}`,\n );\n }\n if (raw == null) return {};\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new DocmetaError(`${source}: top level must be a mapping.`);\n }\n const obj = raw as Record<string, unknown>;\n const config: DocmetaConfig = {};\n\n if (obj.paths !== undefined) config.paths = asStringList(obj.paths, \"paths\", source);\n if (obj.exclude !== undefined)\n config.exclude = asStringList(obj.exclude, \"exclude\", source);\n if (obj.schemas !== undefined)\n config.schemas = asStringList(obj.schemas, \"schemas\", source);\n\n if (obj.overrides !== undefined) {\n if (!Array.isArray(obj.overrides)) {\n throw new DocmetaError(`${source}: \"overrides\" must be a list.`);\n }\n config.overrides = obj.overrides.map((entry, i) => {\n if (typeof entry !== \"object\" || entry === null) {\n throw new DocmetaError(`${source}: overrides[${i}] must be a mapping.`);\n }\n const e = entry as Record<string, unknown>;\n if (typeof e.files !== \"string\") {\n throw new DocmetaError(\n `${source}: overrides[${i}].files must be a string glob.`,\n );\n }\n return {\n files: e.files,\n schemas: asStringList(e.schemas, `overrides[${i}].schemas`, source),\n };\n });\n }\n\n return config;\n}\n\n/**\n * Load config from an explicit path (error if missing) or by discovery in cwd.\n * Returns null when no config is found via discovery.\n */\nexport async function loadConfig(\n explicitPath?: string,\n cwd: string = process.cwd(),\n): Promise<{ config: DocmetaConfig; path: string } | null> {\n if (explicitPath) {\n let text: string;\n try {\n text = await readFile(explicitPath, \"utf8\");\n } catch {\n throw new DocmetaError(`Config file not found: \"${explicitPath}\".`);\n }\n return { config: parseConfig(text, explicitPath), path: explicitPath };\n }\n\n for (const name of CONFIG_NAMES) {\n const p = resolve(cwd, name);\n try {\n const text = await readFile(p, \"utf8\");\n return { config: parseConfig(text, name), path: p };\n } catch {\n // not found; try next\n }\n }\n return null;\n}\n","/**\n * Resolve the schema *set* for a single file by precedence:\n * 1. CLI --schema overrides (apply to all files)\n * 2. $schema in the file's metadata (string or list)\n * 3. first matching config override (by glob)\n * 4. config default schemas\n * 5. built-in default (google:okf:0.1)\n */\nimport picomatch from \"picomatch\";\nimport type { DocmetaConfig } from \"./config.js\";\n\nexport const DEFAULT_SCHEMA = \"google:okf:0.1\";\nexport const FILE_SCHEMA_KEY = \"$schema\";\n\nexport interface ResolveParams {\n /** File path (relative is fine) used for override glob matching. */\n filePath: string;\n /** `$schema` value pulled from the file's metadata. */\n fileSchema?: unknown;\n /** Repeatable `--schema` values; non-empty means override. */\n cliSchemas?: string[];\n /** Loaded config, if any. */\n config?: DocmetaConfig | null;\n}\n\nconst matcherCache = new Map<string, (p: string) => boolean>();\nfunction matches(glob: string, filePath: string): boolean {\n let m = matcherCache.get(glob);\n if (!m) {\n m = picomatch(glob, { dot: true });\n matcherCache.set(glob, m);\n }\n // Normalize Windows separators so globs written with `/` still match.\n return m(filePath.replace(/\\\\/g, \"/\"));\n}\n\nfunction coerceFileSchema(value: unknown): string[] | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value === \"string\") return [value];\n if (Array.isArray(value) && value.every((v) => typeof v === \"string\")) {\n return value as string[];\n }\n throw new Error(\n `Invalid \"${FILE_SCHEMA_KEY}\": must be a string or a list of strings.`,\n );\n}\n\nfunction dedupe(refs: string[]): string[] {\n return [...new Set(refs)];\n}\n\nexport function resolveSchemaSet(params: ResolveParams): string[] {\n const { filePath, fileSchema, cliSchemas, config } = params;\n\n if (cliSchemas && cliSchemas.length > 0) return dedupe(cliSchemas);\n\n const fromFile = coerceFileSchema(fileSchema);\n if (fromFile && fromFile.length > 0) return dedupe(fromFile);\n\n if (config?.overrides) {\n for (const ov of config.overrides) {\n if (matches(ov.files, filePath) && ov.schemas.length > 0) {\n return dedupe(ov.schemas);\n }\n }\n }\n\n if (config?.schemas && config.schemas.length > 0) return dedupe(config.schemas);\n\n return [DEFAULT_SCHEMA];\n}\n","/**\n * Source of truth for schemas. Holds the built-in schemas (addressed by\n * `vendor:name:version` ids) and knows how to load any schema reference —\n * a built-in id, a local `.json` path, or an `http(s)` URL.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { DocmetaError } from \"../types.js\";\n\nimport okf01 from \"../schemas/okf/0.1.json\" with { type: \"json\" };\n\nexport interface BuiltinInfo {\n id: string;\n title: string;\n description: string;\n}\n\n/** Built-in schemas keyed by `vendor:name:version` id. */\nconst BUILTINS = new Map<string, Record<string, unknown>>([\n [\"google:okf:0.1\", okf01 as Record<string, unknown>],\n]);\n\nexport function listBuiltins(): BuiltinInfo[] {\n return [...BUILTINS.entries()].map(([id, schema]) => ({\n id,\n title: typeof schema.title === \"string\" ? schema.title : id,\n description:\n typeof schema.description === \"string\" ? schema.description : \"\",\n }));\n}\n\nexport type RefKind = \"builtin\" | \"file\" | \"url\";\n\n/**\n * A built-in id looks like `seg(:seg)+` using only [a-z0-9._-] segments, with\n * no path separators and not ending in `.json`. This deliberately excludes\n * Windows paths (`C:\\...`), URLs, and `.json` files so a typo'd built-in is\n * reported as an unknown id rather than silently treated as a missing file.\n */\nconst BUILTIN_ID = /^[a-z0-9][a-z0-9._-]*(?::[a-z0-9][a-z0-9._-]*)+$/i;\n\nexport function classifyRef(ref: string): { kind: RefKind; ref: string } {\n if (/^https?:\\/\\//i.test(ref)) return { kind: \"url\", ref };\n if (\n !ref.includes(\"/\") &&\n !ref.includes(\"\\\\\") &&\n !ref.toLowerCase().endsWith(\".json\") &&\n BUILTIN_ID.test(ref)\n ) {\n return { kind: \"builtin\", ref };\n }\n return { kind: \"file\", ref };\n}\n\nconst urlCache = new Map<string, Record<string, unknown>>();\n\n/** Default network timeout for fetching a remote (`http(s)`) schema. */\nconst DEFAULT_TIMEOUT_MS = 10_000;\n\nexport interface LoadSchemaOptions {\n /** Abort a remote fetch after this many ms (default 10_000). */\n timeoutMs?: number;\n}\n\n/** Load and return the JSON Schema object for a reference. */\nexport async function loadSchema(\n ref: string,\n options: LoadSchemaOptions = {},\n): Promise<Record<string, unknown>> {\n const { kind } = classifyRef(ref);\n\n if (kind === \"builtin\") {\n const schema = BUILTINS.get(ref);\n if (!schema) {\n const available = [...BUILTINS.keys()].join(\", \");\n throw new DocmetaError(\n `Unknown built-in schema \"${ref}\". Available: ${available || \"(none)\"}.`,\n );\n }\n return schema;\n }\n\n if (kind === \"url\") {\n const cached = urlCache.get(ref);\n if (cached) return cached;\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n let res: Response;\n try {\n res = await fetch(ref, { signal: AbortSignal.timeout(timeoutMs) });\n } catch (err) {\n const e = err as Error;\n if (e.name === \"TimeoutError\" || e.name === \"AbortError\") {\n throw new DocmetaError(\n `Failed to fetch schema \"${ref}\": timed out after ${timeoutMs}ms.`,\n );\n }\n throw new DocmetaError(`Failed to fetch schema \"${ref}\": ${e.message}`);\n }\n if (!res.ok) {\n throw new DocmetaError(\n `Failed to fetch schema \"${ref}\": HTTP ${res.status}.`,\n );\n }\n let json: Record<string, unknown>;\n try {\n json = (await res.json()) as Record<string, unknown>;\n } catch (err) {\n throw new DocmetaError(\n `Schema \"${ref}\" did not return valid JSON: ${(err as Error).message}`,\n );\n }\n urlCache.set(ref, json);\n return json;\n }\n\n // file\n let raw: string;\n try {\n raw = await readFile(ref, \"utf8\");\n } catch {\n throw new DocmetaError(`Schema file not found: \"${ref}\".`);\n }\n try {\n return JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n throw new DocmetaError(\n `Schema file \"${ref}\" is not valid JSON: ${(err as Error).message}`,\n );\n }\n}\n","{\n \"$schema\": \"https://json-schema.org/draft/2020-12/schema\",\n \"$id\": \"google:okf:0.1\",\n \"title\": \"Open Knowledge Format (OKF) v0.1\",\n \"description\": \"Frontmatter schema for OKF v0.1 concept files. OKF requires only `type`; all other fields are recommended, and unknown keys are explicitly tolerated. See https://github.com/GoogleCloudPlatform/knowledge-catalog/blob/main/okf/SPEC.md\",\n \"type\": \"object\",\n \"required\": [\"type\"],\n \"additionalProperties\": true,\n \"properties\": {\n \"type\": {\n \"type\": \"string\",\n \"minLength\": 1,\n \"description\": \"A short string identifying the kind of concept. Used for routing, filtering, and presentation.\"\n },\n \"title\": {\n \"type\": \"string\",\n \"description\": \"Human-readable display name. If omitted, consumers MAY derive a title from the filename.\"\n },\n \"description\": {\n \"type\": \"string\",\n \"description\": \"Single-sentence summary used for indexing and previews.\"\n },\n \"resource\": {\n \"type\": \"string\",\n \"format\": \"uri\",\n \"description\": \"A URI uniquely identifying the underlying asset. Absent for abstract concepts.\"\n },\n \"tags\": {\n \"type\": \"array\",\n \"items\": { \"type\": \"string\" },\n \"description\": \"Short strings for categorization.\"\n },\n \"timestamp\": {\n \"type\": \"string\",\n \"format\": \"date-time\",\n \"description\": \"ISO 8601 datetime of last meaningful change.\"\n }\n }\n}\n","/**\n * JSON Schema validation engine. Compiles and caches an Ajv validator per\n * schema reference, validates extracted metadata against each schema in a set,\n * and maps every violation to a {schema, instancePath, line} FieldError.\n */\nimport * as AjvDraft07Ns from \"ajv\";\nimport * as Ajv2019Ns from \"ajv/dist/2019.js\";\nimport * as Ajv2020Ns from \"ajv/dist/2020.js\";\nimport * as AjvDraft04Ns from \"ajv-draft-04\";\nimport * as addFormatsNs from \"ajv-formats\";\nimport { createRequire } from \"node:module\";\nimport type { ErrorObject, ValidateFunction } from \"ajv/dist/2020.js\";\nimport { DocmetaError, type FieldError } from \"../types.js\";\n\n// ajv ships its meta-schema refs as JSON. A static JSON import survives\n// bundling as a bare ESM import without the required `type: json` attribute, so\n// load it through `require` instead (ajv is an external dep at runtime).\nconst draft06MetaSchema = createRequire(import.meta.url)(\n \"ajv/dist/refs/json-schema-draft-06.json\",\n) as Record<string, unknown>;\n\n// ajv and ajv-formats are CommonJS with a default export; under NodeNext the\n// callable/constructable value lives on `.default`. Cast through the named\n// default types so tsc sees a constructor / callable. The per-dialect builds\n// expose the same shape, so we treat them all as the 2020 constructor type.\ntype AjvCtor = typeof import(\"ajv/dist/2020.js\").default;\nconst AjvDraft07 = AjvDraft07Ns.default as unknown as AjvCtor;\nconst Ajv2019 = Ajv2019Ns.default as unknown as AjvCtor;\nconst Ajv2020 = Ajv2020Ns.default as unknown as AjvCtor;\nconst AjvDraft04 = AjvDraft04Ns.default as unknown as AjvCtor;\nconst addFormats =\n addFormatsNs.default as unknown as typeof import(\"ajv-formats\").default;\nimport { loadSchema } from \"./schema-registry.js\";\nimport { FILE_SCHEMA_KEY } from \"./resolve-schema.js\";\n\ntype Dialect = \"2020\" | \"2019\" | \"draft7\" | \"draft4\";\n\n/**\n * Pick a JSON Schema dialect from a schema's own `$schema` meta-schema URI.\n * Remote schemas commonly target draft-07/draft-04, which the 2020 build can't\n * compile, so each dialect gets its own Ajv. A missing or unrecognized\n * `$schema` falls back to 2020 (the dialect of the built-ins).\n */\nfunction dialectOf(schema: Record<string, unknown>): Dialect {\n const meta = typeof schema.$schema === \"string\" ? schema.$schema : \"\";\n if (meta.includes(\"2019-09\")) return \"2019\";\n // draft-06 shares the draft-07 build (its meta-schema is registered there).\n if (\n meta.includes(\"draft-07\") ||\n meta.includes(\"draft/7\") ||\n meta.includes(\"draft-06\") ||\n meta.includes(\"draft/6\")\n ) {\n return \"draft7\";\n }\n if (meta.includes(\"draft-04\") || meta.includes(\"draft/4\")) return \"draft4\";\n return \"2020\";\n}\n\nfunction buildAjv(dialect: Dialect): InstanceType<AjvCtor> {\n // strict: false so user-supplied schemas with lax metadata still compile.\n const opts = { allErrors: true, strict: false } as const;\n const ajv =\n dialect === \"2019\"\n ? new Ajv2019(opts)\n : dialect === \"draft7\"\n ? new AjvDraft07(opts)\n : dialect === \"draft4\"\n ? new AjvDraft04(opts)\n : new Ajv2020(opts);\n addFormats(ajv);\n // draft-06 shares the draft-07 build; register its meta-schema so draft-06\n // schemas compile too rather than erroring on an unknown `$schema`.\n if (dialect === \"draft7\") ajv.addMetaSchema(draft06MetaSchema);\n return ajv;\n}\n\nexport class Validator {\n private ajvByDialect = new Map<Dialect, InstanceType<AjvCtor>>();\n private cache = new Map<string, ValidateFunction>();\n\n private ajvFor(dialect: Dialect): InstanceType<AjvCtor> {\n let ajv = this.ajvByDialect.get(dialect);\n if (!ajv) {\n ajv = buildAjv(dialect);\n this.ajvByDialect.set(dialect, ajv);\n }\n return ajv;\n }\n\n private async compile(ref: string): Promise<ValidateFunction> {\n const cached = this.cache.get(ref);\n if (cached) return cached;\n const schema = await loadSchema(ref);\n let fn: ValidateFunction;\n try {\n fn = this.ajvFor(dialectOf(schema)).compile(schema);\n } catch (err) {\n throw new DocmetaError(\n `Schema \"${ref}\" failed to compile: ${(err as Error).message}`,\n );\n }\n this.cache.set(ref, fn);\n return fn;\n }\n\n /**\n * Validate `data` against every schema in `refs`. Returns all violations,\n * each tagged with the schema that produced it and a source line via\n * `lineFor`.\n */\n async validate(\n data: Record<string, unknown>,\n refs: string[],\n lineFor: (pointer: string) => number | undefined,\n ): Promise<FieldError[]> {\n // `$schema` is a docmeta directive, not part of the document's metadata —\n // strip it so schemas with additionalProperties:false don't flag it.\n const { [FILE_SCHEMA_KEY]: _omit, ...subject } = data;\n void _omit;\n\n const errors: FieldError[] = [];\n for (const ref of refs) {\n const fn = await this.compile(ref);\n const ok = fn(subject);\n if (ok) continue;\n for (const e of fn.errors ?? []) {\n errors.push(toFieldError(ref, e, lineFor));\n }\n }\n return errors;\n }\n}\n\nfunction toFieldError(\n schema: string,\n e: ErrorObject,\n lineFor: (pointer: string) => number | undefined,\n): FieldError {\n const instancePath = e.instancePath;\n // For `required`, point at the parent object but name the missing property.\n let message = e.message ?? \"is invalid\";\n if (e.keyword === \"required\" && e.params && \"missingProperty\" in e.params) {\n message = `must have required property '${String(e.params.missingProperty)}'`;\n } else if (\n e.keyword === \"additionalProperties\" &&\n e.params &&\n \"additionalProperty\" in e.params\n ) {\n message = `must NOT have additional property '${String(e.params.additionalProperty)}'`;\n }\n const line = lineFor(instancePath);\n return { schema, instancePath, message, ...(line != null ? { line } : {}) };\n}\n","/**\n * `validate` command core. Resolves targets, extracts metadata, resolves a\n * schema set per file, validates, and returns structured results. Kept free of\n * CLI/IO plumbing so it can be tested directly.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve, extname } from \"node:path\";\nimport {\n DocmetaError,\n type FieldError,\n type RunSummary,\n type ValidationResult,\n} from \"../types.js\";\nimport {\n extractorByName,\n extractorForExtension,\n supportedExtensions,\n} from \"../extractors/index.js\";\nimport { resolveTargets, STDIN_TOKEN } from \"../core/load-files.js\";\nimport { loadConfig, type DocmetaConfig } from \"../core/config.js\";\nimport { resolveSchemaSet, FILE_SCHEMA_KEY } from \"../core/resolve-schema.js\";\nimport { Validator } from \"../core/validator.js\";\n\nexport interface ValidateOptions {\n inputs: string[];\n cliSchemas?: string[];\n exts?: string[];\n exclude?: string[];\n /** `--as` format override (extractor name). */\n as?: string;\n configPath?: string;\n cwd?: string;\n /** Content for the `-` (stdin) input, injected by the CLI/tests. */\n stdinContent?: string;\n}\n\nexport interface ValidateRun {\n results: ValidationResult[];\n summary: RunSummary;\n}\n\nfunction parseErrorResult(\n file: string,\n format: string,\n message: string,\n): ValidationResult {\n const err: FieldError = { schema: \"(parse)\", instancePath: \"\", message };\n return { file, format, ok: false, schemas: [], errors: [err] };\n}\n\nexport async function runValidate(\n opts: ValidateOptions,\n): Promise<ValidateRun> {\n const cwd = opts.cwd ?? process.cwd();\n\n const loaded = await loadConfig(opts.configPath, cwd);\n const config: DocmetaConfig | null = loaded?.config ?? null;\n\n // Determine inputs: explicit CLI inputs win, else config.paths.\n const inputs =\n opts.inputs.length > 0 ? opts.inputs : (config?.paths ?? []);\n const usingStdin = inputs.includes(STDIN_TOKEN);\n\n if (inputs.length === 0) {\n throw new DocmetaError(\n \"No files to validate. Pass paths/globs, or add `paths:` to docmeta.config.yaml.\",\n );\n }\n\n // Pick an explicit extractor for `--as`, validating it up front.\n const forcedExtractor = opts.as ? extractorByName(opts.as) : undefined;\n if (opts.as && !forcedExtractor) {\n throw new DocmetaError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n\n const exts =\n opts.exts ?? (forcedExtractor ? forcedExtractor.extensions : undefined);\n\n const fileInputs = inputs.filter((i) => i !== STDIN_TOKEN);\n const files = await resolveTargets({\n inputs: fileInputs,\n exts,\n exclude: [...(config?.exclude ?? []), ...(opts.exclude ?? [])],\n cwd,\n });\n\n const validator = new Validator();\n const results: ValidationResult[] = [];\n\n const processOne = async (\n label: string,\n content: string,\n extension: string,\n ): Promise<void> => {\n const extractor =\n forcedExtractor ?? extractorForExtension(extension);\n if (!extractor) {\n throw new DocmetaError(\n `Unsupported file type \"${extension}\" for \"${label}\". Supported: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n );\n }\n\n let extracted;\n try {\n extracted = extractor.extract(content, label);\n } catch (err) {\n if (err instanceof DocmetaError) throw err; // operational (stub/unsupported)\n results.push(parseErrorResult(label, extractor.name, (err as Error).message));\n return;\n }\n\n let schemaSet: string[];\n try {\n schemaSet = resolveSchemaSet({\n filePath: label,\n fileSchema: extracted.data[FILE_SCHEMA_KEY],\n cliSchemas: opts.cliSchemas,\n config,\n });\n } catch (err) {\n results.push(parseErrorResult(label, extractor.name, (err as Error).message));\n return;\n }\n\n const errors = await validator.validate(\n extracted.data,\n schemaSet,\n extracted.lineFor,\n );\n results.push({\n file: label,\n format: extractor.name,\n ok: errors.length === 0,\n schemas: schemaSet,\n errors,\n });\n };\n\n if (usingStdin) {\n const content = opts.stdinContent ?? \"\";\n if (!forcedExtractor) {\n throw new DocmetaError(\n \"Reading from stdin (`-`) requires --as <format> to choose an extractor.\",\n );\n }\n await processOne(\"<stdin>\", content, forcedExtractor.extensions[0] ?? \"\");\n }\n\n for (const file of files) {\n const content = await readFile(resolve(cwd, file), \"utf8\");\n await processOne(file, content, extname(file));\n }\n\n const failed = results.filter((r) => !r.ok).length;\n const summary: RunSummary = {\n files: results.length,\n passed: results.length - failed,\n failed,\n errors: results.reduce((n, r) => n + r.errors.length, 0),\n };\n\n return { results, summary };\n}\n","/**\n * Markdown frontmatter extractor. Splits the leading YAML frontmatter block\n * ourselves (deterministic offsets) and parses it with the `yaml` AST + a\n * LineCounter to recover a JSON-Pointer -> source-line map for annotations.\n */\nimport { parseDocument, LineCounter, isMap, isSeq, isScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\nconst OPENING = /^---\\r?\\n/;\n\ninterface Block {\n /** Raw YAML between the delimiters (no leading/trailing newline). */\n raw: string;\n /** 1-based file line of the first YAML content line. */\n firstYamlLine: number;\n}\n\n/** Locate the leading `--- ... ---` frontmatter block, if any. */\nfunction splitFrontmatter(content: string): Block | null {\n // A BOM stays part of line 1; it doesn't shift line numbers.\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (!OPENING.test(body)) return null;\n\n const lines = body.split(/\\r?\\n/);\n let close = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i] === \"---\" || lines[i] === \"...\") {\n close = i;\n break;\n }\n }\n if (close === -1) return null;\n\n return { raw: lines.slice(1, close).join(\"\\n\"), firstYamlLine: 2 };\n}\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Build a JSON-Pointer -> 1-based file line map from a parsed YAML block. */\nfunction buildLineMap(\n doc: ReturnType<typeof parseDocument>,\n lc: LineCounter,\n prefixLines: number,\n): Map<string, number> {\n const map = new Map<string, number>();\n // Root pointer maps to the opening `---` line (block start).\n map.set(\"\", 1);\n\n const lineAt = (offset: number | undefined): number | undefined =>\n offset == null ? undefined : lc.linePos(offset).line + prefixLines;\n\n const walk = (node: unknown, pointer: string): void => {\n if (isMap(node)) {\n for (const pair of node.items) {\n const key = isScalar(pair.key)\n ? String(pair.key.value)\n : String(pair.key);\n const ptr = `${pointer}/${escapePointerSegment(key)}`;\n const line = lineAt(\n (pair.key as { range?: [number, number, number] })?.range?.[0],\n );\n if (line != null) map.set(ptr, line);\n if (pair.value) walk(pair.value, ptr);\n }\n } else if (isSeq(node)) {\n node.items.forEach((item, i) => {\n const ptr = `${pointer}/${i}`;\n const line = lineAt(\n (item as { range?: [number, number, number] })?.range?.[0],\n );\n if (line != null) map.set(ptr, line);\n walk(item, ptr);\n });\n }\n };\n\n if (doc.contents) walk(doc.contents, \"\");\n return map;\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/** Core frontmatter extraction shared by the markdown and mdx extractors. */\nexport function extractFrontmatter(\n content: string,\n format: string,\n): ExtractedMetadata {\n const block = splitFrontmatter(content);\n if (!block) {\n return { data: {}, present: false, format, lineFor: () => undefined };\n }\n\n const lc = new LineCounter();\n const doc = parseDocument(block.raw, { lineCounter: lc });\n if (doc.errors.length > 0) {\n const e = doc.errors[0];\n // Surface as a thrown error; the command layer records it as a per-file\n // failure so the rest of the run continues.\n throw new Error(`Invalid YAML frontmatter: ${e?.message ?? \"parse error\"}`);\n }\n\n const js = doc.toJS({ maxAliasCount: 100 }) as unknown;\n const data =\n js && typeof js === \"object\" && !Array.isArray(js)\n ? (js as Record<string, unknown>)\n : {};\n\n const map = buildLineMap(doc, lc, block.firstYamlLine - 1);\n return { data, present: true, format, lineFor: lineForFactory(map) };\n}\n\nexport const markdownExtractor: MetadataExtractor = {\n name: \"markdown\",\n extensions: [\".md\", \".markdown\"],\n implemented: true,\n extract: (content) => extractFrontmatter(content, \"markdown\"),\n};\n","/**\n * MDX extractor. MDX frontmatter is identical to Markdown's YAML block, so we\n * reuse the same logic. Parsing `export const meta = {...}` is future work.\n */\nimport { extractFrontmatter } from \"./markdown.js\";\nimport type { MetadataExtractor } from \"../types.js\";\n\nexport const mdxExtractor: MetadataExtractor = {\n name: \"mdx\",\n extensions: [\".mdx\"],\n implemented: true,\n extract: (content) => extractFrontmatter(content, \"mdx\"),\n};\n","/**\n * AsciiDoc metadata extractor.\n *\n * Two metadata styles are accepted:\n * 1. A leading YAML frontmatter block (`--- … ---`), as some static-site\n * generators use. This delegates to the shared `extractFrontmatter` so the\n * values are typed and the line map comes for free.\n * 2. The native AsciiDoc document header: the `= Title` line plus `:key: value`\n * attribute entries, running from the first line until the first blank line.\n * Attribute values are parsed as YAML scalars so `2` -> number, `true` ->\n * boolean, etc., consistent with frontmatter typing.\n */\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\nimport { extractFrontmatter } from \"./markdown.js\";\n\nconst OPENING = /^---\\r?\\n/;\nconst TITLE = /^=\\s+(.+?)\\s*$/;\n// `:!name:` or `:name!:` — an unset attribute.\nconst UNSET = /^:(?:!([^:\\s]+)|([^:\\s]+)!):\\s*$/;\n// `:name:` or `:name: value` — a set attribute (value optional).\nconst SET = /^:([^:\\s!][^:\\s]*):(?:\\s+(.*\\S))?\\s*$/;\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw attribute value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // A YAML-typed value can be an array/object, so Ajv may report nested\n // pointers like \"/tags/0\". Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/** Parse the native AsciiDoc document header (title + attribute entries). */\nfunction extractHeader(content: string): ExtractedMetadata {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const lines = body.split(/\\r?\\n/);\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n map.set(\"\", 1);\n\n const setKey = (key: string, value: unknown, line: number): void => {\n data[key] = value;\n map.set(`/${escapePointerSegment(key)}`, line);\n };\n\n for (const [i, line] of lines.entries()) {\n // The header ends at the first blank line.\n if (line.trim() === \"\") break;\n\n if (i === 0) {\n const title = TITLE.exec(line);\n if (title?.[1] != null) {\n setKey(\"title\", title[1], i + 1);\n continue;\n }\n }\n\n const unset = UNSET.exec(line);\n if (unset) {\n const name = unset[1] ?? unset[2];\n if (name != null) setKey(name, false, i + 1);\n continue;\n }\n\n const set = SET.exec(line);\n if (set?.[1] != null) {\n const value = set[2] === undefined ? true : typeValue(set[2]);\n setKey(set[1], value, i + 1);\n continue;\n }\n // Non-attribute header lines (e.g. author/revision) are ignored.\n }\n\n const present = Object.keys(data).length > 0;\n return {\n data,\n present,\n format: \"asciidoc\",\n lineFor: lineForFactory(map),\n };\n}\n\nexport const asciidocExtractor: MetadataExtractor = {\n name: \"asciidoc\",\n extensions: [\".adoc\", \".asciidoc\"],\n implemented: true,\n extract(content) {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (OPENING.test(body)) {\n // Delegate only when a complete frontmatter block is actually present;\n // a stray opening `---` with no closing delimiter should not shadow a\n // native AsciiDoc header that follows.\n const fm = extractFrontmatter(content, \"asciidoc\");\n if (fm.present) return fm;\n }\n return extractHeader(content);\n },\n};\n","/**\n * reStructuredText metadata extractor.\n *\n * Two metadata styles are accepted:\n * 1. A leading YAML frontmatter block (`--- … ---`), as some static-site\n * generators (e.g. MyST) use. This delegates to the shared\n * `extractFrontmatter` so the values are typed and the line map comes for\n * free.\n * 2. The native reStructuredText docinfo field list: the run of `:name: value`\n * entries at the top of the document, optionally preceded by a section\n * title (which we skip — only page-level metadata is extracted, not\n * headings). Field values are parsed as YAML scalars so `2` -> number,\n * `[a, b]` -> array, etc., consistent with frontmatter typing.\n */\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\nimport { extractFrontmatter } from \"./markdown.js\";\n\nconst OPENING = /^---\\r?\\n/;\n// `:name:` or `:name: value` — a docinfo field (value optional). The name may\n// contain spaces but not a colon; the value (if any) may.\nconst FIELD = /^:([^:]+):(?:\\s+(.*\\S))?\\s*$/;\n// A section-title adornment: a line of two or more identical punctuation chars.\nconst ADORN = /^([=\\-~:.'\"*+#_^<>])\\1+$/;\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw field value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // A YAML-typed value can be an array/object, so Ajv may report nested\n // pointers like \"/tags/0\". Walk up to the nearest recorded ancestor.\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\n/**\n * Detect a leading section title — a text line underlined with punctuation,\n * optionally also overlined — after any blank lines. The title is collected as\n * page metadata; `next` is the index where docinfo field-list parsing resumes.\n */\ninterface TitleInfo {\n /** Title text, when a leading section title is present. */\n title?: string;\n /** 1-based source line of the title text. */\n line?: number;\n /** Index of the first line after the title (and its adornment lines). */\n next: number;\n}\n\n/** A run of identical title-adornment punctuation, or null for any other line. */\nfunction adornment(line: string): { char: string; length: number } | null {\n const m = ADORN.exec(line);\n return m && m[1] != null ? { char: m[1], length: line.length } : null;\n}\n\nfunction parseTitle(lines: string[]): TitleInfo {\n let i = 0;\n while (i < lines.length && (lines[i] ?? \"\").trim() === \"\") i++;\n if (i >= lines.length) return { next: i };\n\n const first = lines[i] ?? \"\";\n // A field line starts the docinfo block, not a title.\n if (FIELD.test(first)) return { next: i };\n\n const over = adornment(first);\n if (over) {\n // Over- and under-lined: adornment / title text / matching adornment. RST\n // requires the over- and underline to use the same character and length,\n // and to be at least as long as the title text.\n const text = lines[i + 1] ?? \"\";\n const under = adornment(lines[i + 2] ?? \"\");\n if (\n text.trim() !== \"\" &&\n !FIELD.test(text) &&\n under != null &&\n under.char === over.char &&\n under.length === over.length &&\n over.length >= text.trim().length\n ) {\n return { title: text.trim(), line: i + 2, next: i + 3 };\n }\n // A lone adornment that isn't a valid overlined title — not metadata.\n return { next: i };\n }\n\n // Underlined: title text / adornment at least as long as the title.\n const under = adornment(lines[i + 1] ?? \"\");\n if (under != null && under.length >= first.trim().length) {\n return { title: first.trim(), line: i + 1, next: i + 2 };\n }\n\n return { next: i };\n}\n\n/**\n * Parse the native reStructuredText page metadata: a leading section title\n * (collected as `title`) followed by the docinfo field list. An explicit\n * `:title:` field takes precedence over the heading.\n */\nfunction extractDocinfo(content: string): ExtractedMetadata {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n const lines = body.split(/\\r?\\n/);\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n // First source line of the metadata block (title or, failing that, a field).\n let blockStart = -1;\n\n const titleInfo = parseTitle(lines);\n if (titleInfo.title != null && titleInfo.line != null) {\n data.title = titleInfo.title;\n map.set(\"/title\", titleInfo.line);\n blockStart = titleInfo.line;\n }\n\n // Skip blank lines between the title and the field list.\n let i = titleInfo.next;\n while (i < lines.length && (lines[i] ?? \"\").trim() === \"\") i++;\n\n for (; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n // The field list ends at the first blank or non-field line.\n if (line.trim() === \"\") break;\n const field = FIELD.exec(line);\n if (!field || field[1] == null) break;\n\n const name = field[1].trim();\n const value = field[2] === undefined ? true : typeValue(field[2]);\n if (blockStart === -1) blockStart = i + 1;\n data[name] = value;\n map.set(`/${escapePointerSegment(name)}`, i + 1);\n }\n\n const present = blockStart !== -1;\n // Root pointer maps to the block start. When no metadata is present we record\n // nothing, so `lineFor` reports unknown rather than misleadingly annotating\n // missing-metadata errors at line 1.\n if (present) map.set(\"\", blockStart);\n\n return {\n data,\n present,\n format: \"rst\",\n lineFor: lineForFactory(map),\n };\n}\n\nexport const rstExtractor: MetadataExtractor = {\n name: \"rst\",\n extensions: [\".rst\"],\n implemented: true,\n extract(content) {\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n if (OPENING.test(body)) {\n // Delegate only when a complete frontmatter block is actually present;\n // a stray opening `---` with no closing delimiter should not shadow a\n // native docinfo field list that follows.\n const fm = extractFrontmatter(content, \"rst\");\n if (fm.present) return fm;\n }\n return extractDocinfo(content);\n },\n};\n","/**\n * XML metadata extractor.\n *\n * Reads metadata from the document's root-element attributes, e.g.\n * `<document type=\"concept\" version=\"2\">` yields `{ type: \"concept\", version: 2 }`.\n * Attribute values are parsed as YAML scalars so `\"2\"` -> number and `\"true\"` ->\n * boolean, consistent with the AsciiDoc header extractor. Namespace declarations\n * (`xmlns`, `xmlns:*`) are dropped as transport noise. Per-node line numbers from\n * the parser give a JSON-Pointer -> source-line map for precise annotations.\n *\n * Malformed XML is surfaced as a thrown error; the command layer records it as a\n * per-file failure so the rest of the run continues (mirroring frontmatter).\n */\nimport { DOMParser } from \"@xmldom/xmldom\";\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw attribute value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n // An explicitly empty attribute (`title=\"\"`) is the empty string, not the\n // YAML `null` that parsing \"\" would yield.\n if (raw === \"\") return \"\";\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor (e.g. a nested Ajv pointer).\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\nexport const xmlExtractor: MetadataExtractor = {\n name: \"xml\",\n extensions: [\".xml\"],\n implemented: true,\n extract(content): ExtractedMetadata {\n // A BOM stays part of line 1; it doesn't shift line numbers.\n const body = content.charCodeAt(0) === 0xfeff ? content.slice(1) : content;\n\n const errors: string[] = [];\n const doc = new DOMParser({\n onError: (level, msg) => {\n if (level === \"error\" || level === \"fatalError\") errors.push(msg);\n },\n }).parseFromString(body, \"text/xml\");\n\n if (errors.length > 0) {\n throw new Error(`Invalid XML: ${errors[0] ?? \"parse error\"}`);\n }\n\n const root = doc.documentElement;\n if (!root) {\n return { data: {}, present: false, format: \"xml\", lineFor: () => undefined };\n }\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n const rootLine = root.lineNumber ?? 1;\n map.set(\"\", rootLine);\n\n const attrs = root.attributes;\n for (let i = 0; i < attrs.length; i++) {\n const attr = attrs.item(i);\n if (!attr) continue;\n const name = attr.name;\n // Namespace declarations describe the document, not its metadata.\n if (name === \"xmlns\" || name.startsWith(\"xmlns:\")) continue;\n data[name] = typeValue(attr.value);\n map.set(`/${escapePointerSegment(name)}`, attr.lineNumber ?? rootLine);\n }\n\n const present = Object.keys(data).length > 0;\n return { data, present, format: \"xml\", lineFor: lineForFactory(map) };\n },\n};\n","/**\n * HTML metadata extractor.\n *\n * Reads document metadata from `<meta>` tags and `<title>`:\n * - `<title>…</title>` -> `title` (the text content, kept verbatim).\n * - `<meta name=\"X\" content=\"Y\">` (or `property=\"X\"` for OpenGraph-style tags)\n * -> `X: Y`. `content` values are parsed as YAML scalars so `\"2\"` -> number\n * and `\"true\"` -> boolean, consistent with the AsciiDoc/XML extractors.\n *\n * Tags with neither `name` nor `property` (e.g. `charset`, `http-equiv`) carry no\n * document metadata and are skipped. Duplicate keys: last tag wins; the first\n * `<title>` wins. The parser (parse5) decodes HTML entities and recovers from\n * malformed markup, so extraction never throws. Per-node line numbers give a\n * JSON-Pointer -> source-line map for annotations.\n */\nimport { parse, defaultTreeAdapter, type DefaultTreeAdapterMap } from \"parse5\";\nimport { parse as parseYamlScalar } from \"yaml\";\nimport type { ExtractedMetadata, MetadataExtractor } from \"../types.js\";\n\ntype ChildNode = DefaultTreeAdapterMap[\"childNode\"];\ntype Element = DefaultTreeAdapterMap[\"element\"];\n\nfunction escapePointerSegment(key: string): string {\n return key.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\n\n/** Parse a raw value as a YAML scalar, falling back to the string. */\nfunction typeValue(raw: string): unknown {\n // Empty meta content (`content=\"\"`) is the empty string, not the YAML `null`\n // that parsing \"\" would yield.\n if (raw === \"\") return \"\";\n try {\n return parseYamlScalar(raw);\n } catch {\n return raw;\n }\n}\n\nfunction lineForFactory(\n map: Map<string, number>,\n): (pointer: string) => number | undefined {\n return (pointer: string) => {\n // A bare top-level key (e.g. \"type\") maps to its \"/type\" JSON pointer.\n const start =\n pointer !== \"\" && !pointer.startsWith(\"/\")\n ? `/${escapePointerSegment(pointer)}`\n : pointer;\n if (map.has(start)) return map.get(start);\n // Walk up to the nearest recorded ancestor (e.g. a nested Ajv pointer).\n let p = start;\n while (p.length > 0) {\n const idx = p.lastIndexOf(\"/\");\n if (idx < 0) break;\n p = p.slice(0, idx);\n if (map.has(p)) return map.get(p);\n }\n return map.get(\"\");\n };\n}\n\nfunction attrValue(el: Element, name: string): string | undefined {\n return el.attrs.find((a) => a.name === name)?.value;\n}\n\nexport const htmlExtractor: MetadataExtractor = {\n name: \"html\",\n extensions: [\".html\", \".htm\"],\n implemented: true,\n extract(content): ExtractedMetadata {\n const doc = parse(content, { sourceCodeLocationInfo: true });\n\n const data: Record<string, unknown> = {};\n const map = new Map<string, number>();\n // The document node has no location; anchor the root pointer at line 1.\n map.set(\"\", 1);\n\n const setKey = (key: string, value: unknown, line: number | undefined): void => {\n data[key] = value;\n if (line != null) map.set(`/${escapePointerSegment(key)}`, line);\n };\n\n const visit = (node: ChildNode): void => {\n if (defaultTreeAdapter.isElementNode(node)) {\n const line = node.sourceCodeLocation?.startLine;\n if (node.tagName === \"title\") {\n // The first <title> wins; later ones (e.g. in SVG) are ignored.\n if (data.title === undefined) {\n const first = node.childNodes[0];\n const text =\n first && defaultTreeAdapter.isTextNode(first) ? first.value : \"\";\n setKey(\"title\", text, line);\n }\n } else if (node.tagName === \"meta\") {\n const key = attrValue(node, \"name\") ?? attrValue(node, \"property\");\n const value = attrValue(node, \"content\");\n if (key != null && value != null) {\n setKey(key, typeValue(value), line);\n }\n }\n }\n if (defaultTreeAdapter.isElementNode(node)) {\n for (const child of node.childNodes) visit(child);\n }\n };\n\n for (const child of doc.childNodes) visit(child);\n\n const present = Object.keys(data).length > 0;\n return { data, present, format: \"html\", lineFor: lineForFactory(map) };\n },\n};\n","/**\n * Extractor registry. Maps file extensions to extractors and resolves an\n * extractor by name (for the `--as` override). Roadmap stubs are registered so\n * detection can report them clearly, but only implemented extractors count as\n * \"supported\" for directory walks.\n */\nimport type { MetadataExtractor } from \"../types.js\";\nimport { markdownExtractor } from \"./markdown.js\";\nimport { mdxExtractor } from \"./mdx.js\";\nimport { asciidocExtractor } from \"./asciidoc.js\";\nimport { rstExtractor } from \"./rst.js\";\nimport { xmlExtractor } from \"./xml.js\";\nimport { htmlExtractor } from \"./html.js\";\n\nexport const EXTRACTORS: MetadataExtractor[] = [\n markdownExtractor,\n mdxExtractor,\n asciidocExtractor,\n rstExtractor,\n xmlExtractor,\n htmlExtractor,\n];\n\nconst byExtension = new Map<string, MetadataExtractor>();\nconst byName = new Map<string, MetadataExtractor>();\nfor (const ex of EXTRACTORS) {\n byName.set(ex.name, ex);\n for (const ext of ex.extensions) byExtension.set(ext.toLowerCase(), ex);\n}\n\n/** Resolve an implemented extractor for a file extension (incl. dot). */\nexport function extractorForExtension(\n ext: string,\n): MetadataExtractor | undefined {\n const ex = byExtension.get(ext.toLowerCase());\n return ex?.implemented ? ex : undefined;\n}\n\n/** Resolve an extractor by its `--as` name (implemented or not). */\nexport function extractorByName(name: string): MetadataExtractor | undefined {\n return byName.get(name.toLowerCase());\n}\n\n/** Extensions handled by implemented extractors (used for directory walks). */\nexport function supportedExtensions(): string[] {\n return EXTRACTORS.filter((e) => e.implemented).flatMap((e) => e.extensions);\n}\n\n/** All registered format names, with their implemented status. */\nexport function listFormats(): { name: string; extensions: string[]; implemented: boolean }[] {\n return EXTRACTORS.map((e) => ({\n name: e.name,\n extensions: e.extensions,\n implemented: e.implemented,\n }));\n}\n","/**\n * Resolve a mix of explicit files, directories, and globs into a concrete,\n * de-duplicated, sorted list of file paths (posix-style, relative to cwd).\n * Directory and glob expansion is restricted to the given extensions; explicit\n * file arguments are always included so the user can target any single file.\n */\nimport { stat } from \"node:fs/promises\";\nimport { extname, relative, resolve } from \"node:path\";\nimport fg from \"fast-glob\";\nimport { supportedExtensions } from \"../extractors/index.js\";\n\nconst DEFAULT_IGNORE = [\"**/node_modules/**\", \"**/.git/**\"];\n\nexport const STDIN_TOKEN = \"-\";\n\nfunction toPosix(p: string): string {\n return p.replace(/\\\\/g, \"/\");\n}\n\nasync function statOrNull(p: string) {\n try {\n return await stat(p);\n } catch {\n return null;\n }\n}\n\nexport interface ResolveOptions {\n /** Positional inputs: files, directories, or globs. `-` is ignored here. */\n inputs: string[];\n /** Extensions to keep during dir/glob expansion (default: supported). */\n exts?: string[];\n /** Extra exclude globs (added to node_modules/.git defaults). */\n exclude?: string[];\n cwd?: string;\n}\n\nexport async function resolveTargets(opts: ResolveOptions): Promise<string[]> {\n const cwd = opts.cwd ?? process.cwd();\n const exts = (opts.exts ?? supportedExtensions()).map((e) =>\n e.toLowerCase().startsWith(\".\") ? e.toLowerCase() : `.${e.toLowerCase()}`,\n );\n const ignore = [...DEFAULT_IGNORE, ...(opts.exclude ?? [])];\n const out = new Set<string>();\n\n const keepByExt = (file: string): boolean =>\n exts.includes(extname(file).toLowerCase());\n\n for (const input of opts.inputs) {\n if (input === STDIN_TOKEN) continue;\n\n const abs = resolve(cwd, input);\n const st = await statOrNull(abs);\n\n if (st?.isFile()) {\n out.add(toPosix(relative(cwd, abs)));\n continue;\n }\n\n if (st?.isDirectory()) {\n const found = await fg(`${toPosix(input)}/**/*`, {\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n });\n for (const f of found) if (keepByExt(f)) out.add(f);\n continue;\n }\n\n // Treat as a glob pattern.\n const found = await fg(toPosix(input), {\n cwd,\n ignore,\n onlyFiles: true,\n dot: false,\n });\n for (const f of found) if (keepByExt(f)) out.add(f);\n }\n\n return [...out].sort();\n}\n","/**\n * `get` command core. Prints one or more metadata field values from each file.\n * Input handling (positional paths, globs, directories, `-` for stdin, and\n * config `paths:` fallback) mirrors `validate` so the two commands behave\n * identically.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { resolve, extname } from \"node:path\";\nimport { DocmetaError } from \"../types.js\";\nimport {\n extractorByName,\n extractorForExtension,\n supportedExtensions,\n} from \"../extractors/index.js\";\nimport { resolveTargets, STDIN_TOKEN } from \"../core/load-files.js\";\nimport { loadConfig, type DocmetaConfig } from \"../core/config.js\";\n\nexport interface GetOptions {\n fields: string[];\n inputs: string[];\n as?: string;\n exclude?: string[];\n exts?: string[];\n configPath?: string;\n cwd?: string;\n /** Content for the `-` (stdin) input, injected by the CLI/tests. */\n stdinContent?: string;\n}\n\nexport interface GetFileResult {\n file: string;\n present: boolean;\n values: Record<string, unknown>;\n}\n\nexport async function runGet(opts: GetOptions): Promise<GetFileResult[]> {\n const cwd = opts.cwd ?? process.cwd();\n if (opts.fields.length === 0) {\n throw new DocmetaError(\"Specify at least one field to get.\");\n }\n\n const loaded = await loadConfig(opts.configPath, cwd);\n const config: DocmetaConfig | null = loaded?.config ?? null;\n\n // Determine inputs: explicit CLI inputs win, else config.paths.\n const inputs = opts.inputs.length > 0 ? opts.inputs : (config?.paths ?? []);\n const usingStdin = inputs.includes(STDIN_TOKEN);\n\n if (inputs.length === 0) {\n throw new DocmetaError(\n \"No files to read. Pass paths/globs, or add `paths:` to docmeta.config.yaml.\",\n );\n }\n\n const forced = opts.as ? extractorByName(opts.as) : undefined;\n if (opts.as && !forced) {\n throw new DocmetaError(\n `Unknown format \"${opts.as}\". Supported extensions: ${supportedExtensions().join(\", \")}.`,\n );\n }\n\n const exts = opts.exts ?? (forced ? forced.extensions : undefined);\n const fileInputs = inputs.filter((i) => i !== STDIN_TOKEN);\n const files = await resolveTargets({\n inputs: fileInputs,\n exts,\n exclude: [...(config?.exclude ?? []), ...(opts.exclude ?? [])],\n cwd,\n });\n\n const out: GetFileResult[] = [];\n\n const readOne = (label: string, content: string, extension: string): void => {\n const extractor = forced ?? extractorForExtension(extension);\n if (!extractor) {\n throw new DocmetaError(\n `Unsupported file type \"${extension}\" for \"${label}\". Supported: ${supportedExtensions().join(\", \")}. Use --as to override.`,\n );\n }\n const extracted = extractor.extract(content, label);\n const values: Record<string, unknown> = {};\n for (const f of opts.fields) values[f] = resolveField(extracted.data, f);\n out.push({ file: label, present: extracted.present, values });\n };\n\n if (usingStdin) {\n if (!forced) {\n throw new DocmetaError(\n \"Reading from stdin (`-`) requires --as <format> to choose an extractor.\",\n );\n }\n readOne(\"<stdin>\", opts.stdinContent ?? \"\", forced.extensions[0] ?? \"\");\n }\n\n for (const file of files) {\n const content = await readFile(resolve(cwd, file), \"utf8\");\n readOne(file, content, extname(file));\n }\n\n return out;\n}\n\n/**\n * Resolve a single field reference against extracted metadata.\n *\n * A reference starting with `/` is a JSON Pointer (RFC 6901) — the same\n * convention the validator and reporters already use for nested error paths,\n * so a pointer copied from a validation error works verbatim. Any other\n * reference is dot-notation (`author.name`, `tags.0`). Pointers also escape\n * keys that contain literal dots or slashes (`/odd.key`, `/a~1b` for `a/b`).\n *\n * Returns `undefined` when any segment is missing or descends into a scalar.\n * A bare top-level key (no `/`, no `.`) resolves to a single segment, so the\n * historical `get title` behavior is unchanged.\n */\nfunction resolveField(data: Record<string, unknown>, field: string): unknown {\n const segments = field.startsWith(\"/\")\n ? parseJsonPointer(field)\n : field.split(\".\");\n let current: unknown = data;\n for (const segment of segments) {\n if (Array.isArray(current)) {\n if (!/^\\d+$/.test(segment)) return undefined;\n current = current[Number(segment)];\n } else if (current !== null && typeof current === \"object\") {\n // Own-property check only: never resolve inherited members like\n // `toString` or `__proto__` — those are \"missing\", not values.\n if (!Object.prototype.hasOwnProperty.call(current, segment)) {\n return undefined;\n }\n current = (current as Record<string, unknown>)[segment];\n } else {\n return undefined;\n }\n }\n return current;\n}\n\n/** Decode a JSON Pointer into path segments, unescaping `~1`→`/` and `~0`→`~`. */\nfunction parseJsonPointer(pointer: string): string[] {\n return pointer\n .split(\"/\")\n .slice(1)\n .map((s) => s.replace(/~1/g, \"/\").replace(/~0/g, \"~\"));\n}\n","/**\n * `schemas` command core. Reports built-in schemas and supported input formats.\n */\nimport { listBuiltins, type BuiltinInfo } from \"../core/schema-registry.js\";\nimport { listFormats } from \"../extractors/index.js\";\n\nexport interface SchemasInfo {\n builtins: BuiltinInfo[];\n formats: { name: string; extensions: string[]; implemented: boolean }[];\n}\n\nexport function getSchemasInfo(): SchemasInfo {\n return { builtins: listBuiltins(), formats: listFormats() };\n}\n","import pc from \"picocolors\";\n\nexport type Colors = ReturnType<typeof pc.createColors>;\n\n/** Build a picocolors palette with color explicitly on or off. */\nexport function palette(enabled: boolean): Colors {\n return pc.createColors(enabled);\n}\n\n/**\n * Decide whether to emit ANSI color: off when `--no-color`/`NO_COLOR`, on only\n * for a TTY otherwise. `forced` (from `--color`) overrides detection.\n */\nexport function shouldColor(opts: {\n noColor?: boolean;\n isTTY?: boolean;\n env?: NodeJS.ProcessEnv;\n}): boolean {\n const env = opts.env ?? process.env;\n if (opts.noColor) return false;\n if (env.NO_COLOR != null && env.NO_COLOR !== \"\") return false;\n return Boolean(opts.isTTY);\n}\n","/**\n * Reporters render validation results to a string. The command layer writes\n * the result to stdout; diagnostics go to stderr separately.\n */\nimport type { RunSummary, ValidationResult } from \"../types.js\";\nimport { palette } from \"./color.js\";\n\nexport type ReportFormat = \"pretty\" | \"json\" | \"github\";\n\nexport interface ReportOptions {\n color?: boolean;\n /** In pretty output, omit passing files. */\n quiet?: boolean;\n}\n\nfunction fieldLabel(instancePath: string): string {\n return instancePath === \"\" ? \"(root)\" : instancePath;\n}\n\nexport function renderPretty(\n results: ValidationResult[],\n summary: RunSummary,\n opts: ReportOptions = {},\n): string {\n const c = palette(opts.color ?? false);\n const lines: string[] = [];\n\n for (const r of results) {\n if (r.ok) {\n if (!opts.quiet) lines.push(`${c.green(\"✓\")} ${r.file}`);\n continue;\n }\n lines.push(`${c.red(\"✗\")} ${r.file}`);\n for (const e of r.errors) {\n const loc = e.line != null ? c.dim(` (line ${e.line})`) : \"\";\n lines.push(\n ` ${c.cyan(fieldLabel(e.instancePath))} ${e.message}${loc} ${c.dim(\n `[${e.schema}]`,\n )}`,\n );\n }\n }\n\n const summaryText = `${summary.files} file${summary.files === 1 ? \"\" : \"s\"} checked, ${summary.passed} passed, ${summary.failed} failed, ${summary.errors} error${summary.errors === 1 ? \"\" : \"s\"}`;\n if (lines.length > 0) lines.push(\"\");\n lines.push(summary.failed > 0 ? c.red(summaryText) : c.green(summaryText));\n return lines.join(\"\\n\");\n}\n\nexport function renderJson(\n results: ValidationResult[],\n summary: RunSummary,\n): string {\n return JSON.stringify({ summary, results }, null, 2);\n}\n\nexport function renderGithub(results: ValidationResult[]): string {\n const lines: string[] = [];\n for (const r of results) {\n for (const e of r.errors) {\n const params = [`file=${r.file}`];\n if (e.line != null) params.push(`line=${e.line}`);\n if (e.col != null) params.push(`col=${e.col}`);\n const msg = `[${e.schema}] ${fieldLabel(e.instancePath)} ${e.message}`;\n lines.push(`::error ${params.join(\",\")}::${msg}`);\n }\n }\n return lines.join(\"\\n\");\n}\n\nexport function render(\n format: ReportFormat,\n results: ValidationResult[],\n summary: RunSummary,\n opts: ReportOptions = {},\n): string {\n switch (format) {\n case \"json\":\n return renderJson(results, summary);\n case \"github\":\n return renderGithub(results);\n case \"pretty\":\n default:\n return renderPretty(results, summary, opts);\n }\n}\n"],"mappings":"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","names":["readFile","readFile","readFile","resolve","extname","OPENING","escapePointerSegment","lineForFactory","parseYamlScalar","OPENING","escapePointerSegment","typeValue","parseYamlScalar","lineForFactory","under","parseYamlScalar","escapePointerSegment","typeValue","lineForFactory","parseYamlScalar","escapePointerSegment","typeValue","lineForFactory","resolve","resolve","found","readFile","resolve","extname","readFile","resolve","extname","readFile","resolve","extname"]}
|
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
runGet,
|
|
8
8
|
runValidate,
|
|
9
9
|
shouldColor
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-DLQ4BV2J.js";
|
|
11
11
|
|
|
12
12
|
// src/cli.ts
|
|
13
13
|
import { realpathSync } from "fs";
|
|
@@ -17,7 +17,7 @@ import { Command } from "commander";
|
|
|
17
17
|
// package.json
|
|
18
18
|
var package_default = {
|
|
19
19
|
name: "docmeta",
|
|
20
|
-
version: "1.
|
|
20
|
+
version: "1.1.0",
|
|
21
21
|
description: "Validate the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema. CI-friendly.",
|
|
22
22
|
type: "module",
|
|
23
23
|
bin: {
|
|
@@ -73,6 +73,9 @@ var package_default = {
|
|
|
73
73
|
"okf"
|
|
74
74
|
],
|
|
75
75
|
license: "MIT",
|
|
76
|
+
overrides: {
|
|
77
|
+
esbuild: "^0.28.1"
|
|
78
|
+
},
|
|
76
79
|
dependencies: {
|
|
77
80
|
"@xmldom/xmldom": "^0.9.10",
|
|
78
81
|
ajv: "^8.17.1",
|
|
@@ -194,6 +197,7 @@ function buildProgram() {
|
|
|
194
197
|
"",
|
|
195
198
|
"Examples:",
|
|
196
199
|
" docmeta get title,type docs/intro.md",
|
|
200
|
+
" docmeta get author.name,/author/email docs/intro.md",
|
|
197
201
|
' docmeta get type "**/*.md" -f json',
|
|
198
202
|
" cat page.md | docmeta get title - --as markdown"
|
|
199
203
|
].join("\n")
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["/**\n * docmeta CLI. Thin commander wrapper over the command cores. Follows clig.dev:\n * primary output to stdout, diagnostics to stderr, color only on a TTY (and\n * never when NO_COLOR/--no-color), meaningful exit codes (0 ok, 1 validation\n * failures, 2 operational/usage errors).\n */\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { DocmetaError } from \"./types.js\";\nimport { runValidate } from \"./commands/validate.js\";\nimport { runGet } from \"./commands/get.js\";\nimport { getSchemasInfo } from \"./commands/schemas.js\";\nimport { render, type ReportFormat } from \"./reporters/index.js\";\nimport { shouldColor, palette } from \"./reporters/color.js\";\n\nfunction collect(value: string, prev: string[]): string[] {\n return prev.concat([value]);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nfunction fail(err: unknown): never {\n const msg =\n err instanceof DocmetaError\n ? err.message\n : `Unexpected error: ${(err as Error).message}`;\n process.stderr.write(`docmeta: ${msg}\\n`);\n process.exit(2);\n}\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n return shouldColor({ noColor, isTTY: Boolean(process.stdout.isTTY) });\n}\n\nfunction stringifyValue(v: unknown): string {\n if (v === undefined) return \"(unset)\";\n if (typeof v === \"string\") return v;\n return JSON.stringify(v);\n}\n\nconst REPORT_FORMATS = new Set([\"pretty\", \"json\", \"github\"]);\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"docmeta\")\n .description(\n \"Validate the presence and format of document metadata against JSON Schema.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n .showHelpAfterError();\n\n program\n .command(\"validate\", { isDefault: true })\n .description(\"Validate metadata in the given files/dirs/globs\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to validate (use - for stdin)\",\n )\n .option(\n \"-s, --schema <ref>\",\n \"schema to validate against; repeatable; overrides $schema/config\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\"-f, --format <format>\", \"output: pretty | json | github\", \"pretty\")\n .option(\"-c, --config <path>\", \"path to a docmeta config file\")\n .option(\"-q, --quiet\", \"in pretty output, hide passing files\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" docmeta validate docs/ # walk a directory\",\n ' docmeta validate \"**/*.md\" -f github # CI annotations',\n \" docmeta validate page.md -s google:okf:0.1 -s ./my.schema.json\",\n \" cat page.md | docmeta validate - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options, command: Command) => {\n try {\n const format = options.format as ReportFormat;\n if (!REPORT_FORMATS.has(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use pretty, json, or github.`,\n );\n }\n const exts: string[] | undefined = options.ext\n ? String(options.ext)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const { results, summary } = await runValidate({\n inputs: paths,\n cliSchemas: options.schema,\n exts,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n stdinContent,\n });\n\n const color = resolveColor(command.parent ?? command);\n const text = render(format, results, summary, {\n color,\n quiet: Boolean(options.quiet),\n });\n if (text.length > 0) process.stdout.write(`${text}\\n`);\n process.exitCode = summary.failed > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"get\")\n .description(\n \"Print metadata field values from the given files/dirs/globs\",\n )\n .argument(\"<fields>\", \"comma-separated metadata fields to print\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to read (use - for stdin)\",\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .option(\"-c, --config <path>\", \"path to a docmeta config file\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" docmeta get title,type docs/intro.md\",\n ' docmeta get type \"**/*.md\" -f json',\n \" cat page.md | docmeta get title - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (fieldsArg: string, paths: string[], options, command: Command) => {\n try {\n const format = options.format as string;\n if (format !== \"pretty\" && format !== \"json\") {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use pretty or json.`,\n );\n }\n const fields = String(fieldsArg)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const exts: string[] | undefined = options.ext\n ? String(options.ext)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const results = await runGet({\n fields,\n inputs: paths,\n as: options.as,\n exclude: options.exclude,\n exts,\n configPath: options.config,\n stdinContent,\n });\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n } else {\n const c = palette(resolveColor(command.parent ?? command));\n for (const r of results) {\n for (const f of fields) {\n process.stdout.write(\n `${c.dim(`${r.file}:`)} ${f}=${stringifyValue(r.values[f])}\\n`,\n );\n }\n }\n }\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"schemas\")\n .description(\"List built-in schemas and supported input formats\")\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action((options, command: Command) => {\n const info = getSchemasInfo();\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(info, null, 2)}\\n`);\n return;\n }\n const c = palette(resolveColor(command.parent ?? command));\n const lines: string[] = [c.bold(\"Built-in schemas:\")];\n for (const b of info.builtins) {\n lines.push(` ${c.cyan(b.id)} ${c.dim(\"—\")} ${b.title}`);\n }\n lines.push(\"\", c.bold(\"Input formats:\"));\n for (const f of info.formats) {\n const tag = f.implemented ? c.green(\"implemented\") : c.dim(\"planned\");\n lines.push(` ${f.name} (${f.extensions.join(\", \")}) [${tag}]`);\n }\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n });\n\n return program;\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const program = buildProgram();\n await program.parseAsync(argv);\n}\n\n/** Run only when executed directly (not when imported by tests). */\nfunction isMainModule(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n return realpathSync(entry) === fileURLToPath(import.meta.url);\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n main().catch(fail);\n}\n","{\n \"name\": \"docmeta\",\n \"version\": \"1.0.0\",\n \"description\": \"Validate the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema. CI-friendly.\",\n \"type\": \"module\",\n \"bin\": {\n \"docmeta\": \"dist/cli.js\"\n },\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/hawkeyexl/docmeta.git\"\n },\n \"homepage\": \"https://hawkeyexl.github.io/docmeta/\",\n \"bugs\": {\n \"url\": \"https://github.com/hawkeyexl/docmeta/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\",\n \"docs:check-cli\": \"node scripts/check-cli-reference.mjs\",\n \"commitlint\": \"commitlint --edit\",\n \"semantic-release\": \"semantic-release\",\n \"prepare\": \"husky\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"frontmatter\",\n \"metadata\",\n \"json-schema\",\n \"markdown\",\n \"validation\",\n \"cli\",\n \"ci\",\n \"okf\"\n ],\n \"license\": \"MIT\",\n \"dependencies\": {\n \"@xmldom/xmldom\": \"^0.9.10\",\n \"ajv\": \"^8.17.1\",\n \"ajv-draft-04\": \"^1.0.0\",\n \"ajv-formats\": \"^3.0.1\",\n \"commander\": \"^15.0.0\",\n \"fast-glob\": \"^3.3.2\",\n \"parse5\": \"^8.0.1\",\n \"picocolors\": \"^1.1.1\",\n \"picomatch\": \"^4.0.4\",\n \"yaml\": \"^2.6.1\"\n },\n \"devDependencies\": {\n \"@commitlint/cli\": \"^21.0.2\",\n \"@commitlint/config-conventional\": \"^21.0.2\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/commit-analyzer\": \"^13.0.1\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/github\": \"^12.0.8\",\n \"@semantic-release/npm\": \"^13.1.5\",\n \"@semantic-release/release-notes-generator\": \"^14.1.1\",\n \"@types/node\": \"^26.0.1\",\n \"@types/picomatch\": \"^4.0.3\",\n \"husky\": \"^9.1.7\",\n \"semantic-release\": \"^25.0.3\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.9\"\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../package.json"],"sourcesContent":["/**\n * docmeta CLI. Thin commander wrapper over the command cores. Follows clig.dev:\n * primary output to stdout, diagnostics to stderr, color only on a TTY (and\n * never when NO_COLOR/--no-color), meaningful exit codes (0 ok, 1 validation\n * failures, 2 operational/usage errors).\n */\nimport { realpathSync } from \"node:fs\";\nimport { fileURLToPath } from \"node:url\";\nimport { Command } from \"commander\";\nimport pkg from \"../package.json\" with { type: \"json\" };\nimport { DocmetaError } from \"./types.js\";\nimport { runValidate } from \"./commands/validate.js\";\nimport { runGet } from \"./commands/get.js\";\nimport { getSchemasInfo } from \"./commands/schemas.js\";\nimport { render, type ReportFormat } from \"./reporters/index.js\";\nimport { shouldColor, palette } from \"./reporters/color.js\";\n\nfunction collect(value: string, prev: string[]): string[] {\n return prev.concat([value]);\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) chunks.push(chunk as Buffer);\n return Buffer.concat(chunks).toString(\"utf8\");\n}\n\nfunction fail(err: unknown): never {\n const msg =\n err instanceof DocmetaError\n ? err.message\n : `Unexpected error: ${(err as Error).message}`;\n process.stderr.write(`docmeta: ${msg}\\n`);\n process.exit(2);\n}\n\nfunction resolveColor(program: Command): boolean {\n // commander maps --no-color to opts.color === false.\n const noColor = program.opts().color === false;\n return shouldColor({ noColor, isTTY: Boolean(process.stdout.isTTY) });\n}\n\nfunction stringifyValue(v: unknown): string {\n if (v === undefined) return \"(unset)\";\n if (typeof v === \"string\") return v;\n return JSON.stringify(v);\n}\n\nconst REPORT_FORMATS = new Set([\"pretty\", \"json\", \"github\"]);\n\nexport function buildProgram(): Command {\n const program = new Command();\n program\n .name(\"docmeta\")\n .description(\n \"Validate the presence and format of document metadata against JSON Schema.\",\n )\n .version(pkg.version, \"-V, --version\")\n .option(\"--no-color\", \"disable colored output\")\n .showHelpAfterError();\n\n program\n .command(\"validate\", { isDefault: true })\n .description(\"Validate metadata in the given files/dirs/globs\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to validate (use - for stdin)\",\n )\n .option(\n \"-s, --schema <ref>\",\n \"schema to validate against; repeatable; overrides $schema/config\",\n collect,\n [],\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\"-f, --format <format>\", \"output: pretty | json | github\", \"pretty\")\n .option(\"-c, --config <path>\", \"path to a docmeta config file\")\n .option(\"-q, --quiet\", \"in pretty output, hide passing files\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" docmeta validate docs/ # walk a directory\",\n ' docmeta validate \"**/*.md\" -f github # CI annotations',\n \" docmeta validate page.md -s google:okf:0.1 -s ./my.schema.json\",\n \" cat page.md | docmeta validate - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (paths: string[], options, command: Command) => {\n try {\n const format = options.format as ReportFormat;\n if (!REPORT_FORMATS.has(format)) {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use pretty, json, or github.`,\n );\n }\n const exts: string[] | undefined = options.ext\n ? String(options.ext)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const { results, summary } = await runValidate({\n inputs: paths,\n cliSchemas: options.schema,\n exts,\n exclude: options.exclude,\n as: options.as,\n configPath: options.config,\n stdinContent,\n });\n\n const color = resolveColor(command.parent ?? command);\n const text = render(format, results, summary, {\n color,\n quiet: Boolean(options.quiet),\n });\n if (text.length > 0) process.stdout.write(`${text}\\n`);\n process.exitCode = summary.failed > 0 ? 1 : 0;\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"get\")\n .description(\n \"Print metadata field values from the given files/dirs/globs\",\n )\n .argument(\"<fields>\", \"comma-separated metadata fields to print\")\n .argument(\n \"[paths...]\",\n \"files, directories, or globs to read (use - for stdin)\",\n )\n .option(\"--ext <list>\", \"comma-separated extensions for directory walks\")\n .option(\"--exclude <glob>\", \"glob to exclude; repeatable\", collect, [])\n .option(\"--as <format>\", \"force an input format (e.g. markdown, mdx)\")\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .option(\"-c, --config <path>\", \"path to a docmeta config file\")\n .addHelpText(\n \"after\",\n [\n \"\",\n \"Examples:\",\n \" docmeta get title,type docs/intro.md\",\n \" docmeta get author.name,/author/email docs/intro.md\",\n ' docmeta get type \"**/*.md\" -f json',\n \" cat page.md | docmeta get title - --as markdown\",\n ].join(\"\\n\"),\n )\n .action(async (fieldsArg: string, paths: string[], options, command: Command) => {\n try {\n const format = options.format as string;\n if (format !== \"pretty\" && format !== \"json\") {\n throw new DocmetaError(\n `Unknown --format \"${format}\". Use pretty or json.`,\n );\n }\n const fields = String(fieldsArg)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n const exts: string[] | undefined = options.ext\n ? String(options.ext)\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean)\n : undefined;\n const stdinContent = paths.includes(\"-\")\n ? await readStdin()\n : undefined;\n\n const results = await runGet({\n fields,\n inputs: paths,\n as: options.as,\n exclude: options.exclude,\n exts,\n configPath: options.config,\n stdinContent,\n });\n if (format === \"json\") {\n process.stdout.write(`${JSON.stringify(results, null, 2)}\\n`);\n } else {\n const c = palette(resolveColor(command.parent ?? command));\n for (const r of results) {\n for (const f of fields) {\n process.stdout.write(\n `${c.dim(`${r.file}:`)} ${f}=${stringifyValue(r.values[f])}\\n`,\n );\n }\n }\n }\n } catch (err) {\n fail(err);\n }\n });\n\n program\n .command(\"schemas\")\n .description(\"List built-in schemas and supported input formats\")\n .option(\"-f, --format <format>\", \"output: pretty | json\", \"pretty\")\n .action((options, command: Command) => {\n const info = getSchemasInfo();\n if (options.format === \"json\") {\n process.stdout.write(`${JSON.stringify(info, null, 2)}\\n`);\n return;\n }\n const c = palette(resolveColor(command.parent ?? command));\n const lines: string[] = [c.bold(\"Built-in schemas:\")];\n for (const b of info.builtins) {\n lines.push(` ${c.cyan(b.id)} ${c.dim(\"—\")} ${b.title}`);\n }\n lines.push(\"\", c.bold(\"Input formats:\"));\n for (const f of info.formats) {\n const tag = f.implemented ? c.green(\"implemented\") : c.dim(\"planned\");\n lines.push(` ${f.name} (${f.extensions.join(\", \")}) [${tag}]`);\n }\n process.stdout.write(`${lines.join(\"\\n\")}\\n`);\n });\n\n return program;\n}\n\nexport async function main(argv: string[] = process.argv): Promise<void> {\n const program = buildProgram();\n await program.parseAsync(argv);\n}\n\n/** Run only when executed directly (not when imported by tests). */\nfunction isMainModule(): boolean {\n const entry = process.argv[1];\n if (!entry) return false;\n try {\n return realpathSync(entry) === fileURLToPath(import.meta.url);\n } catch {\n return false;\n }\n}\n\nif (isMainModule()) {\n main().catch(fail);\n}\n","{\n \"name\": \"docmeta\",\n \"version\": \"1.1.0\",\n \"description\": \"Validate the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema. CI-friendly.\",\n \"type\": \"module\",\n \"bin\": {\n \"docmeta\": \"dist/cli.js\"\n },\n \"main\": \"dist/index.js\",\n \"module\": \"dist/index.js\",\n \"types\": \"dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n },\n \"./package.json\": \"./package.json\"\n },\n \"files\": [\n \"dist\"\n ],\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/hawkeyexl/docmeta.git\"\n },\n \"homepage\": \"https://hawkeyexl.github.io/docmeta/\",\n \"bugs\": {\n \"url\": \"https://github.com/hawkeyexl/docmeta/issues\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"engines\": {\n \"node\": \">=24\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"test\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"typecheck\": \"tsc --noEmit\",\n \"docs:check-cli\": \"node scripts/check-cli-reference.mjs\",\n \"commitlint\": \"commitlint --edit\",\n \"semantic-release\": \"semantic-release\",\n \"prepare\": \"husky\",\n \"prepublishOnly\": \"npm run build\"\n },\n \"keywords\": [\n \"frontmatter\",\n \"metadata\",\n \"json-schema\",\n \"markdown\",\n \"validation\",\n \"cli\",\n \"ci\",\n \"okf\"\n ],\n \"license\": \"MIT\",\n \"overrides\": {\n \"esbuild\": \"^0.28.1\"\n },\n \"dependencies\": {\n \"@xmldom/xmldom\": \"^0.9.10\",\n \"ajv\": \"^8.17.1\",\n \"ajv-draft-04\": \"^1.0.0\",\n \"ajv-formats\": \"^3.0.1\",\n \"commander\": \"^15.0.0\",\n \"fast-glob\": \"^3.3.2\",\n \"parse5\": \"^8.0.1\",\n \"picocolors\": \"^1.1.1\",\n \"picomatch\": \"^4.0.4\",\n \"yaml\": \"^2.6.1\"\n },\n \"devDependencies\": {\n \"@commitlint/cli\": \"^21.0.2\",\n \"@commitlint/config-conventional\": \"^21.0.2\",\n \"@semantic-release/changelog\": \"^6.0.3\",\n \"@semantic-release/commit-analyzer\": \"^13.0.1\",\n \"@semantic-release/git\": \"^10.0.1\",\n \"@semantic-release/github\": \"^12.0.8\",\n \"@semantic-release/npm\": \"^13.1.5\",\n \"@semantic-release/release-notes-generator\": \"^14.1.1\",\n \"@types/node\": \"^26.0.1\",\n \"@types/picomatch\": \"^4.0.3\",\n \"husky\": \"^9.1.7\",\n \"semantic-release\": \"^25.0.3\",\n \"tsup\": \"^8.3.5\",\n \"typescript\": \"^6.0.3\",\n \"vitest\": \"^4.1.9\"\n }\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docmeta",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Validate the presence and format of document metadata (Markdown frontmatter and more) against JSON Schema. CI-friendly.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -56,6 +56,9 @@
|
|
|
56
56
|
"okf"
|
|
57
57
|
],
|
|
58
58
|
"license": "MIT",
|
|
59
|
+
"overrides": {
|
|
60
|
+
"esbuild": "^0.28.1"
|
|
61
|
+
},
|
|
59
62
|
"dependencies": {
|
|
60
63
|
"@xmldom/xmldom": "^0.9.10",
|
|
61
64
|
"ajv": "^8.17.1",
|