markdown-schema 0.2.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.
- package/.claude/skills/markdown-schema/SKILL.md +282 -0
- package/.claude/skills/markdown-schema/markdown-schema.guideline.md +419 -0
- package/LICENSE +21 -0
- package/README.md +720 -0
- package/dist/bin/validate-md.js +1127 -0
- package/dist/bin/validate-md.js.map +1 -0
- package/dist/index.d.ts +296 -0
- package/dist/index.js +1039 -0
- package/dist/index.js.map +1 -0
- package/dist/node.d.ts +17 -0
- package/dist/node.js +18 -0
- package/dist/node.js.map +1 -0
- package/package.json +72 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index/parse-template/infer-section/freetext.ts","../src/index/parse-template/_shared/extract-directive-body.ts","../src/index/parse-template/infer-section/table.ts","../src/index/parse-template/infer-section/bullet-list.ts","../src/index/parse-template/infer-section/task-list.ts","../src/index/code-blocks.ts","../src/index/raw-nodes.ts","../src/index/parse-template/infer-section/optional.ts","../src/index/fenced-code-with-marker.ts","../src/index/parse-template/infer-section/repeated/repeated-where.ts","../src/index/parse-template/infer-section/repeated.ts","../src/index/parse-template/define-doc-schema.ts","../src/index/parse-template/define-doc-schema/split-doc.ts","../src/index/parse-template/define-doc-schema/split-doc/extract-frontmatter.ts","../src/index/parse-template.ts","../src/index/parse-template/infer-section.ts","../src/index/parse-template/_shared/parse-directive/_shared/split-escaped-choices.ts","../src/index/parse-template/_shared/parse-directive/parse-enum.ts","../src/index/parse-template/_shared/parse-directive/parse-field.ts","../src/index/parse-template/_shared/directive-error.ts","../src/index/parse-template/_shared/parse-directive/parse-freetext-directive.ts","../src/index/parse-template/_shared/parse-directive/parse-guide.ts","../src/index/parse-template/_shared/parse-directive/parse-row-directive/parse-column-spec.ts","../src/index/parse-template/_shared/parse-directive/parse-row-directive.ts","../src/index/parse-template/_shared/parse-directive/parse-section-directive.ts","../src/index/parse-template/_shared/parse-directive.ts","../src/index/parse-template/infer-section/build-row-schema.ts","../src/index/parse-template/_shared/compile-user-regex.ts","../src/index/parse-template/infer-section/parse-block-directives/block-html-nodes.ts","../src/index/parse-template/infer-section/parse-block-directives.ts","../src/index/parse-template/infer-section/find-directive.ts","../src/index/parse-template/_shared/collect-item-directives.ts","../src/index/parse-template/infer-section/is-labeled-list.ts","../src/index/parse-template/infer-section/is-task-list.ts","../src/index/parse-template/infer-section/build-labeled-list-schema.ts","../src/index/parse-template/infer-section/build-repeated-schema.ts","../src/index/parse-template/infer-section/directive-to-field-schema.ts","../src/index/parse-template/split-sections.ts","../src/index/parse-template/build-title-schema.ts","../src/index/parse-template/heading-to-key.ts","../src/index/parse-template/validate-directive-shape.ts"],"sourcesContent":["import { toMarkdown } from \"mdast-util-to-markdown\";\nimport { gfmToMarkdown } from \"mdast-util-gfm\";\nimport type { Root } from \"mdast\";\nimport type { Extractor } from \"../../_shared/extractor\";\nimport { extractDirectiveBody } from \"../_shared/extract-directive-body\";\n\n/**\n * Serializes a section's body nodes back to a markdown string, preserving all\n * node types (paragraphs, code, lists, tables, blockquotes, thematic breaks,\n * H3+ headings, etc.).\n *\n * Throws if any TEMPLATE-ONLY directive is found nested inside the body.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param props - Extractor context with the section heading name.\n * @returns The section body serialized to a trimmed markdown string.\n */\nexport const freetext: Extractor<string> = (nodes, { section }) => {\n const hasNestedDirective = (n: unknown): boolean => {\n if (typeof n !== \"object\" || n === null) return false;\n const node = n as { type: string; value?: string; children?: unknown[] };\n if (node.type === \"html\" && typeof node.value === \"string\") {\n if (extractDirectiveBody(node.value) !== null) return true;\n }\n if (Array.isArray(node.children)) {\n return node.children.some(hasNestedDirective);\n }\n return false;\n };\n\n for (const n of nodes) {\n if (hasNestedDirective(n)) {\n throw new Error(\n `Section \"${section}\": free-text bodies cannot contain TEMPLATE-ONLY directives`,\n );\n }\n }\n\n const root: Root = { type: \"root\", children: nodes };\n return toMarkdown(root, { extensions: [gfmToMarkdown()] }).trim();\n};\n","/** Regex that matches TEMPLATE-ONLY HTML comment blocks. */\nconst TEMPLATE_ONLY_RE = /<!--\\s*TEMPLATE-ONLY:\\s*([\\s\\S]*?)\\s*-->/;\n\n/**\n * Extracts the body from an HTML comment string of the form\n * `<!-- TEMPLATE-ONLY: ... -->`, or returns `null` if the string is not a\n * recognised template directive.\n *\n * @param html - Raw HTML comment string.\n * @returns The directive body, or `null` if not a TEMPLATE-ONLY comment.\n */\nexport function extractDirectiveBody(html: string): string | null {\n const m = html.match(TEMPLATE_ONLY_RE);\n return m ? m[1].trim() : null;\n}\n","import { toString } from \"mdast-util-to-string\";\nimport type { Table } from \"mdast\";\nimport type { Extractor } from \"../../_shared/extractor\";\n\n/**\n * Parses the first GFM table in a section into an array of row objects keyed\n * by header cell text.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param ctx - Context carrying the section heading for error messages.\n * @returns An array where each entry maps header text to cell text.\n */\nexport const table: Extractor<Record<string, string>[]> = (\n nodes,\n { section },\n) => {\n const t = nodes.find((n): n is Table => n.type === \"table\");\n if (!t) throw new Error(`Section \"${section}\" must contain a table`);\n const [head, ...body] = t.children;\n const headers = head.children.map((c) => toString(c).trim());\n return body.map((row) => {\n // Null-prototype object: header text is untrusted, so a header literally\n // named `__proto__`/`constructor` is stored as an ordinary key instead of\n // hitting the prototype setter (no pollution, no silently-dropped value).\n const obj = Object.create(null) as Record<string, string>;\n row.children.forEach(\n (cell, i) => (obj[headers[i]] = toString(cell).trim()),\n );\n return obj;\n });\n};\n","import { toString } from \"mdast-util-to-string\";\nimport type { List } from \"mdast\";\nimport type { Extractor } from \"../../_shared/extractor\";\n\n/**\n * Extracts a plain bullet list from a section into an array of strings.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param ctx - Context carrying the section heading for error messages.\n * @returns An array of trimmed item strings.\n */\nexport const bulletList: Extractor<string[]> = (nodes, { section }) => {\n const l = nodes.find((n): n is List => n.type === \"list\");\n if (!l) throw new Error(`Section \"${section}\" must contain a list`);\n return l.children.map((item) => toString(item).trim());\n};\n","import { toString } from \"mdast-util-to-string\";\nimport type { List, ListItem } from \"mdast\";\nimport type { Extractor } from \"../../_shared/extractor\";\n\n/**\n * Extracts a GFM task list (`- [ ]` / `- [x]`) from a section.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param ctx - Context carrying the section heading for error messages.\n * @returns An array of `{ checked, text }` objects.\n */\nexport const taskList: Extractor<{ checked: boolean; text: string }[]> = (\n nodes,\n { section },\n) => {\n const list = nodes.find((n): n is List => n.type === \"list\");\n if (!list) throw new Error(`Section \"${section}\" must contain a list`);\n return list.children.map((item: ListItem) => ({\n checked: item.checked ?? false,\n text: toString(item).trim(),\n }));\n};\n","import type { Code } from \"mdast\";\nimport type { Extractor } from \"./_shared/extractor\";\n\n/**\n * Collects all fenced code blocks in a section.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param _ctx - Unused context (required by the {@link Extractor} signature).\n * @returns An array of `{ lang, value }` objects; `lang` is `null` when the\n * fence has no language specifier.\n */\nexport const codeBlocks: Extractor<{ lang: string | null; value: string }[]> = (\n nodes,\n) =>\n nodes\n .filter((n): n is Code => n.type === \"code\")\n .map((n) => ({ lang: n.lang ?? null, value: n.value }));\n","import type { RootContent } from \"mdast\";\nimport type { Extractor } from \"./_shared/extractor\";\n\n/**\n * Returns the raw mdast nodes for a section unchanged.\n *\n * This is an escape hatch for when none of the built-in extractors fit.\n *\n * @param nodes - The mdast nodes belonging to the section body.\n * @param _ctx - Unused context (required by the {@link Extractor} signature).\n * @returns The same `nodes` array passed in.\n */\nexport const rawNodes: Extractor<RootContent[]> = (nodes) => nodes;\n","import type { Extractor } from \"../../_shared/extractor\";\n\n/**\n * Wraps an extractor so that when it throws (e.g. a required element is\n * missing) the wrapped extractor returns `undefined` instead.\n *\n * @param ex - The extractor to make optional.\n * @returns A new extractor that returns `T | undefined`.\n */\nexport const optional =\n <T>(ex: Extractor<T>): Extractor<T | undefined> =>\n (nodes, ctx) => {\n try {\n return ex(nodes, ctx);\n } catch {\n return undefined;\n }\n };\n","import type { Html } from \"mdast\";\nimport type { Extractor } from \"./_shared/extractor\";\n\n/**\n * Extracts a fenced code block that is immediately preceded by an HTML comment\n * matching `opts.marker`.\n *\n * @param opts - Configuration for the marker pattern.\n * @param opts.marker - Regular expression tested against each HTML comment node.\n * @param opts.markerLabel - Human-readable label used in error messages.\n * @returns An extractor that yields `{ lang, value }` of the matched code block.\n */\nexport function fencedCodeWithMarker(opts: {\n marker: RegExp;\n markerLabel?: string;\n}): Extractor<{ lang: string | null; value: string }> {\n return (nodes, { section }) => {\n const idx = nodes.findIndex(\n (n): n is Html => n.type === \"html\" && opts.marker.test(n.value),\n );\n if (idx === -1) {\n throw new Error(\n `Section \"${section}\" must contain ${opts.markerLabel ?? \"a marker comment\"}`,\n );\n }\n const next = nodes[idx + 1];\n if (!next || next.type !== \"code\") {\n throw new Error(\n `Section \"${section}\": code block must follow ${opts.markerLabel ?? \"the marker\"}`,\n );\n }\n return { lang: next.lang ?? null, value: next.value };\n };\n}\n","import { toString } from \"mdast-util-to-string\";\nimport type { RootContent } from \"mdast\";\nimport type { Extractor } from \"../../../_shared/extractor\";\nimport type { GroupShape } from \"../_shared/group-shape\";\nimport type { GroupResult } from \"../_shared/group-result\";\n\n/**\n * Generic repeating-group extractor that splits section nodes into groups\n * using an arbitrary predicate.\n *\n * Useful when groups are separated by anything other than headings — thematic\n * breaks, bold lead-in paragraphs, etc.\n *\n * @param opts - Configuration for the split strategy.\n * @param opts.startsAt - Predicate that returns `true` for the boundary node\n * that opens a new group.\n * @param opts.headingFrom - Optional function that derives the group heading\n * string from the boundary node. Defaults to `toString(node).trim()`.\n * @param opts.shape - Map of output key → extractor applied to each group's body.\n * @param opts.includeBoundary - When `true`, the boundary node is included in\n * the group's body nodes. Default `false`.\n * @returns An extractor that yields an array of {@link GroupResult} objects.\n */\nexport function repeatedWhere<S extends GroupShape>(opts: {\n startsAt: (node: RootContent) => boolean;\n headingFrom?: (node: RootContent) => string;\n shape: S;\n includeBoundary?: boolean;\n}): Extractor<GroupResult<S>[]> {\n return (nodes, ctx) => {\n const groups: { heading: string; nodes: RootContent[] }[] = [];\n let current: { heading: string; nodes: RootContent[] } | null = null;\n\n for (const node of nodes) {\n if (opts.startsAt(node)) {\n if (current) groups.push(current);\n current = {\n heading: opts.headingFrom?.(node) ?? toString(node).trim(),\n nodes: opts.includeBoundary ? [node] : [],\n };\n } else if (current) {\n current.nodes.push(node);\n }\n }\n if (current) groups.push(current);\n\n return groups.map((g) => {\n const out: Record<string, unknown> = { heading: g.heading };\n for (const [key, ex] of Object.entries(opts.shape)) {\n out[key] = ex(g.nodes, { section: `${ctx.section} > ${g.heading}` });\n }\n return out as GroupResult<S>;\n });\n };\n}\n","import { toString } from \"mdast-util-to-string\";\nimport type { Heading } from \"mdast\";\nimport type { Extractor } from \"../../_shared/extractor\";\nimport type { GroupShape } from \"./_shared/group-shape\";\nimport type { GroupResult } from \"./_shared/group-result\";\nimport { repeatedWhere } from \"./repeated/repeated-where\";\n\n/**\n * Splits a section by sub-heading depth and runs sub-extractors on each group.\n *\n * When `opts.by` is omitted the depth is auto-detected from the first\n * sub-heading encountered and all subsequent group boundaries are pinned to\n * that same depth. Deeper or shallower headings are treated as body content.\n * Pin `opts.by` explicitly when your convention matters.\n *\n * @param opts - Configuration for the repeating groups.\n * @param opts.by - Expected heading depth (e.g. `3` for H3). Auto-detected\n * from the first sub-heading when omitted.\n * @param opts.shape - Map of output key → extractor applied to each group's body.\n * @returns An extractor that yields an array of {@link GroupResult} objects.\n */\nexport function repeated<S extends GroupShape>(opts: {\n by?: number;\n shape: S;\n}): Extractor<GroupResult<S>[]> {\n return (nodes, ctx) => {\n let depth = opts.by;\n return repeatedWhere({\n startsAt: (n): n is Heading => {\n if (n.type !== \"heading\") return false;\n if (depth === undefined) depth = n.depth;\n return n.depth === depth;\n },\n headingFrom: (n) => toString(n).trim(),\n shape: opts.shape,\n includeBoundary: false,\n })(nodes, ctx);\n };\n}\n","import { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkGfm from \"remark-gfm\";\nimport { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { Extractor } from \"../_shared/extractor\";\nimport { splitDoc } from \"./define-doc-schema/split-doc\";\n\n/**\n * Specification for a single section within a document schema.\n *\n * @template S - The Zod schema type that validates the extracted section value.\n */\nexport type SectionSpec<S extends ZodTypeAny = ZodTypeAny> = {\n /** H2 heading text in the document. Defaults to the section key. */\n heading?: string;\n /** Extractor that lifts the raw section value from mdast nodes. */\n extract: Extractor<unknown>;\n /** Zod schema that validates the extracted value. */\n schema: S;\n /** When `true`, a missing section yields `undefined` instead of an error. */\n optional?: boolean;\n};\n\n/**\n * Internal shape of the spec passed to {@link defineDocSchema}.\n * Uses `z.ZodType<any>` as the section-schema bound so that the deferred\n * evaluation path inside `DocOf` degrades to `any` (not `unknown`) when\n * TypeScript cannot yet resolve the specific generic argument.\n */\ntype DocSpec = {\n /** Schema for the document title (extracted from the first H1 by default). */\n title?: { schema: ZodTypeAny };\n /** Heading depth for the document title. Default `1`. */\n titleDepth?: number;\n /** Heading depth for sections. Default `2`. */\n sectionDepth?: number;\n /** Map of output key → section specification. */\n sections: Record<string, SectionSpec<z.ZodType<any>>>;\n};\n\n/**\n * Infers the fully-typed parse result for a document schema `S` produced by\n * {@link defineDocSchema}.\n */\nexport type DocOf<S extends DocSpec> = { frontmatter?: unknown } & (S[\"title\"] extends {\n schema: infer T extends ZodTypeAny;\n}\n ? { title: z.infer<T> }\n : // eslint-disable-next-line @typescript-eslint/no-empty-object-type\n {}) & {\n [K in keyof S[\"sections\"]]: S[\"sections\"][K] extends {\n optional: true;\n schema: infer T extends ZodTypeAny;\n }\n ? z.infer<T> | undefined\n : S[\"sections\"][K] extends { schema: infer T extends ZodTypeAny }\n ? z.infer<T>\n : never;\n};\n\n/**\n * Defines a document schema that parses and validates a markdown string.\n *\n * The returned object exposes a single `parse` method that accepts raw\n * markdown and returns a fully-typed document object, or throws a\n * `ZodError` (content issues) or plain `Error` (structural issues such as\n * missing required sections or malformed tables).\n *\n * @param spec - The document specification including section definitions and\n * an optional cross-section refinement callback.\n * @returns An object with a `parse(raw: string): DocOf<S>` method.\n */\nexport function defineDocSchema<S extends DocSpec>(\n spec: S & {\n refine?: (doc: DocOf<S>, ctx: z.core.$RefinementCtx) => void;\n },\n) {\n const shape: Record<string, ZodTypeAny> = {};\n // Frontmatter is always permitted (and always optional). The parser exposes\n // it on `doc.frontmatter` for refine rules and `--emit-json`; declarative\n // frontmatter constraints live in `*.refine.ts`, not in the schema shape.\n shape.frontmatter = z.unknown().optional();\n if (spec.title) shape.title = spec.title.schema;\n for (const [key, sec] of Object.entries(spec.sections)) {\n shape[key] = sec.optional ? sec.schema.optional() : sec.schema;\n }\n let composite: ZodTypeAny = z.object(shape).strict();\n if (spec.refine) {\n composite = composite.superRefine((doc, ctx) =>\n spec.refine!(doc as DocOf<S>, ctx),\n );\n }\n\n const sectionDepth = spec.sectionDepth ?? 2;\n const titleDepth = spec.title ? (spec.titleDepth ?? 1) : undefined;\n\n return {\n /**\n * Parses and validates a raw markdown string against this document schema.\n *\n * @param raw - The raw markdown content to parse.\n * @returns A fully-typed document object.\n */\n parse(raw: string): DocOf<S> {\n const tree = unified()\n .use(remarkParse)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkGfm)\n .parse(raw);\n const { frontmatter, title, sections } = splitDoc(tree, {\n titleDepth,\n sectionDepth,\n });\n\n const lifted: Record<string, unknown> = {};\n if (frontmatter !== undefined) lifted.frontmatter = frontmatter;\n if (spec.title) lifted.title = title;\n\n for (const [key, sec] of Object.entries(spec.sections)) {\n const heading = sec.heading ?? key;\n const nodes = sections.get(heading);\n if (!nodes) {\n if (sec.optional) continue;\n throw new Error(`Missing required section: \"${heading}\"`);\n }\n if (nodes.length === 0 && sec.optional) continue;\n lifted[key] = sec.extract(nodes, { section: heading });\n }\n\n return composite.parse(lifted) as DocOf<S>;\n },\n };\n}\n","import { toString } from \"mdast-util-to-string\";\nimport type { Root, RootContent } from \"mdast\";\nimport { extractFrontmatter } from \"./split-doc/extract-frontmatter\";\n\n/**\n * Splits an mdast tree into a title string and a map of section heading →\n * body nodes.\n *\n * @param tree - The parsed mdast Root node.\n * @param opts - Split options.\n * @param opts.titleDepth - Heading depth treated as the document title.\n * `undefined` means no title extraction.\n * @param opts.sectionDepth - Heading depth treated as section boundaries.\n * @returns An object with `frontmatter` (parsed YAML frontmatter, or\n * `undefined` when absent), `title` (empty string when absent), and\n * `sections` map from heading text to body nodes.\n */\nexport function splitDoc(\n tree: Root,\n opts: { titleDepth: number | undefined; sectionDepth: number },\n): {\n frontmatter: unknown;\n title: string;\n sections: Map<string, RootContent[]>;\n} {\n const frontmatter = extractFrontmatter(tree);\n let title = \"\";\n const sections = new Map<string, RootContent[]>();\n let current: string | null = null;\n\n for (const node of tree.children) {\n if (\n opts.titleDepth !== undefined &&\n !title &&\n node.type === \"heading\" &&\n node.depth === opts.titleDepth\n ) {\n title = toString(node).trim();\n continue;\n }\n if (node.type === \"heading\" && node.depth === opts.sectionDepth) {\n current = toString(node).trim();\n sections.set(current, []);\n continue;\n }\n if (current) sections.get(current)!.push(node);\n }\n return { frontmatter, title, sections };\n}\n","import { parse as parseYaml } from \"yaml\";\nimport type { Root } from \"mdast\";\n\n/**\n * Reads the YAML frontmatter from a parsed mdast tree.\n *\n * Requires the `remark-frontmatter` plugin to have run during parsing so that\n * a leading `---`-fenced block is represented as a `yaml` root node. When no\n * frontmatter is present, returns `undefined`. An empty frontmatter block\n * (`---\\n---`) parses to `undefined` via `yaml` and is normalized to an empty\n * object so callers can distinguish \"absent\" from \"present but empty\".\n *\n * @param tree - The parsed mdast Root node.\n * @returns The parsed frontmatter object, or `undefined` when no frontmatter\n * block exists.\n */\nexport function extractFrontmatter(tree: Root): unknown {\n const node = tree.children.find((n) => n.type === \"yaml\");\n if (!node) return undefined;\n const raw = (node as { value: string }).value;\n const parsed = parseYaml(raw) as unknown;\n return parsed ?? {};\n}\n","import { unified } from \"unified\";\nimport remarkParse from \"remark-parse\";\nimport remarkFrontmatter from \"remark-frontmatter\";\nimport remarkGfm from \"remark-gfm\";\nimport { z } from \"zod\";\nimport { defineDocSchema } from \"./parse-template/define-doc-schema\";\nimport { inferSection } from \"./parse-template/infer-section\";\nimport type { RefineFunction } from \"./parse-template/load-refine\";\nimport { splitSections } from \"./parse-template/split-sections\";\nimport { buildTitleSchema } from \"./parse-template/build-title-schema\";\nimport { headingToKey } from \"./parse-template/heading-to-key\";\nimport { validateDirectiveShape } from \"./parse-template/validate-directive-shape\";\n\nexport { headingToKey };\n\n/**\n * Parses a `*.template.md` document into a `defineDocSchema` schema object\n * that can validate filled instances of the template.\n *\n * The template's `<!-- TEMPLATE-ONLY: -->` directives drive schema inference:\n * - `enum:` → `z.enum([...])`\n * - field directives (`string; …`) → typed scalar with optional/required/regex modifiers\n * - `row` directive → table row schema\n * - `section` directive → optional/remove-if/min-groups for the section\n * - `guide` directive → author prose, ignored by the schema\n *\n * An optional `refine` function (loaded separately via {@link loadRefine})\n * can be supplied via `opts.refine` to add cross-section invariants.\n *\n * Inline directives must close on the same line as the opener. Multi-line\n * bodies are reserved for block directives. Unknown directive keywords are\n * hard errors with position information.\n *\n * @param templateRaw - Raw markdown content of the template file.\n * @param opts - Optional configuration.\n * @param opts.refine - Cross-section refinement callback to attach.\n * @param opts.file - Source file path used in error messages.\n * @returns A schema object with a `parse(raw: string)` method.\n */\nexport function parseTemplate(\n templateRaw: string,\n opts?: { refine?: RefineFunction; file?: string },\n): { parse(raw: string): Record<string, unknown> } {\n validateDirectiveShape(templateRaw, opts?.file);\n const tree = unified()\n .use(remarkParse)\n .use(remarkFrontmatter, [\"yaml\"])\n .use(remarkGfm)\n .parse(templateRaw);\n\n const titleDepth = 1;\n const sectionDepth = 2;\n\n const titleValidation = buildTitleSchema(tree, titleDepth);\n const sections = splitSections(tree, titleDepth, sectionDepth);\n\n // Build section specs\n const sectionSpecs: Record<\n string,\n {\n heading: string;\n extract: ReturnType<typeof inferSection>[\"extract\"];\n schema: ReturnType<typeof inferSection>[\"schema\"];\n optional?: boolean;\n }\n > = {};\n\n for (const [heading, nodes] of sections) {\n const inference = inferSection(nodes, heading);\n\n // Derive a camelCase key from the heading (e.g. \"1. Summary\" → \"summary\")\n const key = headingToKey(heading);\n\n sectionSpecs[key] = {\n heading,\n extract: inference.extract,\n schema: inference.schema,\n optional: inference.optional,\n };\n }\n\n return defineDocSchema({\n title: titleValidation ? { schema: titleValidation } : undefined,\n sections: sectionSpecs,\n refine: opts?.refine as\n | ((doc: Record<string, unknown>, ctx: z.core.$RefinementCtx) => void)\n | undefined,\n }) as { parse(raw: string): Record<string, unknown> };\n}\n","import { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { RootContent, List, Heading } from \"mdast\";\nimport type { Html } from \"mdast\";\nimport { bulletList } from \"./infer-section/bullet-list\";\nimport { freetext } from \"./infer-section/freetext\";\nimport { table } from \"./infer-section/table\";\nimport { taskList } from \"./infer-section/task-list\";\nimport { optional as optionalExtractor } from \"./infer-section/optional\";\nimport { repeated } from \"./infer-section/repeated\";\nimport type { Extractor } from \"../_shared/extractor\";\nimport {\n extractDirectiveBody,\n parseDirective,\n} from \"./_shared/parse-directive\";\nimport { buildRowSchema } from \"./infer-section/build-row-schema\";\nimport { parseBlockDirectives } from \"./infer-section/parse-block-directives\";\nimport { findDirective } from \"./infer-section/find-directive\";\nimport { collectItemDirectives } from \"./_shared/collect-item-directives\";\nimport { isLabeledList } from \"./infer-section/is-labeled-list\";\nimport { isTaskList } from \"./infer-section/is-task-list\";\nimport { buildLabeledListSchema } from \"./infer-section/build-labeled-list-schema\";\nimport { buildRepeatedSchema } from \"./infer-section/build-repeated-schema\";\nimport { directiveToFieldSchema } from \"./infer-section/directive-to-field-schema\";\nimport { DirectiveError } from \"./_shared/directive-error\";\n\n/** Result produced for one section by {@link inferSection}. */\nexport type SectionInference = {\n extract: Extractor<unknown>;\n schema: ZodTypeAny;\n /** The whole section heading may be absent from the document. */\n optional?: boolean;\n};\n\n/**\n * Infers the extractor and Zod schema for a single document section from its\n * mdast body nodes.\n *\n * @param nodes - The body nodes for the section (after the H2 heading).\n * @param _heading - The heading text (used in error messages).\n * @returns Extractor, schema, and optional flag for this section.\n */\nexport function inferSection(\n nodes: RootContent[],\n _heading: string,\n): SectionInference {\n const blockDirectives = parseBlockDirectives(nodes);\n\n const sectionDir = findDirective(blockDirectives, \"section\");\n const rowDir = findDirective(blockDirectives, \"row\");\n const freetextDir = findDirective(blockDirectives, \"freetext\");\n\n const isOptional =\n (sectionDir?.optional ?? rowDir?.sectionOptional ?? false) ||\n (freetextDir?.optional ?? false);\n\n // Content nodes: everything that isn't a block html TEMPLATE-ONLY comment\n const contentNodes = nodes.filter((n) => {\n if (n.type !== \"html\") return true;\n const body = extractDirectiveBody(n.value);\n return body === null;\n });\n\n // 0. Explicit freetext directive → free-form markdown string\n if (freetextDir) {\n if (rowDir) {\n throw new Error(\n `Section \"${_heading}\" cannot use both 'freetext' and 'row' directives`,\n );\n }\n let extract: Extractor<unknown> = freetext;\n let schema: ZodTypeAny = z.string().min(1);\n if (isOptional) {\n extract = optionalExtractor(freetext);\n schema = schema.optional();\n }\n return { extract, schema, optional: isOptional };\n }\n\n // 1. Sub-headings → repeated\n const hasSubHeadings = contentNodes.some(\n (n): n is Heading => n.type === \"heading\",\n );\n if (hasSubHeadings) {\n const minGroups = sectionDir?.minGroups;\n const maxGroups = sectionDir?.maxGroups;\n\n // Check the first H3 for an inline directive (Step 6.5)\n let headingSchema: ZodTypeAny | undefined;\n const firstHeading = contentNodes.find(\n (n): n is Heading => n.type === \"heading\",\n );\n if (firstHeading) {\n const inlineHtml = firstHeading.children.find(\n (c): c is Html => c.type === \"html\",\n );\n if (inlineHtml) {\n const body = extractDirectiveBody(inlineHtml.value);\n if (body) {\n const dir = parseDirective(body);\n if (dir.kind === \"field\" || dir.kind === \"enum\") {\n headingSchema = directiveToFieldSchema(dir);\n } else {\n throw new DirectiveError(\n `H3 sub-headings only support inline field or enum directives, got: ${dir.kind}`,\n );\n }\n }\n }\n }\n\n const schema = buildRepeatedSchema(\n contentNodes,\n minGroups,\n maxGroups,\n headingSchema,\n );\n return {\n extract: repeated({ shape: { items: bulletList } }),\n schema,\n optional: isOptional,\n };\n }\n\n // 2. Row directive + table → table section\n const hasTable = contentNodes.some((n) => n.type === \"table\");\n if (rowDir || hasTable) {\n let rowSchema: ZodTypeAny = z.record(z.string(), z.string());\n if (rowDir) rowSchema = buildRowSchema(rowDir.columns);\n\n let arraySchema: ZodTypeAny = z.array(rowSchema);\n if (rowDir?.minRows)\n arraySchema = (arraySchema as ReturnType<typeof z.array>).min(\n rowDir.minRows,\n );\n if (rowDir?.maxRows)\n arraySchema = (arraySchema as ReturnType<typeof z.array>).max(\n rowDir.maxRows,\n );\n\n let extract: Extractor<unknown> = table;\n if (isOptional) {\n extract = optionalExtractor(table);\n arraySchema = arraySchema.optional();\n }\n\n return { extract, schema: arraySchema, optional: isOptional };\n }\n\n // 3. Labeled bullet list (items have enum/field directives)\n const listNode = contentNodes.find((n): n is List => n.type === \"list\");\n if (listNode) {\n if (isTaskList(listNode)) {\n return {\n extract: taskList,\n schema: z.array(z.object({ checked: z.boolean(), text: z.string() })),\n optional: isOptional,\n };\n }\n\n const itemDirs = collectItemDirectives(listNode);\n if (isLabeledList(listNode)) {\n const schema = buildLabeledListSchema(itemDirs);\n return { extract: bulletList, schema, optional: isOptional };\n }\n\n // Plain bullet list\n return {\n extract: bulletList,\n schema: z.array(z.string()),\n optional: isOptional,\n };\n }\n\n // No recognized shape and no freetext directive → hard error\n throw new Error(\n `Section \"${_heading}\" has no recognized shape; add a 'freetext' directive if free-form content is intended`,\n );\n}\n","/**\n * Splits a `|`-delimited choice string into individual choices, honouring\n * `\\|` (literal `|`) and `\\\\` (literal `\\`) escape sequences.\n *\n * - `\\\\` → `\\`, advance 2\n * - `\\|` → `|`, advance 2\n * - `\\<other>` → `\\` + `<other>`, advance 2 (lenient)\n * - bare `|` → end current choice, start new one\n *\n * Each choice is trimmed; empty choices are dropped.\n *\n * @param input - Raw pipe-separated choice string, e.g. `\"A | B \\\\| C\"`.\n * @returns Array of trimmed, non-empty choice strings.\n */\nexport function splitEscapedChoices(input: string): string[] {\n const choices: string[] = [];\n let current = \"\";\n let i = 0;\n while (i < input.length) {\n const ch = input[i];\n if (ch === \"\\\\\") {\n const next = input[i + 1];\n if (next === \"\\\\\") {\n current += \"\\\\\";\n i += 2;\n } else if (next === \"|\") {\n current += \"|\";\n i += 2;\n } else {\n current += \"\\\\\" + (next ?? \"\");\n i += 2;\n }\n } else if (ch === \"|\") {\n choices.push(current.trim());\n current = \"\";\n i++;\n } else {\n current += ch;\n i++;\n }\n }\n choices.push(current.trim());\n return choices.filter(Boolean);\n}\n","import type { ParsedDirective } from \"../parsed-directive\";\nimport { splitEscapedChoices } from \"./_shared/split-escaped-choices\";\n\n/**\n * Parses the body of an `enum:` inline directive.\n *\n * Expected form: `enum: Choice1 | Choice2 | Choice3; required`\n * Choice separators (`|`) may be escaped with `\\|` for a literal pipe,\n * or `\\\\` for a literal backslash.\n *\n * Modifiers after the choices (`;`-separated): `required` / `optional`.\n * Defaults to `required` when neither modifier is present.\n *\n * @param body - Trimmed directive body starting with `enum:`.\n * @returns An `enum` ParsedDirective with the split choices and required flag.\n */\nexport function parseEnum(body: string): ParsedDirective & { kind: \"enum\" } {\n const parts = body.split(\";\").map((s) => s.trim());\n const choicesPart = parts[0] ?? body;\n const after = choicesPart.slice(\"enum:\".length).trim();\n const choices = splitEscapedChoices(after);\n const required = !parts.slice(1).includes(\"optional\");\n return { kind: \"enum\", choices, required };\n}\n","import type { ParsedDirective } from \"../parsed-directive\";\n\n/**\n * Parses the body of a field directive.\n *\n * Expected form (semicolon-separated modifiers):\n * `string; required`\n * `string; optional; only-if Type=Primitive`\n * `string; regex \\`^[a-z]+$\\`; required`\n *\n * The `regex` modifier must follow `string` — bare `regex \\`...\\`` without\n * a leading `string` token is rejected by the dispatcher before this function\n * is called.\n *\n * @param body - Trimmed directive body starting with `string`.\n * @returns A `field` ParsedDirective.\n */\nexport function parseField(body: string): ParsedDirective & { kind: \"field\" } {\n const parts = body.split(\";\").map((s) => s.trim());\n let required = true;\n let regex: string | undefined;\n let defaultValue: string | undefined;\n let onlyIf: { key: string; value: string } | undefined;\n\n for (const part of parts) {\n if (part === \"string\") {\n // type token — present but carries no extra info\n } else if (part === \"optional\") {\n required = false;\n } else if (part === \"required\") {\n required = true;\n } else if (part.startsWith(\"regex\")) {\n const m = part.match(/`([^`]+)`/);\n if (m) regex = m[1];\n } else if (part.startsWith(\"default=\")) {\n defaultValue = part\n .slice(\"default=\".length)\n .replace(/^[\"']/, \"\")\n .replace(/[\"']$/, \"\");\n } else if (part.startsWith(\"only-if \")) {\n const rest = part.slice(\"only-if \".length);\n const eqIdx = rest.indexOf(\"=\");\n if (eqIdx > -1) {\n onlyIf = {\n key: rest.slice(0, eqIdx).trim(),\n value: rest.slice(eqIdx + 1).trim(),\n };\n }\n }\n // example= modifiers are ignored (documentation only)\n }\n\n return { kind: \"field\", required, regex, defaultValue, onlyIf };\n}\n","/**\n * Thrown when a `<!-- TEMPLATE-ONLY: -->` directive has invalid syntax.\n * The `message` field is formatted as `path:line:col: description` when\n * position information is available, so the CLI formatter needs no changes.\n *\n * @param message - Human-readable error description (may include path:line:col prefix).\n * @param options - Optional context: directive body, source position, and file path.\n */\nexport class DirectiveError extends Error {\n constructor(\n message: string,\n options?: {\n body?: string;\n position?: { line: number; column: number };\n file?: string;\n },\n ) {\n super(message);\n this.name = \"DirectiveError\";\n this.body = options?.body;\n this.position = options?.position;\n this.file = options?.file;\n }\n /** The raw directive body that triggered the error, if available. */\n readonly body?: string;\n /** Source position of the directive opener, if available. */\n readonly position?: { line: number; column: number };\n /** Source file path, if available. */\n readonly file?: string;\n}\n","import type { ParsedDirective } from \"../parsed-directive\";\nimport { DirectiveError } from \"../directive-error\";\n\n/**\n * Parses the body of a `freetext` block directive.\n *\n * All modifiers live on the opener line, semicolon-separated:\n * `freetext; optional`\n * `freetext; required`\n *\n * @param body - Trimmed directive body starting with `freetext`.\n * @returns A `freetext` ParsedDirective.\n */\nexport function parseFreetextDirective(\n body: string,\n): ParsedDirective & { kind: \"freetext\" } {\n const allLines = body.split(\"\\n\");\n const openerLine = allLines[0] ?? \"\";\n const bodyLines = allLines.slice(1);\n\n // Body lines (non-blank, non-//) are an error\n for (const line of bodyLines) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n if (trimmed.startsWith(\"//\")) continue;\n throw new DirectiveError(\n `freetext modifiers must be on the directive opener, not in the body; found: \"${trimmed}\"`,\n { body },\n );\n }\n\n const parts = openerLine\n .slice(\"freetext\".length)\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n let optional = false;\n\n for (const part of parts) {\n if (part === \"optional\") {\n optional = true;\n } else if (part === \"required\") {\n // no-op; default\n } else {\n throw new DirectiveError(`unknown freetext modifier: '${part}'`, {\n body,\n });\n }\n }\n\n return { kind: \"freetext\", optional };\n}\n","import type { ParsedDirective } from \"../parsed-directive\";\nimport { DirectiveError } from \"../directive-error\";\n\n/**\n * Parses the body of a `guide` block directive.\n *\n * A guide block may contain only blank lines and `//`-prefixed prose lines.\n * Any other non-blank line is a hard error.\n *\n * @param body - Trimmed directive body starting with `guide`.\n * @returns A `guide` ParsedDirective (carries no semantic data).\n */\nexport function parseGuide(body: string): ParsedDirective & { kind: \"guide\" } {\n const lines = body.split(\"\\n\").slice(1);\n for (const line of lines) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n if (trimmed.startsWith(\"//\")) continue;\n throw new DirectiveError(\n `guide block: line must start with '//' or be blank; got: \"${trimmed}\"`,\n { body },\n );\n }\n return { kind: \"guide\" };\n}\n","import type { ColumnSpec } from \"../../parsed-directive\";\nimport { splitEscapedChoices } from \"../_shared/split-escaped-choices\";\n\n/**\n * Parses a semicolon-separated column-spec string into a {@link ColumnSpec}.\n *\n * Column spec grammar (mirrors the inline field grammar):\n * `string; required`\n * `string; regex \\`^[A-Z]+$\\`; required`\n * `enum: A | B | C; required`\n *\n * @param spec - Semicolon-separated spec string, e.g. `\"string; required\"`.\n * @returns A {@link ColumnSpec} describing the column's constraints.\n */\nexport function parseColumnSpec(spec: string): ColumnSpec {\n const parts = spec.split(\";\").map((s) => s.trim());\n let required = true;\n let regex: string | undefined;\n let enumChoices: string[] | undefined;\n let defaultValue: string | undefined;\n\n for (const part of parts) {\n if (part === \"string\") {\n // type token — present but carries no extra info\n } else if (part === \"optional\") {\n required = false;\n } else if (part === \"required\") {\n required = true;\n } else if (part.startsWith(\"regex\")) {\n const m = part.match(/`([^`]+)`/);\n if (m) regex = m[1];\n } else if (part.startsWith(\"enum:\")) {\n enumChoices = splitEscapedChoices(part.slice(\"enum:\".length).trim());\n } else if (part.startsWith(\"default=\")) {\n defaultValue = part\n .slice(\"default=\".length)\n .replace(/^[\"']/, \"\")\n .replace(/[\"']$/, \"\");\n }\n }\n\n return { required, regex, enumChoices, defaultValue };\n}\n","import type { ParsedDirective, ColumnSpec } from \"../parsed-directive\";\nimport { parseColumnSpec } from \"./parse-row-directive/parse-column-spec\";\nimport { DirectiveError } from \"../directive-error\";\n\n/**\n * Parses the body of a `row` block directive.\n *\n * The opener line may carry semicolon-separated modifiers:\n * `row; min-rows: 1; max-rows: 50`\n *\n * Body lines are column specs (at column 0):\n * `ColumnName: string; required`\n * `OtherCol: enum: Yes | No; required`\n *\n * @param body - Trimmed directive body starting with `row`.\n * @returns A `row` ParsedDirective.\n */\nexport function parseRowDirective(\n body: string,\n): ParsedDirective & { kind: \"row\" } {\n const allLines = body.split(\"\\n\");\n const openerLine = allLines[0] ?? \"\";\n const bodyLines = allLines.slice(1);\n\n // Parse modifiers from the opener (everything after \"row\")\n const openerParts = openerLine\n .slice(\"row\".length)\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n const columns: Record<string, ColumnSpec> = {};\n let minRows: number | undefined;\n let maxRows: number | undefined;\n let sectionOptional = false;\n\n for (const part of openerParts) {\n if (part.startsWith(\"min-rows:\")) {\n minRows = parseInt(part.slice(\"min-rows:\".length).trim(), 10);\n } else if (part.startsWith(\"max-rows:\")) {\n maxRows = parseInt(part.slice(\"max-rows:\".length).trim(), 10);\n } else if (part === \"section-optional\") {\n sectionOptional = true;\n }\n }\n\n // Parse body lines as column specs\n for (const line of bodyLines) {\n if (line.trim().length === 0) continue;\n if (line.trim().startsWith(\"//\")) continue;\n\n // Modifiers on body lines are a migration error\n if (\n line.trim().startsWith(\"min-rows:\") ||\n line.trim().startsWith(\"max-rows:\") ||\n line.trim() === \"section-optional\"\n ) {\n throw new DirectiveError(\n `min-rows / max-rows / section-optional must be on the directive opener, not in the body`,\n { body },\n );\n }\n\n const colonIdx = line.indexOf(\":\");\n if (colonIdx > -1) {\n let colName = line.slice(0, colonIdx).trim();\n // Strip surrounding quotes so column names that need to escape special\n // characters (e.g. `\"#\"`, `\"some name\"`) work transparently.\n if (\n (colName.startsWith('\"') && colName.endsWith('\"')) ||\n (colName.startsWith(\"'\") && colName.endsWith(\"'\"))\n ) {\n colName = colName.slice(1, -1);\n }\n const spec = line.slice(colonIdx + 1).trim();\n if (colName) columns[colName] = parseColumnSpec(spec);\n }\n }\n\n return { kind: \"row\", columns, minRows, maxRows, sectionOptional };\n}\n","import type { ParsedDirective } from \"../parsed-directive\";\nimport { DirectiveError } from \"../directive-error\";\n\n/**\n * Parses the body of a `section` block directive.\n *\n * All modifiers live on the opener line, semicolon-separated:\n * `section; optional; remove-if Type=View`\n * `section; min-groups: 1; max-groups: 10`\n *\n * @param body - Trimmed directive body starting with `section`.\n * @returns A `section` ParsedDirective.\n */\nexport function parseSectionDirective(\n body: string,\n): ParsedDirective & { kind: \"section\" } {\n const allLines = body.split(\"\\n\");\n const openerLine = allLines[0] ?? \"\";\n const bodyLines = allLines.slice(1);\n\n // Body lines (non-blank, non-//) are a migration error\n for (const line of bodyLines) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n if (trimmed.startsWith(\"//\")) continue;\n throw new DirectiveError(\n `section modifiers must be on the directive opener, not in the body; found: \"${trimmed}\"`,\n { body },\n );\n }\n\n const parts = openerLine\n .slice(\"section\".length)\n .split(\";\")\n .map((s) => s.trim())\n .filter(Boolean);\n\n let optional = false;\n let removeIf: { key: string; value: string } | undefined;\n let minGroups: number | undefined;\n let maxGroups: number | undefined;\n\n for (const part of parts) {\n if (part === \"optional\") {\n optional = true;\n } else if (part.startsWith(\"remove-if \")) {\n const rest = part.slice(\"remove-if \".length);\n const eqIdx = rest.indexOf(\"=\");\n if (eqIdx > -1) {\n removeIf = {\n key: rest.slice(0, eqIdx).trim(),\n value: rest.slice(eqIdx + 1).trim(),\n };\n }\n } else if (part.startsWith(\"min-groups:\")) {\n minGroups = parseInt(part.slice(\"min-groups:\".length).trim(), 10);\n } else if (part.startsWith(\"max-groups:\")) {\n maxGroups = parseInt(part.slice(\"max-groups:\".length).trim(), 10);\n }\n }\n\n return { kind: \"section\", optional, removeIf, minGroups, maxGroups };\n}\n","import type { ParsedDirective } from \"./parsed-directive\";\nimport { parseEnum } from \"./parse-directive/parse-enum\";\nimport { parseField } from \"./parse-directive/parse-field\";\nimport { parseFreetextDirective } from \"./parse-directive/parse-freetext-directive\";\nimport { parseGuide } from \"./parse-directive/parse-guide\";\nimport { parseRowDirective } from \"./parse-directive/parse-row-directive\";\nimport { parseSectionDirective } from \"./parse-directive/parse-section-directive\";\nimport { extractDirectiveBody } from \"./extract-directive-body\";\nimport { DirectiveError } from \"./directive-error\";\n\nexport { extractDirectiveBody };\n\n/**\n * Parses the body of a `<!-- TEMPLATE-ONLY: ... -->` comment into a typed\n * {@link ParsedDirective}.\n *\n * First-token dispatch:\n * - Block directives (`guide`, `row`, `section`) are recognised by their\n * opening keyword; prose `//` lines inside them are ignored.\n * - Inline directives: after stripping `//`-prose lines, the first token\n * determines the kind (`enum:` or `string`).\n * - Unrecognised first token → hard {@link DirectiveError}.\n *\n * @param body - Trimmed directive body extracted by {@link extractDirectiveBody}.\n * @param opts - Optional context for error messages.\n * @param opts.position - Source position of the directive opener.\n * @param opts.file - Source file path.\n * @returns A {@link ParsedDirective}.\n */\nexport function parseDirective(\n body: string,\n opts?: { position?: { line: number; column: number }; file?: string },\n): ParsedDirective {\n // Block directives: recognised by opener keyword\n if (\n body === \"guide\" ||\n body.startsWith(\"guide\\n\") ||\n body.startsWith(\"guide;\")\n )\n return parseGuide(body);\n if (body === \"row\" || body.startsWith(\"row\\n\") || body.startsWith(\"row;\"))\n return parseRowDirective(body);\n if (\n body === \"section\" ||\n body.startsWith(\"section\\n\") ||\n body.startsWith(\"section;\")\n )\n return parseSectionDirective(body);\n if (\n body === \"freetext\" ||\n body.startsWith(\"freetext\\n\") ||\n body.startsWith(\"freetext;\")\n )\n return parseFreetextDirective(body);\n\n // Strip `//`-prose lines for inline directives\n const stripped = body\n .split(\"\\n\")\n .filter((l) => !l.trim().startsWith(\"//\"))\n .join(\"\\n\")\n .trim();\n\n // First-token dispatch for inline directives\n const firstToken = stripped.split(/[\\s;]/)[0] ?? \"\";\n\n if (stripped.startsWith(\"enum:\")) return parseEnum(stripped);\n if (firstToken === \"string\") return parseField(stripped);\n\n // Unknown keyword — hard error\n const token = firstToken || stripped.slice(0, 20);\n throw new DirectiveError(`unknown TEMPLATE-ONLY directive kind: '${token}'`, {\n body,\n position: opts?.position,\n file: opts?.file,\n });\n}\n","import { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { ColumnSpec } from \"../_shared/parsed-directive\";\nimport { compileUserRegex } from \"../_shared/compile-user-regex\";\n\n/**\n * Builds a Zod schema for one table row from the column specs parsed from a\n * `row` directive.\n *\n * @param columns - Map of column header → column spec.\n * @returns A `z.object({...}).strict()` schema keyed by column header text.\n */\nexport function buildRowSchema(\n columns: Record<string, ColumnSpec>,\n): ZodTypeAny {\n const shape: Record<string, ZodTypeAny> = {};\n\n for (const [col, spec] of Object.entries(columns)) {\n // Compile the user-supplied regex once, through the ReDoS-safe choke point.\n const re = spec.regex ? compileUserRegex(spec.regex, col) : undefined;\n let field: ZodTypeAny;\n\n if (spec.enumChoices && spec.enumChoices.length > 0) {\n field = z.enum(spec.enumChoices as [string, ...string[]]);\n } else if (re) {\n field = z.string().regex(re);\n } else {\n field = z.string();\n }\n\n if (spec.required) {\n if (spec.enumChoices && spec.enumChoices.length > 0) {\n field = z.enum(spec.enumChoices as [string, ...string[]]);\n } else if (re) {\n field = z.string().min(1).regex(re);\n } else {\n field = z.string();\n }\n } else {\n field = field.optional();\n }\n\n shape[col] = field;\n }\n\n return z.object(shape).strict();\n}\n","import { checkSync } from \"recheck\";\nimport { DirectiveError } from \"./directive-error\";\n\n/** Maximum length of a template-supplied regex source, in characters. */\nconst MAX_REGEX_LENGTH = 200;\n\n/**\n * Highest polynomial backtracking degree tolerated. Exponential blowup (the\n * catastrophic `^(a+)+$` class) is always rejected; low-degree polynomial\n * patterns (e.g. an unanchored `\\d+\\.\\d+`, degree 2) are permitted because the\n * inputs they match are bounded markdown cells/values, so the worst case is a\n * mild quadratic, not a hang.\n */\nconst MAX_POLYNOMIAL_DEGREE = 2;\n\n/**\n * Safely compiles a regular expression supplied by a template author.\n *\n * Template `regex` modifiers are untrusted input: a `*.template.md` may come\n * from a PR, an upload, or any other party. A naive `new RegExp(src)` lets the\n * author plant a catastrophic-backtracking pattern (ReDoS) that hangs the\n * validator on a crafted document value. This helper is the single choke point\n * for every user-supplied regex — it fails **closed**:\n *\n * 1. Rejects sources longer than {@link MAX_REGEX_LENGTH}.\n * 2. Statically analyses the pattern with `recheck` and rejects anything not\n * proven to run in linear time (`status !== \"safe\"`), so vulnerable and\n * unknown patterns are both refused rather than compiled.\n *\n * @param src - The raw regex source from a directive (without delimiters).\n * @param label - Human-readable context for the error message (e.g. the field\n * or column name the regex belongs to).\n * @returns A compiled {@link RegExp} that is safe to `.test()` against\n * untrusted input.\n * @throws DirectiveError when the pattern is too long, unsafe, or otherwise\n * uncompilable.\n */\nexport function compileUserRegex(src: string, label?: string): RegExp {\n const ctx = label ? ` for ${label}` : \"\";\n\n if (src.length > MAX_REGEX_LENGTH) {\n throw new DirectiveError(\n `regex${ctx} is too long (${src.length} > ${MAX_REGEX_LENGTH} characters)`,\n );\n }\n\n const diagnostics = checkSync(src, \"\");\n if (diagnostics.status === \"vulnerable\") {\n // Exponential is always fatal; polynomial is tolerated up to a low degree\n // (matched inputs are bounded markdown values, so a mild quadratic is fine).\n const c = diagnostics.complexity;\n const tolerable =\n c?.type === \"polynomial\" && c.degree <= MAX_POLYNOMIAL_DEGREE;\n if (!tolerable) {\n const detail =\n c?.type === \"polynomial\"\n ? `is super-linear (degree ${c.degree})`\n : \"is vulnerable to catastrophic backtracking (ReDoS)\";\n throw new DirectiveError(`regex${ctx} ${detail}: \\`${src}\\``);\n }\n } else if (diagnostics.status !== \"safe\") {\n // \"unknown\"/\"error\"/\"timeout\" → not proven safe, so refuse it. Fail closed.\n throw new DirectiveError(\n `regex${ctx} could not be proven safe (${diagnostics.status}): \\`${src}\\``,\n );\n }\n\n try {\n return new RegExp(src);\n } catch (err) {\n throw new DirectiveError(\n `regex${ctx} is invalid: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","import type { RootContent, Html } from \"mdast\";\n\n/**\n * Returns all block-level html nodes from a flat node list.\n *\n * @param nodes - Flat list of mdast content nodes.\n * @returns An array containing only the `Html` nodes from `nodes`.\n */\nexport function blockHtmlNodes(nodes: RootContent[]): Html[] {\n return nodes.filter((n): n is Html => n.type === \"html\");\n}\n","import type { RootContent } from \"mdast\";\nimport {\n extractDirectiveBody,\n parseDirective,\n} from \"../_shared/parse-directive\";\nimport type { ParsedDirective } from \"../_shared/parsed-directive\";\nimport { blockHtmlNodes } from \"./parse-block-directives/block-html-nodes\";\n\n/**\n * Parses all block directives from a section body.\n *\n * @param nodes - Flat list of mdast content nodes for the section.\n * @returns An array of all recognised {@link ParsedDirective} objects found in block HTML comments.\n */\nexport function parseBlockDirectives(nodes: RootContent[]): ParsedDirective[] {\n const result: ParsedDirective[] = [];\n for (const n of blockHtmlNodes(nodes)) {\n const body = extractDirectiveBody(n.value);\n if (!body) continue;\n const d = parseDirective(body);\n if (d) result.push(d);\n }\n return result;\n}\n","import type { ParsedDirective } from \"../_shared/parsed-directive\";\n\n/**\n * Returns the first directive of the given kind, or `undefined`.\n *\n * @param directives - Array of parsed directives to search.\n * @param kind - The directive kind to find.\n * @returns The first directive matching `kind`, or `undefined` if none found.\n */\nexport function findDirective<K extends ParsedDirective[\"kind\"]>(\n directives: ParsedDirective[],\n kind: K,\n): Extract<ParsedDirective, { kind: K }> | undefined {\n return directives.find(\n (d): d is Extract<ParsedDirective, { kind: K }> => d.kind === kind,\n );\n}\n","import type { List, Paragraph } from \"mdast\";\nimport { extractDirectiveBody, parseDirective } from \"./parse-directive\";\nimport type { ParsedDirective } from \"./parsed-directive\";\n\n/**\n * Collects inline `enum` / `field` directives from the html children of\n * list items, keyed by the label prefix text of each item.\n *\n * @param list - The mdast `List` node to inspect.\n * @returns A record mapping label text to the parsed directive (or `null` if none).\n */\nexport function collectItemDirectives(\n list: List,\n): Record<string, ParsedDirective | null> {\n const result: Record<string, ParsedDirective | null> = {};\n\n for (const item of list.children) {\n // Find the first paragraph in the list item\n const para = item.children.find(\n (c): c is Paragraph => c.type === \"paragraph\",\n );\n if (!para) continue;\n\n // Label: the text of the first text-like node before any html comment\n let label = \"\";\n let directive: ParsedDirective | null = null;\n\n for (const child of para.children) {\n if (child.type === \"text\") {\n label += child.value;\n } else if (child.type === \"html\") {\n const body = extractDirectiveBody(child.value);\n if (body) {\n directive = parseDirective(body);\n }\n } else if (child.type === \"inlineCode\") {\n // Ignore inline code examples\n }\n }\n\n const colonIdx = label.indexOf(\":\");\n if (colonIdx > -1) {\n const key = label.slice(0, colonIdx).trim();\n if (key) result[key] = directive;\n }\n }\n\n return result;\n}\n","import type { List } from \"mdast\";\nimport { collectItemDirectives } from \"../_shared/collect-item-directives\";\n\n/**\n * Returns `true` when at least one item in the list carries a label directive.\n *\n * @param list - The mdast `List` node to inspect.\n * @returns `true` if the list has labeled items with directives, `false` otherwise.\n */\nexport function isLabeledList(list: List): boolean {\n const directives = collectItemDirectives(list);\n return (\n Object.keys(directives).length > 0 &&\n Object.values(directives).some((d) => d !== null)\n );\n}\n","import type { List } from \"mdast\";\n\n/**\n * Returns `true` when at least one list item has a checked/unchecked state.\n *\n * @param list - The mdast `List` node to inspect.\n * @returns `true` if any item has a `checked` property set, `false` otherwise.\n */\nexport function isTaskList(list: List): boolean {\n return list.children.some(\n (item) => item.checked !== null && item.checked !== undefined,\n );\n}\n","import { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { ParsedDirective } from \"../_shared/parsed-directive\";\nimport { compileUserRegex } from \"../_shared/compile-user-regex\";\n\n/**\n * Builds a `z.array(z.string()).transform(…).superRefine(…)` schema that\n * validates a labeled bullet list extracted by `bulletList`.\n *\n * Output type: `Record<string, string | undefined>`.\n *\n * @param itemDirectives - Record mapping label keys to their parsed directives.\n * @returns A Zod schema that validates and transforms bullet list lines into a keyed record.\n */\nexport function buildLabeledListSchema(\n itemDirectives: Record<string, ParsedDirective | null>,\n): ZodTypeAny {\n type FieldSpec = {\n required: boolean;\n validate: (val: string | undefined) => string | null; // null = ok, string = error\n onlyIf?: { key: string; value: string };\n };\n\n const specs: Record<string, FieldSpec> = {};\n for (const [key, d] of Object.entries(itemDirectives)) {\n if (!d) {\n specs[key] = { required: false, validate: () => null };\n continue;\n }\n if (d.kind === \"enum\") {\n specs[key] = {\n required: d.required,\n validate: (val) => {\n if (d.required && !val) return `${key} is required`;\n if (val && !d.choices.includes(val))\n return `Invalid option: expected one of ${d.choices.map((c) => `\"${c}\"`).join(\"|\")}`;\n return null;\n },\n };\n } else if (d.kind === \"field\") {\n const spec = d;\n // Compile once at schema-build time through the ReDoS-safe choke point,\n // not on every value in the per-line validator.\n const re = spec.regex ? compileUserRegex(spec.regex, key) : undefined;\n specs[key] = {\n required: spec.required,\n validate: (val) => {\n if (spec.required && !val) return `${key} is required`;\n if (val && re) {\n if (!re.test(val)) return `${key} does not match required format`;\n }\n return null;\n },\n onlyIf: spec.onlyIf,\n };\n }\n }\n\n return z\n .array(z.string())\n .transform((lines) => {\n // Null-prototype: line labels are untrusted (a `__proto__:` line must not\n // hit the prototype setter).\n const obj = Object.create(null) as Record<string, string | undefined>;\n for (const line of lines) {\n const idx = line.indexOf(\":\");\n if (idx >= 0) {\n const k = line.slice(0, idx).trim();\n const v = line.slice(idx + 1).trim();\n if (k) obj[k] = v || undefined;\n }\n }\n return obj;\n })\n .superRefine((obj, ctx) => {\n for (const [key, spec] of Object.entries(specs)) {\n const val = obj[key];\n const err = spec.validate(val);\n if (err) {\n ctx.addIssue({ code: \"custom\", path: [key], message: err });\n }\n if (spec.onlyIf && val) {\n const guardVal = obj[spec.onlyIf.key];\n if (guardVal !== spec.onlyIf.value) {\n ctx.addIssue({\n code: \"custom\",\n path: [key],\n message: `${key} is only allowed when ${spec.onlyIf.key}=${spec.onlyIf.value}`,\n });\n }\n }\n }\n });\n}\n","import { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { RootContent } from \"mdast\";\n\n/**\n * Builds the per-group schema for a `repeated` section.\n *\n * Inspects the body of the first heading group to determine whether it\n * contains a labeled list (→ labeled schema per group) or a plain list\n * (→ `z.array(z.string())`), then wraps in `z.array(...).min(N)`.\n *\n * @param nodes - The body nodes for the repeated section.\n * @param minGroups - Minimum number of groups required, or undefined.\n * @param maxGroups - Maximum number of groups allowed, or undefined.\n * @param headingSchema - Optional Zod schema to validate the per-group heading text.\n * @returns A Zod schema validating an array of heading+items group objects.\n */\nexport function buildRepeatedSchema(\n nodes: RootContent[],\n minGroups: number | undefined,\n maxGroups: number | undefined,\n headingSchema?: ZodTypeAny,\n): ZodTypeAny {\n const groupItemZod = z.object({\n heading: headingSchema ?? z.string().min(1),\n items: z.array(z.string()),\n });\n\n let schema: ZodTypeAny = z.array(groupItemZod);\n if (minGroups) schema = (schema as ReturnType<typeof z.array>).min(minGroups);\n if (maxGroups) schema = (schema as ReturnType<typeof z.array>).max(maxGroups);\n return schema;\n}\n","import { z } from \"zod\";\nimport type { ZodTypeAny } from \"zod\";\nimport type { ParsedDirective } from \"../_shared/parsed-directive\";\nimport { compileUserRegex } from \"../_shared/compile-user-regex\";\n\n/**\n * Converts a `field` or `enum` {@link ParsedDirective} into a Zod schema\n * suitable for validating a single string value (e.g. a heading or title).\n *\n * @param directive - A `field` or `enum` ParsedDirective.\n * @returns A Zod string (or enum) schema.\n */\nexport function directiveToFieldSchema(directive: ParsedDirective): ZodTypeAny {\n if (directive.kind === \"enum\") {\n const base = z.enum(directive.choices as [string, ...string[]]);\n return directive.required ? base : base.optional();\n }\n if (directive.kind === \"field\") {\n const base = directive.regex\n ? z.string().min(1).regex(compileUserRegex(directive.regex))\n : z.string().min(1);\n return directive.required ? base : base.optional();\n }\n return z.string().min(1);\n}\n","import type { Root, RootContent } from \"mdast\";\nimport { toString } from \"mdast-util-to-string\";\nimport { extractDirectiveBody } from \"./_shared/extract-directive-body\";\nimport { DirectiveError } from \"./_shared/directive-error\";\n\n/**\n * Splits the document into section bodies by H2 headings, preserving order.\n * Returns a map of heading text → body nodes.\n *\n * H2 headings must not carry inline `TEMPLATE-ONLY` directives — those belong\n * in H1 (title) or H3 (per-group heading inside repeated sections). Throws\n * {@link DirectiveError} if an H2 heading carries such a directive.\n *\n * @param tree - The mdast Root node to split.\n * @param titleDepth - The heading depth used for the document title (skipped).\n * @param sectionDepth - The heading depth used for section boundaries.\n * @returns A map from section heading text to the body nodes of that section.\n */\nexport function splitSections(\n tree: Root,\n titleDepth: number,\n sectionDepth: number,\n): Map<string, RootContent[]> {\n const sections = new Map<string, RootContent[]>();\n let current: string | null = null;\n let titleSeen = false;\n\n for (const node of tree.children) {\n if (node.type === \"heading\" && node.depth === titleDepth && !titleSeen) {\n titleSeen = true;\n continue;\n }\n if (node.type === \"heading\" && node.depth === sectionDepth) {\n // Reject inline TEMPLATE-ONLY directives in H2 headings\n for (const child of node.children) {\n if (child.type === \"html\") {\n const body = extractDirectiveBody(child.value);\n if (body !== null) {\n const pos = node.position?.start;\n throw new DirectiveError(\n `H2 headings cannot carry inline TEMPLATE-ONLY directives — only H1 (title) and H3 (per-group heading inside repeated sections) support inline directives`,\n {\n body,\n position: pos\n ? { line: pos.line, column: pos.column }\n : undefined,\n },\n );\n }\n }\n }\n current = toString(node).trim();\n sections.set(current, []);\n continue;\n }\n if (current !== null) {\n sections.get(current)!.push(node);\n }\n }\n return sections;\n}\n","import { z } from \"zod\";\nimport type { Root, Heading } from \"mdast\";\nimport { extractDirectiveBody } from \"./_shared/extract-directive-body\";\nimport { parseDirective } from \"./_shared/parse-directive\";\nimport { DirectiveError } from \"./_shared/directive-error\";\nimport { compileUserRegex } from \"./_shared/compile-user-regex\";\n\n/**\n * Builds a title validation schema from the H1 node.\n *\n * If the heading contains an inline html comment (a placeholder), the schema\n * uses the directive body to choose its shape:\n * - `field` directive with `regex` modifier → match `<prefix> <pattern>`.\n * - `field` directive without regex → match `<prefix> <any non-empty string>`.\n * - `enum` directive → match `<prefix> <one of choices>`.\n * - otherwise → match `<prefix> PascalCaseName`.\n * If the heading has no placeholder, it validates the literal title text.\n *\n * @param tree - The mdast Root node to search for the title heading.\n * @param depth - The heading depth that represents the document title.\n * @returns A Zod string schema for the title, or `undefined` if no matching heading found.\n */\nexport function buildTitleSchema(\n tree: Root,\n depth: number,\n): z.ZodString | undefined {\n const h = tree.children.find(\n (n): n is Heading => n.type === \"heading\" && n.depth === depth,\n );\n if (!h) return undefined;\n\n // Gather text nodes before the first html comment node\n let prefix = \"\";\n let hasPlaceholder = false;\n let directiveHtml: string | undefined;\n for (const child of h.children) {\n if (child.type === \"text\") prefix += child.value;\n else if (child.type === \"html\") {\n hasPlaceholder = true;\n directiveHtml = child.value;\n break;\n }\n }\n // Preserve trailing whitespace so prefixes ending in `-` (e.g. `CR-`) don't\n // force a space between prefix and suffix in the resulting regex; the\n // template author controls spacing via the literal text.\n prefix = prefix.replace(/^\\s+/, \"\");\n const hadTrailingSpace = /\\s$/.test(prefix);\n prefix = prefix.replace(/\\s+$/, \"\");\n\n if (prefix && hasPlaceholder) {\n const escaped = prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n const sep = hadTrailingSpace ? \" \" : \"\";\n\n const body = directiveHtml ? extractDirectiveBody(directiveHtml) : null;\n let directive = null;\n if (body) {\n try {\n directive = parseDirective(body);\n } catch (err) {\n if (!(err instanceof DirectiveError)) throw err;\n // Unrecognised body (e.g. free-text H1 hint) falls through to PascalCase default\n }\n }\n\n if (directive && directive.kind === \"field\") {\n // Validate the author-supplied regex through the ReDoS-safe choke point\n // before interpolating it into the composed title pattern. compileUserRegex\n // rejects unsafe/over-long sources; the returned `.source` is the\n // validated pattern (no surrounding delimiters).\n const innerSource = directive.regex\n ? compileUserRegex(directive.regex, \"title\").source.replace(\n /^\\^|\\$$/g,\n \"\",\n )\n : undefined;\n const suffix = innerSource ? `(?:${innerSource})` : `.+`;\n const label = directive.regex ? directive.regex : \"value\";\n return z\n .string()\n .regex(\n new RegExp(`^${escaped}${sep}${suffix}$`),\n `title must match '${prefix}${sep}<${label}>'`,\n );\n }\n\n if (directive && directive.kind === \"enum\") {\n const choicePattern = directive.choices\n .map((c) => c.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\"))\n .join(\"|\");\n return z\n .string()\n .regex(\n new RegExp(`^${escaped}${sep}(?:${choicePattern})$`),\n `title must be '${prefix}${sep}<${directive.choices.join(\" | \")}>'`,\n );\n }\n\n // Default: PascalCase suffix.\n return z\n .string()\n .regex(\n new RegExp(`^${escaped}${sep}[A-Z][A-Za-z0-9]*$`),\n `title must be '${prefix}${sep}PascalCaseName'`,\n );\n }\n\n if (prefix) {\n const escaped = prefix.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return z\n .string()\n .regex(new RegExp(`^${escaped}$`), `title must be '${prefix}'`);\n }\n\n return z.string().min(1);\n}\n","/**\n * Converts a section heading into a camelCase key.\n *\n * Words are split on whitespace AND hyphens, so headings that contain\n * either separator produce the same camelCase shape.\n *\n * Examples:\n * - `\"1. Summary\"` → `\"summary\"`\n * - `\"4. Inputs (Props)\"` → `\"inputs\"`\n * - `\"8. Visual States\"` → `\"visualStates\"`\n * - `\"7. Internal State\"` → `\"internalState\"`\n * - `\"5. Slots / Content Projection\"` → `\"slots\"`\n * - `\"Cross-Domain\"` → `\"crossDomain\"`\n *\n * @param heading - The raw section heading text to convert.\n * @returns A camelCase key derived from the heading.\n */\nexport function headingToKey(heading: string): string {\n // Strip leading numbering like \"1.\" or \"3.2\"\n const withoutNumber = heading.replace(/^\\d+(\\.\\d+)*\\.\\s*/, \"\");\n // Strip parenthetical suffixes and slash-separated parts\n const cleaned = withoutNumber\n .replace(/\\s*\\(.*\\)\\s*$/, \"\")\n .replace(/\\s*\\/.*$/, \"\")\n .trim();\n // CamelCase from words: split on whitespace AND hyphens so `Cross-Domain`\n // and `Cross Domain` both yield `crossDomain`.\n const words = cleaned.split(/[\\s-]+/).filter(Boolean);\n if (words.length === 0) return heading.toLowerCase();\n const [first, ...rest] = words;\n return (\n first.toLowerCase() +\n rest\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase())\n .join(\"\")\n );\n}\n","import { DirectiveError } from \"./_shared/directive-error\";\n\n/**\n * Walks the raw template string and throws {@link DirectiveError} for any\n * structural violation before remark-parse runs:\n *\n * - Inline directive (`<!-- TEMPLATE-ONLY:` preceded by content on the same\n * line) without `-->` on the same line.\n * - Block directive opener at column ≤ 3 with no content before it, whose\n * matching `-->` cannot be found.\n *\n * @param raw - Raw template markdown string.\n * @param file - Optional source file path for error messages.\n * @returns Nothing; throws {@link DirectiveError} if a violation is found.\n */\nexport function validateDirectiveShape(raw: string, file?: string): void {\n const lines = raw.split(\"\\n\");\n\n for (let i = 0; i < lines.length; i++) {\n const line = lines[i] ?? \"\";\n const openerIdx = line.indexOf(\"<!-- TEMPLATE-ONLY:\");\n if (openerIdx < 0) continue;\n\n const beforeOpener = line.slice(0, openerIdx).trim();\n const isInline = beforeOpener.length > 0;\n const closesOnSameLine = line.indexOf(\"-->\", openerIdx) > -1;\n\n const lineNum = i + 1;\n const col = openerIdx + 1;\n const pos = { line: lineNum, column: col };\n\n if (isInline && !closesOnSameLine) {\n throw new DirectiveError(\n `${file ?? \"template.md\"}:${lineNum}:${col}: inline TEMPLATE-ONLY directive must close on the same line; \"-->\" not found before line end`,\n { position: pos, file },\n );\n }\n\n if (!isInline && !closesOnSameLine) {\n // Block directive — find the closing -->\n let found = false;\n for (let j = i + 1; j < lines.length; j++) {\n if ((lines[j] ?? \"\").includes(\"-->\")) {\n found = true;\n break;\n }\n }\n if (!found) {\n throw new DirectiveError(\n `${file ?? \"template.md\"}:${lineNum}:${col}: block TEMPLATE-ONLY directive is unclosed; \"-->\" not found`,\n { position: pos, file },\n );\n }\n }\n }\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,qBAAqB;;;ACA9B,IAAM,mBAAmB;AAUlB,SAAS,qBAAqB,MAA6B;AAChE,QAAM,IAAI,KAAK,MAAM,gBAAgB;AACrC,SAAO,IAAI,EAAE,CAAC,EAAE,KAAK,IAAI;AAC3B;;;ADGO,IAAM,WAA8B,CAAC,OAAO,EAAE,QAAQ,MAAM;AACjE,QAAM,qBAAqB,CAAC,MAAwB;AAClD,QAAI,OAAO,MAAM,YAAY,MAAM,KAAM,QAAO;AAChD,UAAM,OAAO;AACb,QAAI,KAAK,SAAS,UAAU,OAAO,KAAK,UAAU,UAAU;AAC1D,UAAI,qBAAqB,KAAK,KAAK,MAAM,KAAM,QAAO;AAAA,IACxD;AACA,QAAI,MAAM,QAAQ,KAAK,QAAQ,GAAG;AAChC,aAAO,KAAK,SAAS,KAAK,kBAAkB;AAAA,IAC9C;AACA,WAAO;AAAA,EACT;AAEA,aAAW,KAAK,OAAO;AACrB,QAAI,mBAAmB,CAAC,GAAG;AACzB,YAAM,IAAI;AAAA,QACR,YAAY,OAAO;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAa,EAAE,MAAM,QAAQ,UAAU,MAAM;AACnD,SAAO,WAAW,MAAM,EAAE,YAAY,CAAC,cAAc,CAAC,EAAE,CAAC,EAAE,KAAK;AAClE;;;AExCA,SAAS,gBAAgB;AAYlB,IAAM,QAA6C,CACxD,OACA,EAAE,QAAQ,MACP;AACH,QAAM,IAAI,MAAM,KAAK,CAAC,MAAkB,EAAE,SAAS,OAAO;AAC1D,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,YAAY,OAAO,wBAAwB;AACnE,QAAM,CAAC,MAAM,GAAG,IAAI,IAAI,EAAE;AAC1B,QAAM,UAAU,KAAK,SAAS,IAAI,CAAC,MAAM,SAAS,CAAC,EAAE,KAAK,CAAC;AAC3D,SAAO,KAAK,IAAI,CAAC,QAAQ;AAIvB,UAAM,MAAM,uBAAO,OAAO,IAAI;AAC9B,QAAI,SAAS;AAAA,MACX,CAAC,MAAM,MAAO,IAAI,QAAQ,CAAC,CAAC,IAAI,SAAS,IAAI,EAAE,KAAK;AAAA,IACtD;AACA,WAAO;AAAA,EACT,CAAC;AACH;;;AC9BA,SAAS,YAAAA,iBAAgB;AAWlB,IAAM,aAAkC,CAAC,OAAO,EAAE,QAAQ,MAAM;AACrE,QAAM,IAAI,MAAM,KAAK,CAAC,MAAiB,EAAE,SAAS,MAAM;AACxD,MAAI,CAAC,EAAG,OAAM,IAAI,MAAM,YAAY,OAAO,uBAAuB;AAClE,SAAO,EAAE,SAAS,IAAI,CAAC,SAASA,UAAS,IAAI,EAAE,KAAK,CAAC;AACvD;;;ACfA,SAAS,YAAAC,iBAAgB;AAWlB,IAAM,WAA4D,CACvE,OACA,EAAE,QAAQ,MACP;AACH,QAAM,OAAO,MAAM,KAAK,CAAC,MAAiB,EAAE,SAAS,MAAM;AAC3D,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,YAAY,OAAO,uBAAuB;AACrE,SAAO,KAAK,SAAS,IAAI,CAAC,UAAoB;AAAA,IAC5C,SAAS,KAAK,WAAW;AAAA,IACzB,MAAMA,UAAS,IAAI,EAAE,KAAK;AAAA,EAC5B,EAAE;AACJ;;;ACVO,IAAM,aAAkE,CAC7E,UAEA,MACG,OAAO,CAAC,MAAiB,EAAE,SAAS,MAAM,EAC1C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,MAAM,OAAO,EAAE,MAAM,EAAE;;;ACJnD,IAAM,WAAqC,CAAC,UAAU;;;ACHtD,IAAM,WACX,CAAI,OACJ,CAAC,OAAO,QAAQ;AACd,MAAI;AACF,WAAO,GAAG,OAAO,GAAG;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;ACLK,SAAS,qBAAqB,MAGiB;AACpD,SAAO,CAAC,OAAO,EAAE,QAAQ,MAAM;AAC7B,UAAM,MAAM,MAAM;AAAA,MAChB,CAAC,MAAiB,EAAE,SAAS,UAAU,KAAK,OAAO,KAAK,EAAE,KAAK;AAAA,IACjE;AACA,QAAI,QAAQ,IAAI;AACd,YAAM,IAAI;AAAA,QACR,YAAY,OAAO,kBAAkB,KAAK,eAAe,kBAAkB;AAAA,MAC7E;AAAA,IACF;AACA,UAAM,OAAO,MAAM,MAAM,CAAC;AAC1B,QAAI,CAAC,QAAQ,KAAK,SAAS,QAAQ;AACjC,YAAM,IAAI;AAAA,QACR,YAAY,OAAO,6BAA6B,KAAK,eAAe,YAAY;AAAA,MAClF;AAAA,IACF;AACA,WAAO,EAAE,MAAM,KAAK,QAAQ,MAAM,OAAO,KAAK,MAAM;AAAA,EACtD;AACF;;;ACjCA,SAAS,YAAAC,iBAAgB;AAuBlB,SAAS,cAAoC,MAKpB;AAC9B,SAAO,CAAC,OAAO,QAAQ;AACrB,UAAM,SAAsD,CAAC;AAC7D,QAAI,UAA4D;AAEhE,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,IAAI,GAAG;AACvB,YAAI,QAAS,QAAO,KAAK,OAAO;AAChC,kBAAU;AAAA,UACR,SAAS,KAAK,cAAc,IAAI,KAAKA,UAAS,IAAI,EAAE,KAAK;AAAA,UACzD,OAAO,KAAK,kBAAkB,CAAC,IAAI,IAAI,CAAC;AAAA,QAC1C;AAAA,MACF,WAAW,SAAS;AAClB,gBAAQ,MAAM,KAAK,IAAI;AAAA,MACzB;AAAA,IACF;AACA,QAAI,QAAS,QAAO,KAAK,OAAO;AAEhC,WAAO,OAAO,IAAI,CAAC,MAAM;AACvB,YAAM,MAA+B,EAAE,SAAS,EAAE,QAAQ;AAC1D,iBAAW,CAAC,KAAK,EAAE,KAAK,OAAO,QAAQ,KAAK,KAAK,GAAG;AAClD,YAAI,GAAG,IAAI,GAAG,EAAE,OAAO,EAAE,SAAS,GAAG,IAAI,OAAO,MAAM,EAAE,OAAO,GAAG,CAAC;AAAA,MACrE;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AACF;;;ACtDA,SAAS,YAAAC,iBAAgB;AAqBlB,SAAS,SAA+B,MAGf;AAC9B,SAAO,CAAC,OAAO,QAAQ;AACrB,QAAI,QAAQ,KAAK;AACjB,WAAO,cAAc;AAAA,MACnB,UAAU,CAAC,MAAoB;AAC7B,YAAI,EAAE,SAAS,UAAW,QAAO;AACjC,YAAI,UAAU,OAAW,SAAQ,EAAE;AACnC,eAAO,EAAE,UAAU;AAAA,MACrB;AAAA,MACA,aAAa,CAAC,MAAMC,UAAS,CAAC,EAAE,KAAK;AAAA,MACrC,OAAO,KAAK;AAAA,MACZ,iBAAiB;AAAA,IACnB,CAAC,EAAE,OAAO,GAAG;AAAA,EACf;AACF;;;ACtCA,SAAS,eAAe;AACxB,OAAO,iBAAiB;AACxB,OAAO,uBAAuB;AAC9B,OAAO,eAAe;AACtB,SAAS,SAAS;;;ACJlB,SAAS,YAAAC,iBAAgB;;;ACAzB,SAAS,SAAS,iBAAiB;AAgB5B,SAAS,mBAAmB,MAAqB;AACtD,QAAM,OAAO,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACxD,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,MAAO,KAA2B;AACxC,QAAM,SAAS,UAAU,GAAG;AAC5B,SAAO,UAAU,CAAC;AACpB;;;ADLO,SAAS,SACd,MACA,MAKA;AACA,QAAM,cAAc,mBAAmB,IAAI;AAC3C,MAAI,QAAQ;AACZ,QAAM,WAAW,oBAAI,IAA2B;AAChD,MAAI,UAAyB;AAE7B,aAAW,QAAQ,KAAK,UAAU;AAChC,QACE,KAAK,eAAe,UACpB,CAAC,SACD,KAAK,SAAS,aACd,KAAK,UAAU,KAAK,YACpB;AACA,cAAQC,UAAS,IAAI,EAAE,KAAK;AAC5B;AAAA,IACF;AACA,QAAI,KAAK,SAAS,aAAa,KAAK,UAAU,KAAK,cAAc;AAC/D,gBAAUA,UAAS,IAAI,EAAE,KAAK;AAC9B,eAAS,IAAI,SAAS,CAAC,CAAC;AACxB;AAAA,IACF;AACA,QAAI,QAAS,UAAS,IAAI,OAAO,EAAG,KAAK,IAAI;AAAA,EAC/C;AACA,SAAO,EAAE,aAAa,OAAO,SAAS;AACxC;;;AD0BO,SAAS,gBACd,MAGA;AACA,QAAM,QAAoC,CAAC;AAI3C,QAAM,cAAc,EAAE,QAAQ,EAAE,SAAS;AACzC,MAAI,KAAK,MAAO,OAAM,QAAQ,KAAK,MAAM;AACzC,aAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AACtD,UAAM,GAAG,IAAI,IAAI,WAAW,IAAI,OAAO,SAAS,IAAI,IAAI;AAAA,EAC1D;AACA,MAAI,YAAwB,EAAE,OAAO,KAAK,EAAE,OAAO;AACnD,MAAI,KAAK,QAAQ;AACf,gBAAY,UAAU;AAAA,MAAY,CAAC,KAAK,QACtC,KAAK,OAAQ,KAAiB,GAAG;AAAA,IACnC;AAAA,EACF;AAEA,QAAM,eAAe,KAAK,gBAAgB;AAC1C,QAAM,aAAa,KAAK,QAAS,KAAK,cAAc,IAAK;AAEzD,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAOL,MAAM,KAAuB;AAC3B,YAAM,OAAO,QAAQ,EAClB,IAAI,WAAW,EACf,IAAI,mBAAmB,CAAC,MAAM,CAAC,EAC/B,IAAI,SAAS,EACb,MAAM,GAAG;AACZ,YAAM,EAAE,aAAa,OAAO,SAAS,IAAI,SAAS,MAAM;AAAA,QACtD;AAAA,QACA;AAAA,MACF,CAAC;AAED,YAAM,SAAkC,CAAC;AACzC,UAAI,gBAAgB,OAAW,QAAO,cAAc;AACpD,UAAI,KAAK,MAAO,QAAO,QAAQ;AAE/B,iBAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,QAAQ,GAAG;AACtD,cAAM,UAAU,IAAI,WAAW;AAC/B,cAAM,QAAQ,SAAS,IAAI,OAAO;AAClC,YAAI,CAAC,OAAO;AACV,cAAI,IAAI,SAAU;AAClB,gBAAM,IAAI,MAAM,8BAA8B,OAAO,GAAG;AAAA,QAC1D;AACA,YAAI,MAAM,WAAW,KAAK,IAAI,SAAU;AACxC,eAAO,GAAG,IAAI,IAAI,QAAQ,OAAO,EAAE,SAAS,QAAQ,CAAC;AAAA,MACvD;AAEA,aAAO,UAAU,MAAM,MAAM;AAAA,IAC/B;AAAA,EACF;AACF;;;AGtIA,SAAS,WAAAC,gBAAe;AACxB,OAAOC,kBAAiB;AACxB,OAAOC,wBAAuB;AAC9B,OAAOC,gBAAe;;;ACHtB,SAAS,KAAAC,UAAS;;;ACcX,SAAS,oBAAoB,OAAyB;AAC3D,QAAM,UAAoB,CAAC;AAC3B,MAAI,UAAU;AACd,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,QAAQ;AACvB,UAAM,KAAK,MAAM,CAAC;AAClB,QAAI,OAAO,MAAM;AACf,YAAM,OAAO,MAAM,IAAI,CAAC;AACxB,UAAI,SAAS,MAAM;AACjB,mBAAW;AACX,aAAK;AAAA,MACP,WAAW,SAAS,KAAK;AACvB,mBAAW;AACX,aAAK;AAAA,MACP,OAAO;AACL,mBAAW,QAAQ,QAAQ;AAC3B,aAAK;AAAA,MACP;AAAA,IACF,WAAW,OAAO,KAAK;AACrB,cAAQ,KAAK,QAAQ,KAAK,CAAC;AAC3B,gBAAU;AACV;AAAA,IACF,OAAO;AACL,iBAAW;AACX;AAAA,IACF;AAAA,EACF;AACA,UAAQ,KAAK,QAAQ,KAAK,CAAC;AAC3B,SAAO,QAAQ,OAAO,OAAO;AAC/B;;;AC3BO,SAAS,UAAU,MAAkD;AAC1E,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACjD,QAAM,cAAc,MAAM,CAAC,KAAK;AAChC,QAAM,QAAQ,YAAY,MAAM,QAAQ,MAAM,EAAE,KAAK;AACrD,QAAM,UAAU,oBAAoB,KAAK;AACzC,QAAM,WAAW,CAAC,MAAM,MAAM,CAAC,EAAE,SAAS,UAAU;AACpD,SAAO,EAAE,MAAM,QAAQ,SAAS,SAAS;AAC3C;;;ACNO,SAAS,WAAW,MAAmD;AAC5E,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACjD,MAAI,WAAW;AACf,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,UAAU;AAAA,IAEvB,WAAW,SAAS,YAAY;AAC9B,iBAAW;AAAA,IACb,WAAW,SAAS,YAAY;AAC9B,iBAAW;AAAA,IACb,WAAW,KAAK,WAAW,OAAO,GAAG;AACnC,YAAM,IAAI,KAAK,MAAM,WAAW;AAChC,UAAI,EAAG,SAAQ,EAAE,CAAC;AAAA,IACpB,WAAW,KAAK,WAAW,UAAU,GAAG;AACtC,qBAAe,KACZ,MAAM,WAAW,MAAM,EACvB,QAAQ,SAAS,EAAE,EACnB,QAAQ,SAAS,EAAE;AAAA,IACxB,WAAW,KAAK,WAAW,UAAU,GAAG;AACtC,YAAM,OAAO,KAAK,MAAM,WAAW,MAAM;AACzC,YAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,UAAI,QAAQ,IAAI;AACd,iBAAS;AAAA,UACP,KAAK,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AAAA,UAC/B,OAAO,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AAAA,QACpC;AAAA,MACF;AAAA,IACF;AAAA,EAEF;AAEA,SAAO,EAAE,MAAM,SAAS,UAAU,OAAO,cAAc,OAAO;AAChE;;;AC7CO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EACxC,YACE,SACA,SAKA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO,SAAS;AACrB,SAAK,WAAW,SAAS;AACzB,SAAK,OAAO,SAAS;AAAA,EACvB;AAAA;AAAA,EAES;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AACX;;;AChBO,SAAS,uBACd,MACwC;AACxC,QAAM,WAAW,KAAK,MAAM,IAAI;AAChC,QAAM,aAAa,SAAS,CAAC,KAAK;AAClC,QAAM,YAAY,SAAS,MAAM,CAAC;AAGlC,aAAW,QAAQ,WAAW;AAC5B,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,EAAG;AAC1B,QAAI,QAAQ,WAAW,IAAI,EAAG;AAC9B,UAAM,IAAI;AAAA,MACR,gFAAgF,OAAO;AAAA,MACvF,EAAE,KAAK;AAAA,IACT;AAAA,EACF;AAEA,QAAM,QAAQ,WACX,MAAM,WAAW,MAAM,EACvB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAEjB,MAAIC,YAAW;AAEf,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,YAAY;AACvB,MAAAA,YAAW;AAAA,IACb,WAAW,SAAS,YAAY;AAAA,IAEhC,OAAO;AACL,YAAM,IAAI,eAAe,+BAA+B,IAAI,KAAK;AAAA,QAC/D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,YAAY,UAAAA,UAAS;AACtC;;;ACxCO,SAAS,WAAW,MAAmD;AAC5E,QAAM,QAAQ,KAAK,MAAM,IAAI,EAAE,MAAM,CAAC;AACtC,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,EAAG;AAC1B,QAAI,QAAQ,WAAW,IAAI,EAAG;AAC9B,UAAM,IAAI;AAAA,MACR,6DAA6D,OAAO;AAAA,MACpE,EAAE,KAAK;AAAA,IACT;AAAA,EACF;AACA,SAAO,EAAE,MAAM,QAAQ;AACzB;;;ACVO,SAAS,gBAAgB,MAA0B;AACxD,QAAM,QAAQ,KAAK,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC;AACjD,MAAI,WAAW;AACf,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,UAAU;AAAA,IAEvB,WAAW,SAAS,YAAY;AAC9B,iBAAW;AAAA,IACb,WAAW,SAAS,YAAY;AAC9B,iBAAW;AAAA,IACb,WAAW,KAAK,WAAW,OAAO,GAAG;AACnC,YAAM,IAAI,KAAK,MAAM,WAAW;AAChC,UAAI,EAAG,SAAQ,EAAE,CAAC;AAAA,IACpB,WAAW,KAAK,WAAW,OAAO,GAAG;AACnC,oBAAc,oBAAoB,KAAK,MAAM,QAAQ,MAAM,EAAE,KAAK,CAAC;AAAA,IACrE,WAAW,KAAK,WAAW,UAAU,GAAG;AACtC,qBAAe,KACZ,MAAM,WAAW,MAAM,EACvB,QAAQ,SAAS,EAAE,EACnB,QAAQ,SAAS,EAAE;AAAA,IACxB;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,OAAO,aAAa,aAAa;AACtD;;;ACzBO,SAAS,kBACd,MACmC;AACnC,QAAM,WAAW,KAAK,MAAM,IAAI;AAChC,QAAM,aAAa,SAAS,CAAC,KAAK;AAClC,QAAM,YAAY,SAAS,MAAM,CAAC;AAGlC,QAAM,cAAc,WACjB,MAAM,MAAM,MAAM,EAClB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAEjB,QAAM,UAAsC,CAAC;AAC7C,MAAI;AACJ,MAAI;AACJ,MAAI,kBAAkB;AAEtB,aAAW,QAAQ,aAAa;AAC9B,QAAI,KAAK,WAAW,WAAW,GAAG;AAChC,gBAAU,SAAS,KAAK,MAAM,YAAY,MAAM,EAAE,KAAK,GAAG,EAAE;AAAA,IAC9D,WAAW,KAAK,WAAW,WAAW,GAAG;AACvC,gBAAU,SAAS,KAAK,MAAM,YAAY,MAAM,EAAE,KAAK,GAAG,EAAE;AAAA,IAC9D,WAAW,SAAS,oBAAoB;AACtC,wBAAkB;AAAA,IACpB;AAAA,EACF;AAGA,aAAW,QAAQ,WAAW;AAC5B,QAAI,KAAK,KAAK,EAAE,WAAW,EAAG;AAC9B,QAAI,KAAK,KAAK,EAAE,WAAW,IAAI,EAAG;AAGlC,QACE,KAAK,KAAK,EAAE,WAAW,WAAW,KAClC,KAAK,KAAK,EAAE,WAAW,WAAW,KAClC,KAAK,KAAK,MAAM,oBAChB;AACA,YAAM,IAAI;AAAA,QACR;AAAA,QACA,EAAE,KAAK;AAAA,MACT;AAAA,IACF;AAEA,UAAM,WAAW,KAAK,QAAQ,GAAG;AACjC,QAAI,WAAW,IAAI;AACjB,UAAI,UAAU,KAAK,MAAM,GAAG,QAAQ,EAAE,KAAK;AAG3C,UACG,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,KAC/C,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAChD;AACA,kBAAU,QAAQ,MAAM,GAAG,EAAE;AAAA,MAC/B;AACA,YAAM,OAAO,KAAK,MAAM,WAAW,CAAC,EAAE,KAAK;AAC3C,UAAI,QAAS,SAAQ,OAAO,IAAI,gBAAgB,IAAI;AAAA,IACtD;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,OAAO,SAAS,SAAS,SAAS,gBAAgB;AACnE;;;ACnEO,SAAS,sBACd,MACuC;AACvC,QAAM,WAAW,KAAK,MAAM,IAAI;AAChC,QAAM,aAAa,SAAS,CAAC,KAAK;AAClC,QAAM,YAAY,SAAS,MAAM,CAAC;AAGlC,aAAW,QAAQ,WAAW;AAC5B,UAAM,UAAU,KAAK,KAAK;AAC1B,QAAI,QAAQ,WAAW,EAAG;AAC1B,QAAI,QAAQ,WAAW,IAAI,EAAG;AAC9B,UAAM,IAAI;AAAA,MACR,+EAA+E,OAAO;AAAA,MACtF,EAAE,KAAK;AAAA,IACT;AAAA,EACF;AAEA,QAAM,QAAQ,WACX,MAAM,UAAU,MAAM,EACtB,MAAM,GAAG,EACT,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO;AAEjB,MAAIC,YAAW;AACf,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,YAAY;AACvB,MAAAA,YAAW;AAAA,IACb,WAAW,KAAK,WAAW,YAAY,GAAG;AACxC,YAAM,OAAO,KAAK,MAAM,aAAa,MAAM;AAC3C,YAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,UAAI,QAAQ,IAAI;AACd,mBAAW;AAAA,UACT,KAAK,KAAK,MAAM,GAAG,KAAK,EAAE,KAAK;AAAA,UAC/B,OAAO,KAAK,MAAM,QAAQ,CAAC,EAAE,KAAK;AAAA,QACpC;AAAA,MACF;AAAA,IACF,WAAW,KAAK,WAAW,aAAa,GAAG;AACzC,kBAAY,SAAS,KAAK,MAAM,cAAc,MAAM,EAAE,KAAK,GAAG,EAAE;AAAA,IAClE,WAAW,KAAK,WAAW,aAAa,GAAG;AACzC,kBAAY,SAAS,KAAK,MAAM,cAAc,MAAM,EAAE,KAAK,GAAG,EAAE;AAAA,IAClE;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,WAAW,UAAAA,WAAU,UAAU,WAAW,UAAU;AACrE;;;ACjCO,SAAS,eACd,MACA,MACiB;AAEjB,MACE,SAAS,WACT,KAAK,WAAW,SAAS,KACzB,KAAK,WAAW,QAAQ;AAExB,WAAO,WAAW,IAAI;AACxB,MAAI,SAAS,SAAS,KAAK,WAAW,OAAO,KAAK,KAAK,WAAW,MAAM;AACtE,WAAO,kBAAkB,IAAI;AAC/B,MACE,SAAS,aACT,KAAK,WAAW,WAAW,KAC3B,KAAK,WAAW,UAAU;AAE1B,WAAO,sBAAsB,IAAI;AACnC,MACE,SAAS,cACT,KAAK,WAAW,YAAY,KAC5B,KAAK,WAAW,WAAW;AAE3B,WAAO,uBAAuB,IAAI;AAGpC,QAAM,WAAW,KACd,MAAM,IAAI,EACV,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,IAAI,CAAC,EACxC,KAAK,IAAI,EACT,KAAK;AAGR,QAAM,aAAa,SAAS,MAAM,OAAO,EAAE,CAAC,KAAK;AAEjD,MAAI,SAAS,WAAW,OAAO,EAAG,QAAO,UAAU,QAAQ;AAC3D,MAAI,eAAe,SAAU,QAAO,WAAW,QAAQ;AAGvD,QAAM,QAAQ,cAAc,SAAS,MAAM,GAAG,EAAE;AAChD,QAAM,IAAI,eAAe,0CAA0C,KAAK,KAAK;AAAA,IAC3E;AAAA,IACA,UAAU,MAAM;AAAA,IAChB,MAAM,MAAM;AAAA,EACd,CAAC;AACH;;;AC3EA,SAAS,KAAAC,UAAS;;;ACAlB,SAAS,iBAAiB;AAI1B,IAAM,mBAAmB;AASzB,IAAM,wBAAwB;AAwBvB,SAAS,iBAAiB,KAAa,OAAwB;AACpE,QAAM,MAAM,QAAQ,QAAQ,KAAK,KAAK;AAEtC,MAAI,IAAI,SAAS,kBAAkB;AACjC,UAAM,IAAI;AAAA,MACR,QAAQ,GAAG,iBAAiB,IAAI,MAAM,MAAM,gBAAgB;AAAA,IAC9D;AAAA,EACF;AAEA,QAAM,cAAc,UAAU,KAAK,EAAE;AACrC,MAAI,YAAY,WAAW,cAAc;AAGvC,UAAM,IAAI,YAAY;AACtB,UAAM,YACJ,GAAG,SAAS,gBAAgB,EAAE,UAAU;AAC1C,QAAI,CAAC,WAAW;AACd,YAAM,SACJ,GAAG,SAAS,eACR,2BAA2B,EAAE,MAAM,MACnC;AACN,YAAM,IAAI,eAAe,QAAQ,GAAG,IAAI,MAAM,OAAO,GAAG,IAAI;AAAA,IAC9D;AAAA,EACF,WAAW,YAAY,WAAW,QAAQ;AAExC,UAAM,IAAI;AAAA,MACR,QAAQ,GAAG,8BAA8B,YAAY,MAAM,QAAQ,GAAG;AAAA,IACxE;AAAA,EACF;AAEA,MAAI;AACF,WAAO,IAAI,OAAO,GAAG;AAAA,EACvB,SAAS,KAAK;AACZ,UAAM,IAAI;AAAA,MACR,QAAQ,GAAG,gBAAgB,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAC7E;AAAA,EACF;AACF;;;AD9DO,SAAS,eACd,SACY;AACZ,QAAM,QAAoC,CAAC;AAE3C,aAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,OAAO,GAAG;AAEjD,UAAM,KAAK,KAAK,QAAQ,iBAAiB,KAAK,OAAO,GAAG,IAAI;AAC5D,QAAI;AAEJ,QAAI,KAAK,eAAe,KAAK,YAAY,SAAS,GAAG;AACnD,cAAQC,GAAE,KAAK,KAAK,WAAoC;AAAA,IAC1D,WAAW,IAAI;AACb,cAAQA,GAAE,OAAO,EAAE,MAAM,EAAE;AAAA,IAC7B,OAAO;AACL,cAAQA,GAAE,OAAO;AAAA,IACnB;AAEA,QAAI,KAAK,UAAU;AACjB,UAAI,KAAK,eAAe,KAAK,YAAY,SAAS,GAAG;AACnD,gBAAQA,GAAE,KAAK,KAAK,WAAoC;AAAA,MAC1D,WAAW,IAAI;AACb,gBAAQA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE;AAAA,MACpC,OAAO;AACL,gBAAQA,GAAE,OAAO;AAAA,MACnB;AAAA,IACF,OAAO;AACL,cAAQ,MAAM,SAAS;AAAA,IACzB;AAEA,UAAM,GAAG,IAAI;AAAA,EACf;AAEA,SAAOA,GAAE,OAAO,KAAK,EAAE,OAAO;AAChC;;;AEtCO,SAAS,eAAe,OAA8B;AAC3D,SAAO,MAAM,OAAO,CAAC,MAAiB,EAAE,SAAS,MAAM;AACzD;;;ACIO,SAAS,qBAAqB,OAAyC;AAC5E,QAAM,SAA4B,CAAC;AACnC,aAAW,KAAK,eAAe,KAAK,GAAG;AACrC,UAAM,OAAO,qBAAqB,EAAE,KAAK;AACzC,QAAI,CAAC,KAAM;AACX,UAAM,IAAI,eAAe,IAAI;AAC7B,QAAI,EAAG,QAAO,KAAK,CAAC;AAAA,EACtB;AACA,SAAO;AACT;;;ACdO,SAAS,cACd,YACA,MACmD;AACnD,SAAO,WAAW;AAAA,IAChB,CAAC,MAAkD,EAAE,SAAS;AAAA,EAChE;AACF;;;ACLO,SAAS,sBACd,MACwC;AACxC,QAAM,SAAiD,CAAC;AAExD,aAAW,QAAQ,KAAK,UAAU;AAEhC,UAAM,OAAO,KAAK,SAAS;AAAA,MACzB,CAAC,MAAsB,EAAE,SAAS;AAAA,IACpC;AACA,QAAI,CAAC,KAAM;AAGX,QAAI,QAAQ;AACZ,QAAI,YAAoC;AAExC,eAAW,SAAS,KAAK,UAAU;AACjC,UAAI,MAAM,SAAS,QAAQ;AACzB,iBAAS,MAAM;AAAA,MACjB,WAAW,MAAM,SAAS,QAAQ;AAChC,cAAM,OAAO,qBAAqB,MAAM,KAAK;AAC7C,YAAI,MAAM;AACR,sBAAY,eAAe,IAAI;AAAA,QACjC;AAAA,MACF,WAAW,MAAM,SAAS,cAAc;AAAA,MAExC;AAAA,IACF;AAEA,UAAM,WAAW,MAAM,QAAQ,GAAG;AAClC,QAAI,WAAW,IAAI;AACjB,YAAM,MAAM,MAAM,MAAM,GAAG,QAAQ,EAAE,KAAK;AAC1C,UAAI,IAAK,QAAO,GAAG,IAAI;AAAA,IACzB;AAAA,EACF;AAEA,SAAO;AACT;;;ACvCO,SAAS,cAAc,MAAqB;AACjD,QAAM,aAAa,sBAAsB,IAAI;AAC7C,SACE,OAAO,KAAK,UAAU,EAAE,SAAS,KACjC,OAAO,OAAO,UAAU,EAAE,KAAK,CAAC,MAAM,MAAM,IAAI;AAEpD;;;ACPO,SAAS,WAAW,MAAqB;AAC9C,SAAO,KAAK,SAAS;AAAA,IACnB,CAAC,SAAS,KAAK,YAAY,QAAQ,KAAK,YAAY;AAAA,EACtD;AACF;;;ACZA,SAAS,KAAAC,UAAS;AAcX,SAAS,uBACd,gBACY;AAOZ,QAAM,QAAmC,CAAC;AAC1C,aAAW,CAAC,KAAK,CAAC,KAAK,OAAO,QAAQ,cAAc,GAAG;AACrD,QAAI,CAAC,GAAG;AACN,YAAM,GAAG,IAAI,EAAE,UAAU,OAAO,UAAU,MAAM,KAAK;AACrD;AAAA,IACF;AACA,QAAI,EAAE,SAAS,QAAQ;AACrB,YAAM,GAAG,IAAI;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,UAAU,CAAC,QAAQ;AACjB,cAAI,EAAE,YAAY,CAAC,IAAK,QAAO,GAAG,GAAG;AACrC,cAAI,OAAO,CAAC,EAAE,QAAQ,SAAS,GAAG;AAChC,mBAAO,mCAAmC,EAAE,QAAQ,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,GAAG,CAAC;AACpF,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF,WAAW,EAAE,SAAS,SAAS;AAC7B,YAAM,OAAO;AAGb,YAAM,KAAK,KAAK,QAAQ,iBAAiB,KAAK,OAAO,GAAG,IAAI;AAC5D,YAAM,GAAG,IAAI;AAAA,QACX,UAAU,KAAK;AAAA,QACf,UAAU,CAAC,QAAQ;AACjB,cAAI,KAAK,YAAY,CAAC,IAAK,QAAO,GAAG,GAAG;AACxC,cAAI,OAAO,IAAI;AACb,gBAAI,CAAC,GAAG,KAAK,GAAG,EAAG,QAAO,GAAG,GAAG;AAAA,UAClC;AACA,iBAAO;AAAA,QACT;AAAA,QACA,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAAA,EACF;AAEA,SAAOC,GACJ,MAAMA,GAAE,OAAO,CAAC,EAChB,UAAU,CAAC,UAAU;AAGpB,UAAM,MAAM,uBAAO,OAAO,IAAI;AAC9B,eAAW,QAAQ,OAAO;AACxB,YAAM,MAAM,KAAK,QAAQ,GAAG;AAC5B,UAAI,OAAO,GAAG;AACZ,cAAM,IAAI,KAAK,MAAM,GAAG,GAAG,EAAE,KAAK;AAClC,cAAM,IAAI,KAAK,MAAM,MAAM,CAAC,EAAE,KAAK;AACnC,YAAI,EAAG,KAAI,CAAC,IAAI,KAAK;AAAA,MACvB;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC,EACA,YAAY,CAAC,KAAK,QAAQ;AACzB,eAAW,CAAC,KAAK,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC/C,YAAM,MAAM,IAAI,GAAG;AACnB,YAAM,MAAM,KAAK,SAAS,GAAG;AAC7B,UAAI,KAAK;AACP,YAAI,SAAS,EAAE,MAAM,UAAU,MAAM,CAAC,GAAG,GAAG,SAAS,IAAI,CAAC;AAAA,MAC5D;AACA,UAAI,KAAK,UAAU,KAAK;AACtB,cAAM,WAAW,IAAI,KAAK,OAAO,GAAG;AACpC,YAAI,aAAa,KAAK,OAAO,OAAO;AAClC,cAAI,SAAS;AAAA,YACX,MAAM;AAAA,YACN,MAAM,CAAC,GAAG;AAAA,YACV,SAAS,GAAG,GAAG,yBAAyB,KAAK,OAAO,GAAG,IAAI,KAAK,OAAO,KAAK;AAAA,UAC9E,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AACL;;;AC7FA,SAAS,KAAAC,UAAS;AAiBX,SAAS,oBACd,OACA,WACA,WACA,eACY;AACZ,QAAM,eAAeA,GAAE,OAAO;AAAA,IAC5B,SAAS,iBAAiBA,GAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC1C,OAAOA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,EAC3B,CAAC;AAED,MAAI,SAAqBA,GAAE,MAAM,YAAY;AAC7C,MAAI,UAAW,UAAU,OAAsC,IAAI,SAAS;AAC5E,MAAI,UAAW,UAAU,OAAsC,IAAI,SAAS;AAC5E,SAAO;AACT;;;AChCA,SAAS,KAAAC,UAAS;AAYX,SAAS,uBAAuB,WAAwC;AAC7E,MAAI,UAAU,SAAS,QAAQ;AAC7B,UAAM,OAAOC,GAAE,KAAK,UAAU,OAAgC;AAC9D,WAAO,UAAU,WAAW,OAAO,KAAK,SAAS;AAAA,EACnD;AACA,MAAI,UAAU,SAAS,SAAS;AAC9B,UAAM,OAAO,UAAU,QACnBA,GAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,iBAAiB,UAAU,KAAK,CAAC,IACzDA,GAAE,OAAO,EAAE,IAAI,CAAC;AACpB,WAAO,UAAU,WAAW,OAAO,KAAK,SAAS;AAAA,EACnD;AACA,SAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AACzB;;;ArBkBO,SAAS,aACd,OACA,UACkB;AAClB,QAAM,kBAAkB,qBAAqB,KAAK;AAElD,QAAM,aAAa,cAAc,iBAAiB,SAAS;AAC3D,QAAM,SAAS,cAAc,iBAAiB,KAAK;AACnD,QAAM,cAAc,cAAc,iBAAiB,UAAU;AAE7D,QAAM,cACH,YAAY,YAAY,QAAQ,mBAAmB,WACnD,aAAa,YAAY;AAG5B,QAAM,eAAe,MAAM,OAAO,CAAC,MAAM;AACvC,QAAI,EAAE,SAAS,OAAQ,QAAO;AAC9B,UAAM,OAAO,qBAAqB,EAAE,KAAK;AACzC,WAAO,SAAS;AAAA,EAClB,CAAC;AAGD,MAAI,aAAa;AACf,QAAI,QAAQ;AACV,YAAM,IAAI;AAAA,QACR,YAAY,QAAQ;AAAA,MACtB;AAAA,IACF;AACA,QAAI,UAA8B;AAClC,QAAI,SAAqBC,GAAE,OAAO,EAAE,IAAI,CAAC;AACzC,QAAI,YAAY;AACd,gBAAU,SAAkB,QAAQ;AACpC,eAAS,OAAO,SAAS;AAAA,IAC3B;AACA,WAAO,EAAE,SAAS,QAAQ,UAAU,WAAW;AAAA,EACjD;AAGA,QAAM,iBAAiB,aAAa;AAAA,IAClC,CAAC,MAAoB,EAAE,SAAS;AAAA,EAClC;AACA,MAAI,gBAAgB;AAClB,UAAM,YAAY,YAAY;AAC9B,UAAM,YAAY,YAAY;AAG9B,QAAI;AACJ,UAAM,eAAe,aAAa;AAAA,MAChC,CAAC,MAAoB,EAAE,SAAS;AAAA,IAClC;AACA,QAAI,cAAc;AAChB,YAAM,aAAa,aAAa,SAAS;AAAA,QACvC,CAAC,MAAiB,EAAE,SAAS;AAAA,MAC/B;AACA,UAAI,YAAY;AACd,cAAM,OAAO,qBAAqB,WAAW,KAAK;AAClD,YAAI,MAAM;AACR,gBAAM,MAAM,eAAe,IAAI;AAC/B,cAAI,IAAI,SAAS,WAAW,IAAI,SAAS,QAAQ;AAC/C,4BAAgB,uBAAuB,GAAG;AAAA,UAC5C,OAAO;AACL,kBAAM,IAAI;AAAA,cACR,sEAAsE,IAAI,IAAI;AAAA,YAChF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,UAAM,SAAS;AAAA,MACb;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO;AAAA,MACL,SAAS,SAAS,EAAE,OAAO,EAAE,OAAO,WAAW,EAAE,CAAC;AAAA,MAClD;AAAA,MACA,UAAU;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,WAAW,aAAa,KAAK,CAAC,MAAM,EAAE,SAAS,OAAO;AAC5D,MAAI,UAAU,UAAU;AACtB,QAAI,YAAwBA,GAAE,OAAOA,GAAE,OAAO,GAAGA,GAAE,OAAO,CAAC;AAC3D,QAAI,OAAQ,aAAY,eAAe,OAAO,OAAO;AAErD,QAAI,cAA0BA,GAAE,MAAM,SAAS;AAC/C,QAAI,QAAQ;AACV,oBAAe,YAA2C;AAAA,QACxD,OAAO;AAAA,MACT;AACF,QAAI,QAAQ;AACV,oBAAe,YAA2C;AAAA,QACxD,OAAO;AAAA,MACT;AAEF,QAAI,UAA8B;AAClC,QAAI,YAAY;AACd,gBAAU,SAAkB,KAAK;AACjC,oBAAc,YAAY,SAAS;AAAA,IACrC;AAEA,WAAO,EAAE,SAAS,QAAQ,aAAa,UAAU,WAAW;AAAA,EAC9D;AAGA,QAAM,WAAW,aAAa,KAAK,CAAC,MAAiB,EAAE,SAAS,MAAM;AACtE,MAAI,UAAU;AACZ,QAAI,WAAW,QAAQ,GAAG;AACxB,aAAO;AAAA,QACL,SAAS;AAAA,QACT,QAAQA,GAAE,MAAMA,GAAE,OAAO,EAAE,SAASA,GAAE,QAAQ,GAAG,MAAMA,GAAE,OAAO,EAAE,CAAC,CAAC;AAAA,QACpE,UAAU;AAAA,MACZ;AAAA,IACF;AAEA,UAAM,WAAW,sBAAsB,QAAQ;AAC/C,QAAI,cAAc,QAAQ,GAAG;AAC3B,YAAM,SAAS,uBAAuB,QAAQ;AAC9C,aAAO,EAAE,SAAS,YAAY,QAAQ,UAAU,WAAW;AAAA,IAC7D;AAGA,WAAO;AAAA,MACL,SAAS;AAAA,MACT,QAAQA,GAAE,MAAMA,GAAE,OAAO,CAAC;AAAA,MAC1B,UAAU;AAAA,IACZ;AAAA,EACF;AAGA,QAAM,IAAI;AAAA,IACR,YAAY,QAAQ;AAAA,EACtB;AACF;;;AsBjLA,SAAS,YAAAC,iBAAgB;AAiBlB,SAAS,cACd,MACA,YACA,cAC4B;AAC5B,QAAM,WAAW,oBAAI,IAA2B;AAChD,MAAI,UAAyB;AAC7B,MAAI,YAAY;AAEhB,aAAW,QAAQ,KAAK,UAAU;AAChC,QAAI,KAAK,SAAS,aAAa,KAAK,UAAU,cAAc,CAAC,WAAW;AACtE,kBAAY;AACZ;AAAA,IACF;AACA,QAAI,KAAK,SAAS,aAAa,KAAK,UAAU,cAAc;AAE1D,iBAAW,SAAS,KAAK,UAAU;AACjC,YAAI,MAAM,SAAS,QAAQ;AACzB,gBAAM,OAAO,qBAAqB,MAAM,KAAK;AAC7C,cAAI,SAAS,MAAM;AACjB,kBAAM,MAAM,KAAK,UAAU;AAC3B,kBAAM,IAAI;AAAA,cACR;AAAA,cACA;AAAA,gBACE;AAAA,gBACA,UAAU,MACN,EAAE,MAAM,IAAI,MAAM,QAAQ,IAAI,OAAO,IACrC;AAAA,cACN;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA,gBAAUC,UAAS,IAAI,EAAE,KAAK;AAC9B,eAAS,IAAI,SAAS,CAAC,CAAC;AACxB;AAAA,IACF;AACA,QAAI,YAAY,MAAM;AACpB,eAAS,IAAI,OAAO,EAAG,KAAK,IAAI;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;;;AC5DA,SAAS,KAAAC,UAAS;AAsBX,SAAS,iBACd,MACA,OACyB;AACzB,QAAM,IAAI,KAAK,SAAS;AAAA,IACtB,CAAC,MAAoB,EAAE,SAAS,aAAa,EAAE,UAAU;AAAA,EAC3D;AACA,MAAI,CAAC,EAAG,QAAO;AAGf,MAAI,SAAS;AACb,MAAI,iBAAiB;AACrB,MAAI;AACJ,aAAW,SAAS,EAAE,UAAU;AAC9B,QAAI,MAAM,SAAS,OAAQ,WAAU,MAAM;AAAA,aAClC,MAAM,SAAS,QAAQ;AAC9B,uBAAiB;AACjB,sBAAgB,MAAM;AACtB;AAAA,IACF;AAAA,EACF;AAIA,WAAS,OAAO,QAAQ,QAAQ,EAAE;AAClC,QAAM,mBAAmB,MAAM,KAAK,MAAM;AAC1C,WAAS,OAAO,QAAQ,QAAQ,EAAE;AAElC,MAAI,UAAU,gBAAgB;AAC5B,UAAM,UAAU,OAAO,QAAQ,uBAAuB,MAAM;AAC5D,UAAM,MAAM,mBAAmB,MAAM;AAErC,UAAM,OAAO,gBAAgB,qBAAqB,aAAa,IAAI;AACnE,QAAI,YAAY;AAChB,QAAI,MAAM;AACR,UAAI;AACF,oBAAY,eAAe,IAAI;AAAA,MACjC,SAAS,KAAK;AACZ,YAAI,EAAE,eAAe,gBAAiB,OAAM;AAAA,MAE9C;AAAA,IACF;AAEA,QAAI,aAAa,UAAU,SAAS,SAAS;AAK3C,YAAM,cAAc,UAAU,QAC1B,iBAAiB,UAAU,OAAO,OAAO,EAAE,OAAO;AAAA,QAChD;AAAA,QACA;AAAA,MACF,IACA;AACJ,YAAM,SAAS,cAAc,MAAM,WAAW,MAAM;AACpD,YAAM,QAAQ,UAAU,QAAQ,UAAU,QAAQ;AAClD,aAAOC,GACJ,OAAO,EACP;AAAA,QACC,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG,GAAG,MAAM,GAAG;AAAA,QACxC,qBAAqB,MAAM,GAAG,GAAG,IAAI,KAAK;AAAA,MAC5C;AAAA,IACJ;AAEA,QAAI,aAAa,UAAU,SAAS,QAAQ;AAC1C,YAAM,gBAAgB,UAAU,QAC7B,IAAI,CAAC,MAAM,EAAE,QAAQ,uBAAuB,MAAM,CAAC,EACnD,KAAK,GAAG;AACX,aAAOA,GACJ,OAAO,EACP;AAAA,QACC,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG,MAAM,aAAa,IAAI;AAAA,QACnD,kBAAkB,MAAM,GAAG,GAAG,IAAI,UAAU,QAAQ,KAAK,KAAK,CAAC;AAAA,MACjE;AAAA,IACJ;AAGA,WAAOA,GACJ,OAAO,EACP;AAAA,MACC,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG,oBAAoB;AAAA,MAChD,kBAAkB,MAAM,GAAG,GAAG;AAAA,IAChC;AAAA,EACJ;AAEA,MAAI,QAAQ;AACV,UAAM,UAAU,OAAO,QAAQ,uBAAuB,MAAM;AAC5D,WAAOA,GACJ,OAAO,EACP,MAAM,IAAI,OAAO,IAAI,OAAO,GAAG,GAAG,kBAAkB,MAAM,GAAG;AAAA,EAClE;AAEA,SAAOA,GAAE,OAAO,EAAE,IAAI,CAAC;AACzB;;;AClGO,SAAS,aAAa,SAAyB;AAEpD,QAAM,gBAAgB,QAAQ,QAAQ,qBAAqB,EAAE;AAE7D,QAAM,UAAU,cACb,QAAQ,iBAAiB,EAAE,EAC3B,QAAQ,YAAY,EAAE,EACtB,KAAK;AAGR,QAAM,QAAQ,QAAQ,MAAM,QAAQ,EAAE,OAAO,OAAO;AACpD,MAAI,MAAM,WAAW,EAAG,QAAO,QAAQ,YAAY;AACnD,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,SACE,MAAM,YAAY,IAClB,KACG,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,IAAI,EAAE,MAAM,CAAC,EAAE,YAAY,CAAC,EAC/D,KAAK,EAAE;AAEd;;;ACrBO,SAAS,uBAAuB,KAAa,MAAqB;AACvE,QAAM,QAAQ,IAAI,MAAM,IAAI;AAE5B,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,UAAM,OAAO,MAAM,CAAC,KAAK;AACzB,UAAM,YAAY,KAAK,QAAQ,qBAAqB;AACpD,QAAI,YAAY,EAAG;AAEnB,UAAM,eAAe,KAAK,MAAM,GAAG,SAAS,EAAE,KAAK;AACnD,UAAM,WAAW,aAAa,SAAS;AACvC,UAAM,mBAAmB,KAAK,QAAQ,OAAO,SAAS,IAAI;AAE1D,UAAM,UAAU,IAAI;AACpB,UAAM,MAAM,YAAY;AACxB,UAAM,MAAM,EAAE,MAAM,SAAS,QAAQ,IAAI;AAEzC,QAAI,YAAY,CAAC,kBAAkB;AACjC,YAAM,IAAI;AAAA,QACR,GAAG,QAAQ,aAAa,IAAI,OAAO,IAAI,GAAG;AAAA,QAC1C,EAAE,UAAU,KAAK,KAAK;AAAA,MACxB;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,CAAC,kBAAkB;AAElC,UAAI,QAAQ;AACZ,eAAS,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACzC,aAAK,MAAM,CAAC,KAAK,IAAI,SAAS,KAAK,GAAG;AACpC,kBAAQ;AACR;AAAA,QACF;AAAA,MACF;AACA,UAAI,CAAC,OAAO;AACV,cAAM,IAAI;AAAA,UACR,GAAG,QAAQ,aAAa,IAAI,OAAO,IAAI,GAAG;AAAA,UAC1C,EAAE,UAAU,KAAK,KAAK;AAAA,QACxB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;;;A1BhBO,SAAS,cACd,aACA,MACiD;AACjD,yBAAuB,aAAa,MAAM,IAAI;AAC9C,QAAM,OAAOC,SAAQ,EAClB,IAAIC,YAAW,EACf,IAAIC,oBAAmB,CAAC,MAAM,CAAC,EAC/B,IAAIC,UAAS,EACb,MAAM,WAAW;AAEpB,QAAM,aAAa;AACnB,QAAM,eAAe;AAErB,QAAM,kBAAkB,iBAAiB,MAAM,UAAU;AACzD,QAAM,WAAW,cAAc,MAAM,YAAY,YAAY;AAG7D,QAAM,eAQF,CAAC;AAEL,aAAW,CAAC,SAAS,KAAK,KAAK,UAAU;AACvC,UAAM,YAAY,aAAa,OAAO,OAAO;AAG7C,UAAM,MAAM,aAAa,OAAO;AAEhC,iBAAa,GAAG,IAAI;AAAA,MAClB;AAAA,MACA,SAAS,UAAU;AAAA,MACnB,QAAQ,UAAU;AAAA,MAClB,UAAU,UAAU;AAAA,IACtB;AAAA,EACF;AAEA,SAAO,gBAAgB;AAAA,IACrB,OAAO,kBAAkB,EAAE,QAAQ,gBAAgB,IAAI;AAAA,IACvD,UAAU;AAAA,IACV,QAAQ,MAAM;AAAA,EAGhB,CAAC;AACH;","names":["toString","toString","toString","toString","toString","toString","toString","unified","remarkParse","remarkFrontmatter","remarkGfm","z","optional","optional","z","z","z","z","z","z","z","z","toString","toString","z","z","unified","remarkParse","remarkFrontmatter","remarkGfm"]}
|
package/dist/node.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
/** Signature of the `refine` export in a `*.refine.ts` companion file. */
|
|
4
|
+
type RefineFunction = (doc: unknown, ctx: z.core.$RefinementCtx) => void;
|
|
5
|
+
/**
|
|
6
|
+
* Looks for a `<stem>.refine.ts` file next to the template and, if found,
|
|
7
|
+
* dynamically imports its `refine` named export.
|
|
8
|
+
*
|
|
9
|
+
* The file is loaded with a plain `import()` call — Node ≥ 22.18 strips
|
|
10
|
+
* TypeScript types natively, so no `tsx` wrapper is needed at runtime.
|
|
11
|
+
*
|
|
12
|
+
* @param templatePath - Absolute path to the `*.template.md` file.
|
|
13
|
+
* @returns The `refine` function, or `undefined` if no companion file exists.
|
|
14
|
+
*/
|
|
15
|
+
declare function loadRefine(templatePath: string): Promise<RefineFunction | undefined>;
|
|
16
|
+
|
|
17
|
+
export { type RefineFunction, loadRefine };
|
package/dist/node.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// src/index/parse-template/load-refine.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
|
+
import { resolve, dirname, basename } from "path";
|
|
4
|
+
import { pathToFileURL } from "url";
|
|
5
|
+
async function loadRefine(templatePath) {
|
|
6
|
+
const dir = dirname(templatePath);
|
|
7
|
+
const stemBase = basename(templatePath).replace(/\.template\.md$/, "");
|
|
8
|
+
const fullPath = resolve(dir, `${stemBase}.refine.ts`);
|
|
9
|
+
if (!existsSync(fullPath)) return void 0;
|
|
10
|
+
const mod = await import(pathToFileURL(fullPath).href);
|
|
11
|
+
const fn = mod["refine"];
|
|
12
|
+
if (typeof fn !== "function") return void 0;
|
|
13
|
+
return fn;
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
loadRefine
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=node.js.map
|
package/dist/node.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index/parse-template/load-refine.ts"],"sourcesContent":["import { existsSync } from \"node:fs\";\nimport { resolve, dirname, basename } from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { z } from \"zod\";\n\n/** Signature of the `refine` export in a `*.refine.ts` companion file. */\nexport type RefineFunction = (doc: unknown, ctx: z.core.$RefinementCtx) => void;\n\n/**\n * Looks for a `<stem>.refine.ts` file next to the template and, if found,\n * dynamically imports its `refine` named export.\n *\n * The file is loaded with a plain `import()` call — Node ≥ 22.18 strips\n * TypeScript types natively, so no `tsx` wrapper is needed at runtime.\n *\n * @param templatePath - Absolute path to the `*.template.md` file.\n * @returns The `refine` function, or `undefined` if no companion file exists.\n */\nexport async function loadRefine(\n templatePath: string,\n): Promise<RefineFunction | undefined> {\n const dir = dirname(templatePath);\n const stemBase = basename(templatePath).replace(/\\.template\\.md$/, \"\");\n const fullPath = resolve(dir, `${stemBase}.refine.ts`);\n\n if (!existsSync(fullPath)) return undefined;\n\n const mod = (await import(pathToFileURL(fullPath).href)) as Record<\n string,\n unknown\n >;\n const fn = mod[\"refine\"];\n if (typeof fn !== \"function\") return undefined;\n return fn as RefineFunction;\n}\n"],"mappings":";AAAA,SAAS,kBAAkB;AAC3B,SAAS,SAAS,SAAS,gBAAgB;AAC3C,SAAS,qBAAqB;AAgB9B,eAAsB,WACpB,cACqC;AACrC,QAAM,MAAM,QAAQ,YAAY;AAChC,QAAM,WAAW,SAAS,YAAY,EAAE,QAAQ,mBAAmB,EAAE;AACrE,QAAM,WAAW,QAAQ,KAAK,GAAG,QAAQ,YAAY;AAErD,MAAI,CAAC,WAAW,QAAQ,EAAG,QAAO;AAElC,QAAM,MAAO,MAAM,OAAO,cAAc,QAAQ,EAAE;AAIlD,QAAM,KAAK,IAAI,QAAQ;AACvB,MAAI,OAAO,OAAO,WAAY,QAAO;AACrC,SAAO;AACT;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "markdown-schema",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Gergely Szerovay",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/gergelyszerovay/markdown-schema.git"
|
|
10
|
+
},
|
|
11
|
+
"fractalTs": {
|
|
12
|
+
"entryPoint": "./src/index.ts"
|
|
13
|
+
},
|
|
14
|
+
"main": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"exports": {
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./node": {
|
|
22
|
+
"types": "./dist/node.d.ts",
|
|
23
|
+
"default": "./dist/node.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
".claude/skills",
|
|
29
|
+
"LICENSE",
|
|
30
|
+
"README.md"
|
|
31
|
+
],
|
|
32
|
+
"bin": {
|
|
33
|
+
"validate-md": "./dist/bin/validate-md.js"
|
|
34
|
+
},
|
|
35
|
+
"engines": {
|
|
36
|
+
"node": ">=22.18.0"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "tsup",
|
|
40
|
+
"typecheck": "tsc --noEmit",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"generate-fractal-tree": "pnpm exec tsx ../../apps/cli/bin/fractal-ts.ts generate --include-source .",
|
|
43
|
+
"validate-fractal-tree": "pnpm exec tsx ../../apps/cli/bin/fractal-ts.ts validate .",
|
|
44
|
+
"destiny": "pnpm exec tsx ../../apps/destiny/bin/destiny.ts",
|
|
45
|
+
"destiny:write": "pnpm exec tsx ../../apps/destiny/bin/destiny.ts -w",
|
|
46
|
+
"lint": "oxlint --deny-warnings --type-aware --type-check",
|
|
47
|
+
"link:global": "pnpm link --global",
|
|
48
|
+
"unlink:global": "pnpm uninstall --global markdown-schema"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"@types/mdast": "^4.0.4",
|
|
52
|
+
"mdast-util-frontmatter": "^2.0.1",
|
|
53
|
+
"mdast-util-gfm": "^3.0.0",
|
|
54
|
+
"mdast-util-to-markdown": "^2.0.0",
|
|
55
|
+
"mdast-util-to-string": "^4.0.0",
|
|
56
|
+
"recheck": "^4.5.0",
|
|
57
|
+
"remark-frontmatter": "^5.0.0",
|
|
58
|
+
"remark-gfm": "^4.0.0",
|
|
59
|
+
"remark-parse": "^11.0.0",
|
|
60
|
+
"unified": "^11.0.0",
|
|
61
|
+
"yaml": "^2.8.2",
|
|
62
|
+
"zod": "^4.3.6"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "^22.19.15",
|
|
66
|
+
"oxlint": "^1.51.0",
|
|
67
|
+
"tsup": "^8.5.1",
|
|
68
|
+
"tsx": "^4.19.2",
|
|
69
|
+
"typescript": "^5.7.3",
|
|
70
|
+
"vitest": "^4.0.18"
|
|
71
|
+
}
|
|
72
|
+
}
|