@spintax/core 0.5.0 → 0.5.1
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/CHANGELOG.md +44 -0
- package/dist/index.cjs +31 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +31 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/internal/ast.ts","../src/internal/neutralize.ts","../src/internal/parser.ts","../src/internal/plurals.ts","../src/internal/validator.ts","../src/internal/extract.ts","../src/internal/errors.ts","../src/internal/render.ts","../src/internal/postprocess.ts","../src/internal/pipeline.ts","../src/internal/rng.ts","../src/index.ts"],"names":["PLURAL_PREFIX","INCLUDE_RE","VARIABLE_RE","phpTrim","PHP_LTRIM_RE","PHP_RTRIM_RE","RESTORE_RE","normalizeBaseLang","pluralArity","resolveAst","neutralize"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Internal AST for @spintax/core. The public `Ast` (spec §9.2) is the opaque,\n * versioned view; `ParsedAst` is the internal shape carrying the node tree that\n * render/validate/extract/analyze walk. Not a serialization format — never\n * persisted across engine versions.\n *\n * Tree nodes: literal / variable / enumeration / permutation / conditional /\n * plural. Directives are NOT tree nodes (plugin parity):\n * - `#set` is extracted GLOBALLY before the tree is built (line-anchored, like\n * `extract_set_directives`) → {@link ParsedAst.setDefs}; its lines are\n * stripped from the body, so a `#set` on its own line even INSIDE a group is\n * a global definition, not literal text.\n * - `#include` is resolved by the renderer as a post-tree string pass (the\n * plugin's `resolve_includes` runs after enum/perm), so it stays literal in\n * the AST here.\n * Permutation's `<config>` + per-element separators are fully parsed (PR-11b).\n */\n\n/**\n * Bumped only on a breaking change to the node shape (independent of syntax v1).\n *\n * 2 — `ParsedAst` gained `defDefs`. An `Ast` cached by an older version carries no `#def` map, so\n * rendering it would silently drop every definition; the version guard turns that into an\n * `AstVersionError` instead.\n */\nexport const AST_VERSION = 2;\n\n/** Opaque public handle (re-exported as `Ast` from the package index). */\nexport interface Ast {\n readonly astVersion: typeof AST_VERSION;\n}\n\n/** Internal parsed tree. Carries the original source so validate(Ast) can do\n * the raw-text checks (bracket balance etc.) and future offset diagnostics, and\n * the globally-extracted directive definitions (name → raw value, name lowercased).\n *\n * The two maps are separate because the directives have opposite semantics: a `#set` value is a\n * macro, substituted at every reference so its brackets re-roll each time, while a `#def` value\n * is rendered once per render and frozen. Neither is a tree node — both are line-anchored\n * pre-passes over the raw text. */\nexport interface ParsedAst extends Ast {\n readonly source: string;\n readonly setDefs: Readonly<Record<string, string>>;\n readonly defDefs: Readonly<Record<string, string>>;\n readonly nodes: readonly Node[];\n}\n\nexport type Node =\n | LiteralNode\n | VariableNode\n | EnumerationNode\n | PermutationNode\n | ConditionalNode\n | PluralNode;\n\n/** Verbatim text. */\nexport interface LiteralNode {\n readonly type: 'literal';\n readonly value: string;\n}\n\n/** `%name%` reference (name stored verbatim; lookup is case-insensitive at render). */\nexport interface VariableNode {\n readonly type: 'variable';\n readonly name: string;\n}\n\n/** `{a|b|c}` — pick one option. Each option is a node sequence. */\nexport interface EnumerationNode {\n readonly type: 'enumeration';\n readonly options: readonly (readonly Node[])[];\n}\n\n/**\n * `[<config>a|b|c]` — select/shuffle/join. PR-10 captures the raw inner\n * verbatim; PR-11 extracts the `<config>` prefix FIRST (before splitting, so a\n * `|` inside a quoted separator like `sep=\"|\"` isn't a false split — matching\n * the plugin's `extract_permutation_config` → `split_top_level` order) and\n * parses the per-element separators + option node sequences.\n */\n/** Permutation `<config>` (parsed in PR-11b). `null` size ⇒ default rules at render (§4.2). */\nexport interface PermConfig {\n readonly minsize: number | null;\n readonly maxsize: number | null;\n readonly sep: string;\n readonly lastsep: string | null;\n}\n\n/** One permutation element + its per-element separator (a trailing `<sep>` from the PREVIOUS part). */\nexport interface PermOption {\n readonly nodes: readonly Node[];\n readonly separator: string | null;\n}\n\nexport interface PermutationNode {\n readonly type: 'permutation';\n readonly config: PermConfig;\n readonly options: readonly PermOption[];\n}\n\n/**\n * `{?VAR?then|else}` / `{?!VAR?then}` — show `then` when VAR is truthy (or falsy\n * if `inverted`), else `else`. A malformed `{?…}` is NOT a conditional: the\n * parser falls back to treating the braces as an enumeration (matching the\n * plugin, where a bad conditional survives the conditional pass unchanged and\n * is then consumed by the enumeration pass).\n */\nexport interface ConditionalNode {\n readonly type: 'conditional';\n readonly name: string;\n readonly inverted: boolean;\n readonly then: readonly Node[];\n readonly else: readonly Node[];\n}\n\n/**\n * `{plural <count>: one|few|many}`. Both slots are kept RAW (they may hold\n * `%var%`): the renderer expands variables in them first (plurals run after\n * var-expansion, before enum/perm), then splits/checks/pick. The lenient path\n * (nested `{}`/`[]` in a form, or arity mismatch) re-emits\n * `{plural <countRaw>:<formsRaw>}` with fullwidth braces (U+FF5B/FF5D).\n * Discriminated by the literal `{plural ` prefix + a `:`.\n */\nexport interface PluralNode {\n readonly type: 'plural';\n readonly countRaw: string;\n readonly formsRaw: string;\n}\n\n/** Depth-first walk over every node, descending into all child sequences. */\nexport function walk(nodes: readonly Node[], visit: (n: Node) => void): void {\n for (const n of nodes) {\n visit(n);\n switch (n.type) {\n case 'enumeration':\n for (const opt of n.options) walk(opt, visit);\n break;\n case 'conditional':\n walk(n.then, visit);\n walk(n.else, visit);\n break;\n case 'permutation':\n for (const opt of n.options) walk(opt.nodes, visit);\n break;\n default:\n break; // literal / variable / plural (raw slots): no child nodes\n }\n }\n}\n\n/** Type guard: is this an internal ParsedAst produced by this engine version? */\nexport function isParsedAst(value: unknown): value is ParsedAst {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { astVersion?: unknown }).astVersion === AST_VERSION &&\n typeof (value as { source?: unknown }).source === 'string' &&\n Array.isArray((value as { nodes?: unknown }).nodes)\n );\n}\n","/**\n * T2 shielding (§6). Text-safe / context-agnostic — NOT the plugin's HTML-entity\n * encoding (that only round-trips in an HTML sink; this engine targets Telegram /\n * plaintext / CLI too). Structural chars `{ } [ ] % #` map to Private-Use-Area\n * sentinels (U+E000–U+E005) the engine's passes never interpret as markup; the\n * mandatory {@link safetyRestore} (always run, even with postProcess:false) maps\n * them back to their literal glyphs. PUA (not the `\\x00…` scheme post-process\n * uses) so the two shielding mechanisms can't collide.\n *\n * \"Text-safe\" = safe against re-interpretation as spintax markup, NOT against an\n * HTML/JS sink — neutralize does not touch `< > &`, so it is not XSS mitigation\n * (an HTML-entity variant is a host concern, §6).\n *\n * RESERVED RANGE: U+E000–U+E005 are engine sentinels. `parseTemplate` strips them\n * from author markup (template source + #include results) via {@link stripSentinels}\n * — every door from author source into a tree, so `parse()`/`analyze()`/`render()`\n * agree — and the restore rewrites them in output, so a RAW (non-neutralized) context\n * value carrying these code points will be altered — hosts should neutralize/strip\n * such data.\n */\nconst STRUCTURAL = ['{', '}', '[', ']', '%', '#'] as const;\nconst SENTINEL_BASE = 0xe000;\n\nconst SHIELD = new Map<string, string>();\nconst RESTORE = new Map<string, string>();\nSTRUCTURAL.forEach((ch, i) => {\n const sentinel = String.fromCharCode(SENTINEL_BASE + i);\n SHIELD.set(ch, sentinel);\n RESTORE.set(sentinel, ch);\n});\n\nconst SHIELD_RE = /[{}[\\]%#]/gu;\nconst RESTORE_RE = new RegExp(\n `[${String.fromCharCode(SENTINEL_BASE)}-${String.fromCharCode(SENTINEL_BASE + STRUCTURAL.length - 1)}]`,\n 'gu',\n);\n\n/** Shield data-derived (T2) input so it can't be re-interpreted as spintax markup. */\nexport function neutralize(value: string): string {\n return value.replace(SHIELD_RE, (ch) => SHIELD.get(ch) ?? ch);\n}\n\n/** Mandatory final stage: restore shielded structural chars to literal glyphs. */\nexport function safetyRestore(text: string): string {\n return text.replace(RESTORE_RE, (ch) => RESTORE.get(ch) ?? ch);\n}\n\n/** Remove stray sentinels from author markup (template / #include) so only\n * neutralize() can introduce them — otherwise safetyRestore would rewrite them. */\nexport function stripSentinels(text: string): string {\n return text.replace(RESTORE_RE, '');\n}\n","/**\n * Recursive-descent parser: template string → {@link ParsedAst}.\n *\n * Lenient by contract (spec §9.2): never throws on malformed markup. Unmatched\n * brackets, malformed `{?…}` / `{plural …}`, and bare `%` degrade gracefully\n * (bad conditional/plural fall back to an enumeration, exactly as the plugin's\n * later passes would consume them). Structural *diagnostics* are the validator's\n * job (PR-12), not the parser's.\n *\n * `#set` is extracted GLOBALLY before the tree is built ({@link extractSetDirectives},\n * line-anchored like the plugin's `extract_set_directives`), so a `#set` on its\n * own line even inside a `{…}`/`[…]` group is a global definition — matching the\n * plugin's brace-oblivious `/m` extraction — not literal text. `#include` stays\n * literal here; the renderer resolves it as a post-tree string pass (like the\n * plugin's post-enum `resolve_includes`).\n */\nimport { AST_VERSION, type Node, type ParsedAst, type PermConfig, type PermOption } from './ast';\nimport { stripSentinels } from './neutralize';\n\nconst VARIABLE_RE = /^%(\\w+)%/;\n// `\\r?` before the multiline `$` so a CRLF line strips cleanly (JS `.` excludes \\r).\n/**\n * The one grammar for `#set` and `#def`. Whitespace is `[ \\t]` (not `\\s`) so a directive is a\n * single line, and the value group is `(.*?)` so an empty value is legal. `\\r?` before the\n * multiline `$` so a CRLF line strips cleanly (JS `.` excludes \\r).\n */\nexport const DIRECTIVE_RE = /^[ \\t]*#(set|def)[ \\t]+%(\\w+)%[ \\t]*=[ \\t]*(.*?)[ \\t]*\\r?$/gmu;\nconst CONDITIONAL_NAME_RE = /[A-Za-z_]\\w*/y;\nconst PLURAL_PREFIX = 'plural ';\n\n/**\n * Parse a full template into an AST (sanitised + comments stripped + directives extracted first).\n *\n * **This is the one door from author source into a tree, and it sanitises.** Stray engine\n * sentinels (U+E000–U+E005) come out first, so a reserved-range character an author typed\n * cannot survive to be rewritten into a brace by the mandatory {@link safetyRestore} — the\n * invariant `neutralize` documents (\"only `neutralize()` may introduce a sentinel\"). It lives\n * here rather than at each caller because there were three callers and two of them (`parse()`\n * and `analyze(str)`) forgot it, so `render(parse(src))` diverged from `render(src)` on that\n * edge and broke the parse-once-reuse contract (#51).\n *\n * {@link parseSequence} is NOT sanitised, and must not be: it re-parses a variable's *value*,\n * where sentinels a host neutralized are legitimate and have to reach the safety-restore.\n *\n * `source` keeps the ORIGINAL, unsanitised text — the validator reads it to place diagnostics,\n * which must point at the bytes the author actually wrote.\n */\nexport function parseTemplate(src: string): ParsedAst {\n const { body, setDefs, defDefs } = extractDirectives(stripComments(stripSentinels(src)));\n return { astVersion: AST_VERSION, source: src, setDefs, defDefs, nodes: parseSequence(body) };\n}\n\n/** One directive occurrence, in source order, with the line it was written on. */\nexport interface DirectiveOccurrence {\n readonly kind: 'set' | 'def';\n readonly name: string;\n readonly value: string;\n readonly line: number;\n}\n\n/**\n * Global directive extraction (parity with `extract_directives`): pull every line-anchored\n * `#set`/`#def` out of the text — regardless of brace nesting — collecting name→value (name\n * lowercased), strip the lines, then collapse `\\n{3,}`→`\\n\\n`.\n *\n * `occurrences` preserves every directive line including duplicates that the two maps flatten\n * away: a validator cannot report a collision it can no longer see.\n */\nexport function extractDirectives(text: string): {\n body: string;\n setDefs: Record<string, string>;\n defDefs: Record<string, string>;\n occurrences: DirectiveOccurrence[];\n} {\n const setDefs: Record<string, string> = {};\n const defDefs: Record<string, string> = {};\n const occurrences: DirectiveOccurrence[] = [];\n\n // Match offsets ascend (replace scans left to right), so the line number resumes\n // from the previous match instead of recounting from the start of the text — a\n // fresh count per occurrence made a directive-heavy document quadratic.\n let cursorOffset = 0;\n let cursorLine = 1;\n const lineAt = (offset: number): number => {\n for (let i = cursorOffset; i < offset; i += 1) {\n if (text.charCodeAt(i) === 10) cursorLine += 1;\n }\n cursorOffset = offset;\n return cursorLine;\n };\n\n DIRECTIVE_RE.lastIndex = 0;\n const stripped = text.replace(\n DIRECTIVE_RE,\n (full: string, kind: string, rawName: string, value: string, offset: number): string => {\n const name = rawName.toLowerCase();\n occurrences.push({\n kind: kind as 'set' | 'def',\n name,\n value,\n line: lineAt(offset),\n });\n if (kind === 'def') defDefs[name] = value;\n else setDefs[name] = value;\n return '';\n },\n );\n\n return { body: stripped.replace(/\\n{3,}/gu, '\\n\\n'), setDefs, defDefs, occurrences };\n}\n\n/** Remove `/# … #/` block comments (non-greedy, spans newlines). */\nexport function stripComments(text: string): string {\n return text.replace(/\\/#[\\s\\S]*?#\\//g, '');\n}\n\n/** Parse a run of text into a node sequence (construct parsing only — no comment\n * strip / #set extraction; the renderer uses this to re-process variable values). */\nexport function parseSequence(text: string): Node[] {\n const nodes: Node[] = [];\n let literal = '';\n let i = 0;\n\n const flushLiteral = (): void => {\n if (literal !== '') {\n nodes.push({ type: 'literal', value: literal });\n literal = '';\n }\n };\n\n while (i < text.length) {\n const ch = text.charAt(i);\n\n if (ch === '{') {\n const end = findMatchingClose(text, i, '{', '}');\n if (end === -1) {\n literal += ch;\n i += 1;\n continue;\n }\n const content = text.slice(i + 1, end);\n flushLiteral();\n nodes.push(parseBraceConstruct(content));\n i = end + 1;\n continue;\n }\n\n if (ch === '[') {\n const end = findMatchingClose(text, i, '[', ']');\n if (end === -1) {\n literal += ch;\n i += 1;\n continue;\n }\n flushLiteral();\n nodes.push(parsePermutation(text.slice(i + 1, end)));\n i = end + 1;\n continue;\n }\n\n if (ch === '%') {\n const name = VARIABLE_RE.exec(text.slice(i))?.[1];\n if (name !== undefined) {\n flushLiteral();\n nodes.push({ type: 'variable', name });\n i += name.length + 2; // \"%\" + name + \"%\"\n continue;\n }\n }\n\n literal += ch;\n i += 1;\n }\n\n flushLiteral();\n return nodes;\n}\n\n/**\n * Decide what a `{…}` (content between the braces) is: a conditional (`?…`), a\n * plural (`plural …:` …), or — the default and the fallback for a malformed\n * conditional — an enumeration.\n */\nfunction parseBraceConstruct(content: string): Node {\n if (content.charAt(0) === '?') {\n const cond = tryParseConditional(content);\n if (cond) return cond;\n // Malformed conditional ⇒ fall back to enumeration (plugin parity).\n } else if (content.startsWith(PLURAL_PREFIX) && content.slice(PLURAL_PREFIX.length).includes(':')) {\n return parsePlural(content.slice(PLURAL_PREFIX.length));\n }\n return { type: 'enumeration', options: splitTopLevel(content).map((o) => parseSequence(o)) };\n}\n\n/**\n * A recognized `{?…}` as OFFSETS into the string it was found in — no branch text\n * copied out. The count-slot pass walks spans instead of substrings; slicing the\n * branch per level of nesting is quadratic on a deeply nested template, and that\n * template arrives from the public Worker.\n */\nexport interface ConditionalHead {\n readonly name: string;\n readonly inverted: boolean;\n /** Offset of the body (past `?name?`). */\n readonly bodyStart: number;\n /** Offset of the top-level `|`, or -1 when the branch stands alone. */\n readonly sepIndex: number;\n}\n\n/** A recognized `{?…}` with its branches materialized — what the parser needs. */\nexport interface ConditionalParts {\n readonly name: string;\n readonly inverted: boolean;\n readonly thenRaw: string;\n readonly elseRaw: string;\n}\n\n/**\n * Recognize `?VAR?then|else` / `?!VAR?then` in `text[contentStart, contentEnd)`\n * (the span between the braces), or null if malformed — the ONE place the\n * conditional grammar lives. Reports offsets only; {@link splitConditional} is\n * the wrapper that materializes the branches for the parser.\n *\n * The renderer needs the branches unparsed as well as parsed: the plural count\n * slot resolves conditionals textually, without resolving the enums a branch may\n * carry (spintax-js#67). Two readers, one recognizer — a second copy of these\n * rules would be a syntax-surface divergence waiting to happen (#55–#57).\n */\nexport function recognizeConditional(\n text: string,\n contentStart: number,\n contentEnd: number,\n): ConditionalHead | null {\n let p = contentStart + 1; // past the leading '?'\n let inverted = false;\n if (text.charAt(p) === '!') {\n inverted = true;\n p += 1;\n }\n\n CONDITIONAL_NAME_RE.lastIndex = p;\n const name = CONDITIONAL_NAME_RE.exec(text)?.[0];\n if (name === undefined || p + name.length > contentEnd) return null;\n p += name.length;\n\n if (text.charAt(p) !== '?') return null; // required '?' after the name\n p += 1;\n\n return { name, inverted, bodyStart: p, sepIndex: firstTopLevelPipe(text, p, contentEnd) };\n}\n\nexport function splitConditional(content: string): ConditionalParts | null {\n const head = recognizeConditional(content, 0, content.length);\n if (head === null) return null;\n\n const body = content.slice(head.bodyStart);\n const sep = head.sepIndex < 0 ? -1 : head.sepIndex - head.bodyStart;\n\n return {\n name: head.name,\n inverted: head.inverted,\n thenRaw: sep < 0 ? body : body.slice(0, sep),\n elseRaw: sep < 0 ? '' : body.slice(sep + 1),\n };\n}\n\n/** Parse `?VAR?then|else` / `?!VAR?then` (content starts with `?`), or null if malformed. */\nfunction tryParseConditional(content: string): Node | null {\n const parts = splitConditional(content);\n if (parts === null) return null;\n\n return {\n type: 'conditional',\n name: parts.name,\n inverted: parts.inverted,\n then: parseSequence(parts.thenRaw),\n else: parseSequence(parts.elseRaw),\n };\n}\n\n/** Parse `<count>: forms` (the part after the `plural ` prefix). */\nfunction parsePlural(afterPrefix: string): Node {\n const colon = afterPrefix.indexOf(':');\n // Count + raw forms are kept as strings; the renderer expands variables in them\n // FIRST (Stage 6d runs after var-expansion, before enum/perm), then splits/checks.\n return { type: 'plural', countRaw: afterPrefix.slice(0, colon), formsRaw: afterPrefix.slice(colon + 1) };\n}\n\n// ─── Permutation parsing (config + per-element separators) ────────────────────\n\nconst CONFIG_KEY_RE = /\\b(?:minsize|maxsize|sep|lastsep)\\s*=/i;\nconst MINSIZE_RE = /minsize\\s*=\\s*(\\d+)/i;\nconst MAXSIZE_RE = /maxsize\\s*=\\s*(\\d+)/i;\nconst SEP_RE = /(?<!last)sep\\s*=\\s*\"([^\"]*)\"/i; // negative lookbehind excludes \"lastsep\"\nconst LASTSEP_RE = /lastsep\\s*=\\s*\"([^\"]*)\"/i;\nconst HTML_TAG_RE = /^([a-zA-Z][a-zA-Z0-9-]*)(?:\\s+[^>]*)?\\/?$/;\nconst PER_ELEM_HTML_RE = /^[a-zA-Z][a-zA-Z0-9]*\\s/;\n\nfunction defaultPermConfig(): PermConfig {\n return { minsize: null, maxsize: null, sep: ' ', lastsep: null };\n}\n\n/** Parse a permutation body `[<config>a|b|c]` inner → config + options with per-element seps. */\nfunction parsePermutation(rawInner: string): Node {\n const { config, content } = extractPermutationConfig(rawInner);\n const options = extractPerElementSeparators(splitTopLevel(content));\n return { type: 'permutation', config, options };\n}\n\n/** Split a leading `<config>` off the body (config is extracted BEFORE the top-level split). */\nfunction extractPermutationConfig(content: string): { config: PermConfig; content: string } {\n const trimmed = phpLtrim(content);\n if (trimmed === '' || trimmed.charAt(0) !== '<') {\n return { config: defaultPermConfig(), content };\n }\n const end = findConfigEnd(trimmed);\n if (end === -1) return { config: defaultPermConfig(), content };\n\n const configStr = trimmed.slice(1, end);\n const remaining = trimmed.slice(end + 1);\n // A leading `<li>…</li>`-style tag is HTML, not config.\n if (looksLikeHtmlStartTag(configStr, remaining)) {\n return { config: defaultPermConfig(), content };\n }\n return { config: parseConfigString(configStr), content: remaining };\n}\n\n/** Index of the closing `>` of a `<…>` config, respecting quoted strings; -1 if none. */\nfunction findConfigEnd(text: string): number {\n let inQuote = false;\n for (let i = 1; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '\"') inQuote = !inQuote;\n if (ch === '>' && !inQuote) return i;\n }\n return -1;\n}\n\nfunction parseConfigString(str: string): PermConfig {\n if (!CONFIG_KEY_RE.test(str)) {\n // Single-separator form: the whole string is sep (and lastsep).\n return { minsize: null, maxsize: null, sep: str, lastsep: str };\n }\n return {\n minsize: intGroup(MINSIZE_RE.exec(str)),\n maxsize: intGroup(MAXSIZE_RE.exec(str)),\n sep: strGroup(SEP_RE.exec(str)) ?? ' ',\n lastsep: strGroup(LASTSEP_RE.exec(str)),\n };\n}\n\nfunction looksLikeHtmlStartTag(tagText: string, remaining: string): boolean {\n const trimmed = phpTrim(tagText);\n if (trimmed === '') return false;\n const m = HTML_TAG_RE.exec(trimmed);\n if (!m) return false;\n if (trimmed.endsWith('/')) return true; // self-closing\n const tagName = (m[1] ?? '').toLowerCase();\n return new RegExp(`</${escapeRegExp(tagName)}\\\\s*>`, 'iu').test(remaining);\n}\n\n/**\n * Turn raw split parts into elements, moving a trailing `<sep>` on part[i] to be\n * the per-element separator of the element from part[i+1]. Each element's text is\n * trimmed; empty elements are dropped (plugin `extract_per_element_separators`).\n */\nfunction extractPerElementSeparators(rawParts: string[]): PermOption[] {\n const options: PermOption[] = [];\n let pendingSep: string | null = null;\n\n rawParts.forEach((part, i) => {\n let text = part;\n let trailingSep: string | null = null;\n if (i < rawParts.length - 1) {\n const extracted = extractTrailingSep(part);\n if (extracted) {\n text = extracted.text;\n trailingSep = extracted.sep;\n }\n }\n const trimmed = phpTrim(text);\n if (trimmed !== '') {\n options.push({ nodes: parseSequence(trimmed), separator: pendingSep });\n }\n pendingSep = trailingSep;\n });\n\n return options;\n}\n\n/** Detect a trailing `< sep >` on a part (not an HTML tag). Returns {text, sep} or null. */\nfunction extractTrailingSep(part: string): { text: string; sep: string } | null {\n const trimmed = phpRtrim(part);\n const len = trimmed.length;\n if (len === 0 || trimmed.charAt(len - 1) !== '>') return null;\n\n let openPos = -1;\n for (let i = len - 2; i >= 0; i -= 1) {\n const ch = trimmed.charAt(i);\n if (ch === '<') {\n openPos = i;\n break;\n }\n if (ch === '>') return null; // nested/complex, bail\n }\n if (openPos === -1) return null;\n\n const inner = trimmed.slice(openPos + 1, len - 1);\n const innerTrimmed = phpTrim(inner);\n // HTML tag → not a separator: closing </x>, self-closing <x/>, or tag-with-attrs `<x …>`.\n if (innerTrimmed.startsWith('/') || innerTrimmed.endsWith('/') || PER_ELEM_HTML_RE.test(innerTrimmed)) {\n return null;\n }\n return { text: trimmed.slice(0, openPos), sep: inner };\n}\n\nfunction intGroup(m: RegExpExecArray | null): number | null {\n return m && m[1] !== undefined ? Number.parseInt(m[1], 10) : null;\n}\nfunction strGroup(m: RegExpExecArray | null): string | null {\n return m && m[1] !== undefined ? m[1] : null;\n}\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/gu, '\\\\$&');\n}\n\n// PHP trim strips only [ \\t\\n\\r\\0\\x0B] — NOT the full JS Unicode whitespace set —\n// so use these for byte-exact parity wherever the plugin trims (permutation\n// config / element text / separators, plural forms).\nconst PHP_LTRIM_RE = /^[ \\t\\n\\r\\0\\x0B]+/u;\nconst PHP_RTRIM_RE = /[ \\t\\n\\r\\0\\x0B]+$/u;\nfunction phpTrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '').replace(PHP_RTRIM_RE, '');\n}\nfunction phpLtrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '');\n}\nfunction phpRtrim(s: string): string {\n return s.replace(PHP_RTRIM_RE, '');\n}\n\n/**\n * Index of the `close` that matches the `open` at `openPos`, tracking depth of\n * this bracket pair only. Returns -1 if unmatched.\n */\nfunction findMatchingClose(text: string, openPos: number, open: string, close: string): number {\n let depth = 0;\n for (let i = openPos; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === open) {\n depth += 1;\n } else if (ch === close) {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n return -1;\n}\n\n/**\n * Split on top-level `|` — mirrors the plugin's `split_top_level`: brace and\n * bracket depths tracked INDEPENDENTLY and decremented UNCONDITIONALLY (may go\n * negative), split only when BOTH are exactly 0. So `a]|b` stays one option.\n */\nexport function splitTopLevel(inner: string): string[] {\n const parts: string[] = [];\n let brace = 0;\n let bracket = 0;\n let cur = '';\n for (const ch of inner) {\n if (ch === '{') brace += 1;\n else if (ch === '}') brace -= 1;\n else if (ch === '[') bracket += 1;\n else if (ch === ']') bracket -= 1;\n\n if (ch === '|' && brace === 0 && bracket === 0) {\n parts.push(cur);\n cur = '';\n } else {\n cur += ch;\n }\n }\n parts.push(cur);\n return parts;\n}\n\n/**\n * Index of the first top-level `|` in a conditional body, or -1. Uses a single\n * depth counter CLAMPED at 0 (matching the plugin's `parse_conditional` body\n * split, which differs from `split_top_level`'s signed dual counters).\n */\nfunction firstTopLevelPipe(body: string, from = 0, to = body.length): number {\n let depth = 0;\n for (let j = from; j < to; j += 1) {\n const ch = body.charAt(j);\n if (ch === '{' || ch === '[') {\n depth += 1;\n } else if (ch === '}' || ch === ']') {\n if (depth > 0) depth -= 1;\n } else if (ch === '|' && depth === 0) {\n return j;\n }\n }\n return -1;\n}\n","/**\n * Locale plural rules — ported from the plugin's `Plurals` (parity item §3.1).\n * Shared by the validator (arity check, PR-12) and the renderer (bucket pick, M2).\n */\n\nconst PLURAL_PREFIX = '{plural ';\n\nexport interface PluralBlock {\n readonly start: number;\n /** Exclusive end offset — one past the block's closing `}` (for diagnostics). */\n readonly end: number;\n readonly countSlot: string;\n readonly formsRaw: string;\n}\n\n/**\n * Raw brace-aware scan for `{plural …}` blocks — ported from the plugin's\n * `find_plural_blocks`. Used by the validator (and available to the renderer).\n * Scans the whole text, so it finds plurals nested inside `[…]` permutations too\n * (the AST leaves a permutation body unparsed until PR-11b). A block without a\n * `:` is not a plural (left to the enumeration path).\n */\nexport function findPluralBlocks(text: string): PluralBlock[] {\n const blocks: PluralBlock[] = [];\n let i = 0;\n while (i < text.length) {\n const start = text.indexOf(PLURAL_PREFIX, i);\n if (start === -1) break;\n\n let depth = 1;\n let j = start + PLURAL_PREFIX.length;\n while (j < text.length) {\n const ch = text.charAt(j);\n if (ch === '{') depth += 1;\n else if (ch === '}') {\n depth -= 1;\n if (depth === 0) break;\n }\n j += 1;\n }\n if (depth !== 0) {\n i = start + PLURAL_PREFIX.length; // unmatched opening — skip past prefix\n continue;\n }\n\n const inner = text.slice(start + PLURAL_PREFIX.length, j);\n const colon = inner.indexOf(':');\n if (colon === -1) {\n i = j + 1; // no colon ⇒ not a plural\n continue;\n }\n blocks.push({ start, end: j + 1, countSlot: inner.slice(0, colon), formsRaw: inner.slice(colon + 1) });\n i = j + 1;\n }\n return blocks;\n}\n\n/** Normalise a locale to its base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. */\nexport function normalizeBaseLang(locale: string): string {\n const first = locale.toLowerCase().split(/[-_]/, 1)[0];\n return first ?? '';\n}\n\n/**\n * Expected number of plural forms: 3 for the Slavic one/few/other family\n * (East Slavic ru/uk/be + BCS sr/hr/bs), else 2 (EN-style).\n *\n * BCS shares the East-Slavic integer rule exactly, so it reuses that bucket; CLDR\n * names the third slot \"other\" rather than \"many\", positionally the same.\n */\nexport function pluralArity(baseLang: string): number {\n switch (baseLang) {\n case 'ru':\n case 'uk':\n case 'be':\n case 'sr':\n case 'hr':\n case 'bs':\n return 3;\n default:\n return 2;\n }\n}\n\n/**\n * How many forms `render` resolves against when the host supplies no locale.\n *\n * Derived from the table rather than written as `2`, so the validator's\n * `plural.locale-missing` warning cannot come to disagree with what render actually\n * does — the disagreement between those two is the whole of issue #65.\n */\nexport const DEFAULT_PLURAL_ARITY = pluralArity('');\n\n/**\n * Pick the plural form for a count by the locale's grammar.\n * - Slavic 3-form (ru/uk/be + sr/hr/bs): one (1,21,31… not 11), few (2-4,22-24…\n * not 12-14), many (rest, incl. 0).\n * - EN-style: one (n=1), many (rest). Negative counts use abs().\n *\n * Counts are integers here (§3.1 erases a non-numeric slot), so the BCS/East-Slavic\n * split on fractions — CLDR gives BCS a fraction-digit rule — cannot be reached.\n */\nexport function pluralFor(baseLang: string, n: number, forms: readonly string[]): string {\n const abs = Math.abs(n);\n const mod10 = abs % 10;\n const mod100 = abs % 100;\n\n switch (baseLang) {\n case 'ru':\n case 'uk':\n case 'be':\n case 'sr':\n case 'hr':\n case 'bs':\n if (mod10 === 1 && mod100 !== 11) return forms[0] ?? '';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return forms[1] ?? '';\n return forms[2] ?? '';\n default:\n return (abs === 1 ? forms[0] : forms[1]) ?? '';\n }\n}\n","/**\n * Static validator — ported from the plugin's `Validator` (parity gate §3.1).\n * Produces {@link Diagnostic}[] with the canonical, stable codes documented in\n * `@spintax/conformance`'s README. \"Valid\" ⇔ no `severity:'error'`.\n *\n * Bracket balance is a raw char scan (the lenient AST doesn't represent\n * imbalance). Plural and #include checks walk the AST. Positions are best-effort\n * — not parity-gated (§3.1): only `code` (+ severity) is.\n *\n * Circular `#include` is NOT a verdict here — it is a render-time maxDepth guard\n * (the plugin's validator never resolves includes).\n */\nimport type { Diagnostic, ValidateOptions } from '../index';\nimport { DIRECTIVE_RE, extractDirectives, stripComments } from './parser';\nimport { DEFAULT_PLURAL_ARITY, findPluralBlocks, normalizeBaseLang, pluralArity } from './plurals';\n\nconst KNOWN_CONFIG_KEYS = new Set(['minsize', 'maxsize', 'sep', 'lastsep']);\n// The gap class is spelled out because no dialect's `\\s` is this set — PHP's under /u is\n// UCP-Unicode (measured, #55), not the ASCII this comment once claimed. Corpus-pinned.\nconst INCLUDE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\n\n/**\n * Pure raw-text validation — exactly like the plugin's `Validator` (which does\n * NOT build an AST). Scanning the raw text (not the lenient AST) is what lets\n * bracket imbalance and constructs nested inside `[…]` permutations be seen.\n */\nexport function validateTemplate(src: string, opts: ValidateOptions = {}): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const text = stripComments(src);\n const idx = buildLineIndex(text);\n\n checkBrackets(text, diagnostics);\n checkDirectives(text, diagnostics);\n checkPermutationConfigs(text, idx, diagnostics);\n checkPlurals(text, idx, opts.locale, opts.knownVariables, diagnostics);\n checkVariableReferences(text, idx, opts.knownVariables, diagnostics);\n if (opts.knownIncludes && opts.knownIncludes.length > 0) {\n checkIncludeTargets(text, idx, opts.knownIncludes, diagnostics);\n }\n\n return diagnostics;\n}\n\n/** Position (+ optional end and structured data) attached to a Diagnostic. */\ninterface Pos { line: number; column: number; endLine?: number; endColumn?: number; data?: Record<string, unknown> }\n\nfunction err(code: string, message: string, pos: Pos): Diagnostic {\n return { severity: 'error', code, message, ...pos };\n}\nfunction warn(code: string, message: string, pos: Pos): Diagnostic {\n return { severity: 'warning', code, message, ...pos };\n}\n\n/**\n * Line-start offsets of `text`, built once per validate() call. Every diagnostic\n * position is then a binary search instead of a scan from offset 0 — the scan made\n * a diagnostic-heavy document quadratic (each of N diagnostics re-walked the text).\n */\ninterface LineIndex { starts: number[]; length: number }\n\nfunction buildLineIndex(text: string): LineIndex {\n const starts = [0];\n for (let i = 0; i < text.length; i += 1) {\n if (text.charCodeAt(i) === 10) starts.push(i + 1);\n }\n return { starts, length: text.length };\n}\n\n/** 1-based (line, column) of a character offset — same clamp and column model as the old scan. */\nfunction offsetToLineCol(idx: LineIndex, offset: number): { line: number; column: number } {\n const end = Math.min(Math.max(offset, 0), idx.length);\n let lo = 0;\n let hi = idx.starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((idx.starts[mid] ?? 0) <= end) lo = mid;\n else hi = mid - 1;\n }\n return { line: lo + 1, column: end - (idx.starts[lo] ?? 0) + 1 };\n}\n\n/** A full [offset, offset+length) span as start + end positions. */\nfunction span(idx: LineIndex, offset: number, length: number): Pos {\n const s = offsetToLineCol(idx, offset);\n const e = offsetToLineCol(idx, offset + length);\n return { line: s.line, column: s.column, endLine: e.line, endColumn: e.column };\n}\n\n/** Balanced `{}`/`[]` with proper nesting (raw char scan, real line/col). */\nfunction checkBrackets(text: string, out: Diagnostic[]): void {\n const close: Record<string, string> = { '{': '}', '[': ']' };\n const stack: Array<{ char: string; expect: string; line: number; column: number }> = [];\n let line = 1;\n let column = 1;\n\n for (const ch of text) {\n if (ch === '\\n') {\n line += 1;\n column = 1;\n continue;\n }\n if (ch === '{' || ch === '[') {\n stack.push({ char: ch, expect: close[ch]!, line, column });\n } else if (ch === '}' || ch === ']') {\n const top = stack.pop();\n if (top === undefined) {\n out.push(err('bracket.unexpected-closing', `Unexpected closing '${ch}'.`, { line, column, endLine: line, endColumn: column + 1, data: { bracket: ch } }));\n } else if (top.expect !== ch) {\n out.push(err('bracket.mismatched', `'${top.char}' closed by '${ch}'.`, { line, column, endLine: line, endColumn: column + 1, data: { open: top.char, close: ch } }));\n }\n }\n column += 1;\n }\n\n for (const unclosed of stack) {\n out.push(err('bracket.unclosed', `Unclosed '${unclosed.char}'.`, { line: unclosed.line, column: unclosed.column, endLine: unclosed.line, endColumn: unclosed.column + 1, data: { bracket: unclosed.char } }));\n }\n}\n\n/**\n * Directive lines must match the shared grammar, each name may be defined once, and `#include`\n * may not appear in a `#def` value.\n *\n * The shape test uses `DIRECTIVE_RE` rather than a private copy. The old copy differed from the\n * parser's in two ways — `\\s` for whitespace and `(.+)` for the value — and the second was a live\n * defect: an empty value is legal and the parser accepts it, but this reported `#set %x% =` as\n * malformed unless a trailing space happened to be present.\n */\nfunction checkDirectives(text: string, out: Diagnostic[]): void {\n const lines = text.split('\\n');\n lines.forEach((lineText, idx) => {\n const trimmed = lineText.replace(/^[ \\t]+/, '');\n const kind = (['#set', '#def'] as const).find(\n (candidate) => trimmed.startsWith(`${candidate} `) || trimmed.startsWith(`${candidate}\\t`),\n );\n if (!kind) return;\n\n DIRECTIVE_RE.lastIndex = 0;\n if (!DIRECTIVE_RE.test(trimmed)) {\n const column = lineText.length - trimmed.length + 1; // first non-space char\n const line = idx + 1;\n const code = kind === '#def' ? 'def.malformed' : 'set.malformed';\n out.push(err(code, `Malformed ${kind}. Expected: ${kind} %name% = value`, { line, column, endLine: line, endColumn: lineText.length + 1 }));\n }\n });\n\n const { occurrences } = extractDirectives(text);\n const seen = new Map<string, number>();\n\n for (const occurrence of occurrences) {\n // A name defined twice is an error whichever directives are involved. The two maps flatten a\n // collision to last-wins before anyone can see it, which is why `occurrences` exists — and a\n // `#set`/`#def` pair sharing a name would be worse still, the two carrying opposite semantics.\n const first = seen.get(occurrence.name);\n if (first !== undefined) {\n out.push(err(\n 'definition.duplicate-name',\n `Variable '${occurrence.name}' is defined more than once (first on line ${first}). A name belongs to one directive, once.`,\n { line: occurrence.line, column: 1 },\n ));\n } else {\n seen.set(occurrence.name, occurrence.line);\n }\n\n // Includes resolve after a definition is frozen, so one cannot be rolled into a value — it\n // would survive as literal text. Inside a `#set` it is fine: the macro is substituted verbatim\n // and its `#include` reaches the include stage in the body.\n if (occurrence.kind === 'def' && /#include\\b/u.test(occurrence.value)) {\n out.push(err(\n 'def.include-in-value',\n `#include cannot appear in a #def value ('${occurrence.name}'): includes resolve after the value is frozen. Use #set, or put the #include in the body.`,\n { line: occurrence.line, column: 1 },\n ));\n }\n }\n}\n\n/** `[<config>]` prefixes: known keys only, minsize/maxsize must be digit runs. */\nfunction checkPermutationConfigs(text: string, idx: LineIndex, out: Diagnostic[]): void {\n for (const m of text.matchAll(/\\[<([^>]*?)>/gu)) {\n const configStr = m[1] ?? '';\n if (!/\\w+\\s*=/.test(configStr)) continue; // not a key=value config\n const configBase = (m.index ?? 0) + 2; // offset of configStr in text (past \"[<\")\n\n for (const km of configStr.matchAll(/(\\w+)\\s*=/gu)) {\n const key = (km[1] ?? '').toLowerCase();\n if (!KNOWN_CONFIG_KEYS.has(key)) {\n out.push(err('permutation.unknown-key', `Unknown permutation config key: '${km[1]}'.`,\n { ...span(idx, configBase + (km.index ?? 0), (km[1] ?? '').length), data: { key: km[1] } }));\n }\n }\n const min = /minsize\\s*=\\s*([^;>\\s]+)/i.exec(configStr);\n if (min && !/^\\d+$/.test(min[1] ?? '')) {\n out.push(err('permutation.minsize-not-integer', `minsize must be a positive integer, got '${min[1]}'.`,\n { ...span(idx, configBase + min.index, min[0].length), data: { value: min[1] } }));\n }\n const max = /maxsize\\s*=\\s*([^;>\\s]+)/i.exec(configStr);\n if (max && !/^\\d+$/.test(max[1] ?? '')) {\n out.push(err('permutation.maxsize-not-integer', `maxsize must be a positive integer, got '${max[1]}'.`,\n { ...span(idx, configBase + max.index, max[0].length), data: { value: max[1] } }));\n }\n }\n}\n\n/** `{plural …}`: no nested brackets in forms; form count matches locale arity. */\nfunction checkPlurals(\n text: string,\n idx: LineIndex,\n locale: string | undefined,\n knownVariables: readonly string[] | undefined,\n out: Diagnostic[],\n): void {\n // Guard on the NORMALIZED base (like the plugin): a non-empty locale that\n // normalizes to '' (e.g. \"_en\") skips the arity check.\n const base = locale && locale !== '' ? normalizeBaseLang(locale) : '';\n const arity = base !== '' ? pluralArity(base) : 0;\n\n const tainted = macroTaintedNames(text);\n const { setDefs: macros, defDefs: defs } = extractDirectives(text);\n // Names the host says it will supply: runtime context outranks a definition of the\n // same name, so one of these makes a form count unknowable however the template\n // defines it.\n const hostNames = new Set((knownVariables ?? []).map((n) => n.toLowerCase()));\n\n for (const block of findPluralBlocks(text)) {\n const at = span(idx, block.start, block.end - block.start);\n\n // A macro in the count slot: the count is still unresolved spintax when the plural is decided,\n // so the block resolves to nothing. `#def` is the fix — it freezes to a literal before the\n // body is walked — which is why this points at the directive, not at the plural block.\n for (const m of block.countSlot.matchAll(/%(\\w+)%/gu)) {\n const name = (m[1] ?? '').toLowerCase();\n if (!tainted.has(name)) continue;\n out.push(err(\n 'plural.count-macro',\n `{plural ...}: the count '${m[1]}' is a #set macro, so it is still unresolved spintax when the plural is decided and the block renders empty. Define it with #def instead.`,\n at,\n ));\n }\n\n if (/[{}[\\]]/.test(block.formsRaw)) {\n out.push(err('plural.nested-brackets', '{plural ...}: forms must not contain nested spintax brackets. Extract via #def first — a #set is substituted verbatim and would put the brackets straight back.', at));\n continue;\n }\n\n // The form list AS THE RENDERER WILL SEE IT. `render` expands variables before it\n // counts forms (internal/render.ts), so counting the raw pipes here judged a\n // different string than the one that gets rendered — a `#def` holding `few|many`\n // made a correct 3-form Russian template report plural.arity, and a 1-pipe list\n // that expands to 2 forms reported nothing (issue #66, found adopting #65 in the\n // Pascal port).\n const expanded = expandFormsForCounting(block.formsRaw, defs, macros, hostNames);\n\n // A `#set` whose value carries spintax lands in the form list VERBATIM and is still\n // unresolved when the plural is decided — the same fact plural.count-macro states\n // for the count slot, and exactly what this message already describes.\n if (expanded.directMacroSpintax) {\n out.push(err('plural.nested-brackets', '{plural ...}: forms must not contain nested spintax brackets. Extract via #def first — a #set is substituted verbatim and would put the brackets straight back.', at));\n continue;\n }\n\n // A reference the template does not define — a host variable, or a chain past the\n // budget — has no static form count. Judging it would repeat the mistake #65 fixed:\n // filing a verdict on a fact the caller never claimed.\n if (expanded.unresolved) continue;\n\n const count = expanded.forms;\n if (arity > 0) {\n if (count !== arity) {\n out.push(err('plural.arity', `{plural ...}: expected ${arity} forms, got ${count}.`,\n { ...at, data: { expected: arity, got: count } }));\n }\n } else if (count !== DEFAULT_PLURAL_ARITY) {\n // No locale ⇒ no arity VERDICT: the template may well be correct for the locale it\n // will be rendered with, and calling it invalid here would fail a good template for\n // a fact the caller never claimed. But `render` has no such luxury — it defaults to\n // 2 forms — so silence sends a 3-form block straight to the fullwidth-brace\n // fallback in finished text (issue #65: a pipeline shipped {plural …} to live\n // pages because validate stayed quiet). A warning says the one true thing: this\n // resolves only if a matching locale arrives at render time.\n // Two ways to arrive with no arity: nothing was passed, or what was passed does\n // not normalize to a language the engine knows (`_en`). Saying \"no locale was\n // supplied\" to a caller who supplied one sends them looking for the wrong bug.\n const unusable = locale !== undefined && locale !== '';\n out.push(warn(\n 'plural.locale-missing',\n unusable\n ? `{plural ...}: ${count} forms, and the locale '${locale}' does not normalize to a ` +\n `language the engine knows, so render falls back to ${DEFAULT_PLURAL_ARITY} forms and ` +\n `leaves this block unresolved — pass a base tag such as 'en' or 'ru'.`\n : `{plural ...}: ${count} forms, but no locale was supplied. render defaults to ` +\n `${DEFAULT_PLURAL_ARITY} forms and leaves this block unresolved — pass the locale you will render with.`,\n {\n ...at,\n data: {\n got: count,\n defaultArity: DEFAULT_PLURAL_ARITY,\n ...(unusable ? { locale } : {}),\n },\n },\n ));\n }\n }\n}\n\n/**\n * Spintax still unresolved when plural agreement runs: `[`, or `{` that does not open a\n * conditional.\n *\n * Stage order decides this, not bracket type. Conditionals resolve BEFORE plurals, so a `{?…}` in\n * a count value is already a literal when the count is read — flagging it would be a false\n * positive on a template that renders correctly. Enumerations and permutations resolve AFTER\n * plurals and are the real hazard. A nested `{plural …}` is NOT exempt either: it resolves in the\n * same pass as the outer block, not before it.\n *\n * Only `#set` names can be tainted; a `#def` is frozen to literal text before the walk begins.\n * Taint propagates through `#set` → `#set` references to a fixpoint, because the chain can be\n * arbitrarily long and carry no bracket at its final link.\n */\nconst UNRESOLVED_AT_PLURAL_TIME = /\\[|\\{(?!\\?)/u;\n\n/**\n * Any bracket at all — all four, and conditionals too.\n *\n * Two reasons, and both were review findings. Conditionals: one resolves before plurals,\n * so it is not \"unresolved at plural time\", but its branches can differ in top-level\n * pipes (`{?flag?a|b|c}` freezes as `a` or as `b|c`), and counting is about invariance\n * rather than stage order. Closing brackets: a `#set %x% = ]` balances against a `[`\n * elsewhere in the template, so the bracket checker stays quiet, and every renderer's\n * plural guard is `[{}[\\]]` — it rejects the form list on a stray closer exactly as on an\n * opener.\n *\n * Construct-free is a SUFFICIENT condition for the count to be invariant, deliberately\n * not a necessary one: `{a|b}` really does always freeze to one form. It is the property\n * this validator elects to prove, because the cases where a construct is invariant cannot\n * be told from the cases where it is not without evaluating it.\n */\nconst ANY_BRACKET = /[[\\]{}]/u;\n\n/**\n * Passes, not occurrences — each one substitutes EVERY reference, as the renderer's\n * expansion does. Counting occurrences instead made a form list with 51 references\n * exhaust the budget and go unjudged.\n *\n * It is deliberately NOT claimed to match a renderer's own limit (they differ: 50 here\n * and in Python, 51 in both PHP engines). It only has to terminate — a chain deeper than\n * this is suppressed rather than judged, which is the safe direction.\n */\nconst FORM_EXPANSION_PASSES = 51;\n\n/**\n * How many forms the plural stage will actually receive — or an admission that it is not\n * knowable.\n *\n * Why this exists: `render` expands `%variables%` and only THEN splits the form list,\n * while this validator used to split the raw source, so any reference inside a form list\n * was judged on the wrong number in both directions (issue #66).\n *\n * The rule is deliberately narrow, and the narrowness IS the correction. A first version\n * tried to predict the roll — counting pipes at bracket depth 0, on the theory that a\n * construct always collapses to one form. It does not:\n *\n * #set %flag% =\n * #def %x% = {?flag?a|b|c} ← the false branch freezes as `b|c`: TWO forms\n * {plural 1: one|%x%} ← renders fine under ru; the guess said arity error\n *\n * So a value is counted only when its form count is the same WHATEVER the roll does —\n * that is, when it carries no spintax construct at all. Anything else, any name the host\n * may supply at render time, and any reference the template does not define, suppresses\n * the count-based verdicts. Silence on an unknowable input is the #65 principle; a\n * confident wrong answer is what it replaced.\n *\n * `directMacroSpintax` is the one prediction that survives, because it is not one: a\n * `#set` named DIRECTLY in the form slot is substituted verbatim and is still spintax\n * when the plural is decided — measured, and exactly what the nested-brackets message has\n * always described. Reached through a `#def` it is rolled first, so it is not reported.\n */\nfunction expandFormsForCounting(\n formsRaw: string,\n defs: Record<string, string>,\n macros: Record<string, string>,\n hostNames: ReadonlySet<string>,\n): { forms: number; unresolved: boolean; directMacroSpintax: boolean } {\n const unknown = (\n directMacroSpintax = false,\n ): { forms: number; unresolved: boolean; directMacroSpintax: boolean } => ({\n forms: 0,\n unresolved: true,\n directMacroSpintax,\n });\n\n // Which brackets reach the form slot VERBATIM: follow the `#set` chain out of the raw\n // slot, stopping at anything that changes the answer. \"Direct\" is a property of the\n // PATH, not of one hop — `#set %a% = %b%` with `#set %b% = {a|b}` never crosses a #def,\n // so the macro text arrives whole and the block renders as the fallback.\n const seenMacro = new Set<string>();\n const walkMacros = (source: string): 'brackets' | 'opaque' | 'clean' => {\n for (const m of source.matchAll(/%(\\w+)%/gu)) {\n const name = (m[1] ?? '').toLowerCase();\n // A #def rolls it, and a host value replaces it — either way the macro text does\n // not arrive verbatim, so this path says nothing.\n if (defs[name] !== undefined || hostNames.has(name)) continue;\n const macro = macros[name];\n if (macro === undefined || seenMacro.has(name)) continue;\n seenMacro.add(name);\n // A conditional is where the engines themselves disagree: both PHP renderers\n // resolve one that expansion introduces INSIDE a form list, TS and Python do not.\n // Until that is settled (filed separately), decline to judge rather than pick a\n // side — the retreat this whole fix is built on.\n if (/\\{\\?/u.test(macro)) return 'opaque';\n if (ANY_BRACKET.test(macro)) return 'brackets';\n const deeper = walkMacros(macro);\n if (deeper !== 'clean') return deeper;\n }\n return 'clean';\n };\n const verbatim = walkMacros(formsRaw);\n if (verbatim === 'brackets') return unknown(true);\n if (verbatim === 'opaque') return unknown();\n\n let text = formsRaw;\n for (let pass = 0; pass < FORM_EXPANSION_PASSES; pass++) {\n let sawReference = false;\n let bailed = false;\n\n // EVERY reference per pass, as the renderer's expansion does. Replacing one at a time\n // spent the budget on a list that merely repeats a name 51 times.\n text = text.replace(/%(\\w+)%/gu, (whole: string, raw: string): string => {\n sawReference = true;\n const name = raw.toLowerCase();\n // Runtime context outranks a definition of the same name, so a host-declared name\n // makes the count unknowable even where the template defines one locally.\n if (hostNames.has(name)) {\n bailed = true;\n return whole;\n }\n const value = defs[name] ?? macros[name];\n if (value === undefined) {\n bailed = true;\n return whole;\n }\n // A construct in the value: what it rolls to may or may not carry a top-level pipe,\n // so no single count is true of every render.\n if (ANY_BRACKET.test(value)) {\n bailed = true;\n return whole;\n }\n return value;\n });\n\n if (bailed) return unknown();\n if (!sawReference) {\n // No construct can be left here, so the plain split is what the renderer does too.\n return { forms: text.split('|').length, unresolved: false, directMacroSpintax: false };\n }\n }\n // A cycle, or a chain deeper than this bothers to follow.\n return unknown();\n}\n\nfunction macroTaintedNames(text: string): Set<string> {\n const macros = extractDirectives(text).setDefs;\n const tainted = new Set<string>();\n const queue: string[] = [];\n\n for (const [name, value] of Object.entries(macros)) {\n if (UNRESOLVED_AT_PLURAL_TIME.test(value)) {\n tainted.add(name);\n queue.push(name);\n }\n }\n\n // Same closure the old fixpoint sweep computed, via reverse edges — the sweep\n // re-parsed every value once per newly tainted name, O(n²) on a macro chain.\n const dependents = new Map<string, string[]>();\n for (const [name, value] of Object.entries(macros)) {\n for (const m of value.matchAll(/%(\\w+)%/gu)) {\n const ref = (m[1] ?? '').toLowerCase();\n const list = dependents.get(ref);\n if (list === undefined) dependents.set(ref, [name]);\n else list.push(name);\n }\n }\n while (queue.length > 0) {\n const source = queue.pop()!;\n for (const name of dependents.get(source) ?? []) {\n if (!tainted.has(name)) {\n tainted.add(name);\n queue.push(name);\n }\n }\n }\n\n return tainted;\n}\n\n/** Self-reference + circular definitions (errors) and undefined `%var%`/conditional refs (warnings). */\nfunction checkVariableReferences(text: string, idx: LineIndex, known: readonly string[] | undefined, out: Diagnostic[]): void {\n const knownSet = new Set((known ?? []).map((n) => n.toLowerCase()));\n // `[ \\t]` (single-line), uniform with the parser's extract_set_directives and\n // extract.ts — so a malformed cross-line `#set` isn't treated as a definition.\n const defs = new Map<string, string>();\n const defPos = new Map<string, Pos>(); // %name% token span in its #set line\n for (const m of text.matchAll(/^[ \\t]*#(?:set|def)[ \\t]+%(\\w+)%[ \\t]*=[ \\t]*(.*?)$/gmu)) {\n const name = (m[1] ?? '').toLowerCase();\n defs.set(name, m[2] ?? '');\n const nameOffset = (m.index ?? 0) + m[0].indexOf('%');\n defPos.set(name, span(idx, nameOffset, name.length + 2));\n }\n\n const somewhere: Pos = { line: 1, column: 1 };\n for (const [name, value] of defs) {\n if (value.toLowerCase().includes(`%${name}%`)) {\n out.push(err('variable.self-reference', `Variable '${name}' references itself.`, defPos.get(name) ?? somewhere));\n }\n }\n\n // Each value's references, parsed once — the walk used to re-run the regex at\n // every visit of every root.\n const refsOf = new Map<string, string[]>();\n for (const [name, value] of defs) {\n const refs: string[] = [];\n for (const m of value.matchAll(/%(\\w+)%/gu)) refs.push((m[1] ?? '').toLowerCase());\n refsOf.set(name, refs);\n }\n\n const reachesCycle = namesThatReachACycle(defs, refsOf);\n for (const name of defs.keys()) {\n detectCycle(name, defs, refsOf, reachesCycle, defPos.get(name) ?? somewhere, out);\n }\n\n // Blank #set lines to same-length whitespace so ref offsets still map to `text`\n // (a bare removal would shift every later column).\n const body = text.replace(/^[ \\t]*#(?:set|def)[ \\t]+%\\w+%[ \\t]*=[ \\t]*.*?$/gmu, (m) => m.replace(/[^\\n]/g, ' '));\n const seen = new Set<string>();\n const undefinedAt = (name: string, offset: number, length: number): void => {\n const key = name.toLowerCase();\n if (defs.has(key) || knownSet.has(key) || seen.has(key)) return;\n seen.add(key);\n out.push(warn('variable.undefined', `Variable '${name}' is not defined — may be a runtime variable.`,\n { ...span(idx, offset, length), data: { name } }));\n };\n for (const m of body.matchAll(/%(\\w+)%/gu)) undefinedAt(m[1] ?? '', m.index ?? 0, m[0].length);\n for (const m of body.matchAll(/\\{\\?!?([A-Za-z_]\\w*)\\?/gu)) {\n undefinedAt(m[1] ?? '', (m.index ?? 0) + m[0].indexOf(m[1] ?? ''), (m[1] ?? '').length);\n }\n}\n\n/**\n * Names from which a cycle of length ≥ 2 is reachable, over the graph name → defined\n * refs with self-edges excluded — exactly the edges the reporting walk can traverse\n * (it skips `ref === current`, and a pure self-loop is `variable.self-reference`).\n *\n * This is the prune that makes the walk affordable, and it is output-neutral by\n * construction: a report fires only when the walk meets a name already on its path,\n * which is a cycle the met name lies on — so a subtree in which no name reaches any\n * cycle cannot emit, and skipping it changes nothing. Without the prune every root\n * re-walked its whole subgraph (a 400-definition chain took hundreds of milliseconds,\n * and a converging diamond re-explored shared subtrees exponentially — a one-kilobyte\n * template validate() never returned from). One iterative colour walk, computed once.\n */\nfunction namesThatReachACycle(defs: Map<string, string>, refsOf: Map<string, string[]>): Set<string> {\n const GREY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n const reaches = new Set<string>();\n\n interface Frame { name: string; refs: string[]; i: number }\n for (const root of defs.keys()) {\n if (color.has(root)) continue;\n const stack: Frame[] = [{ name: root, refs: refsOf.get(root) ?? [], i: 0 }];\n color.set(root, GREY);\n while (stack.length > 0) {\n const top = stack[stack.length - 1]!;\n if (top.i < top.refs.length) {\n const ref = top.refs[top.i]!;\n top.i += 1;\n if (ref === top.name || !defs.has(ref)) continue;\n const c = color.get(ref);\n if (c === GREY) reaches.add(top.name); // back edge — top sits on a cycle\n else if (c === BLACK) { if (reaches.has(ref)) reaches.add(top.name); }\n else {\n stack.push({ name: ref, refs: refsOf.get(ref) ?? [], i: 0 });\n color.set(ref, GREY);\n }\n } else {\n stack.pop();\n color.set(top.name, BLACK);\n if (stack.length > 0 && reaches.has(top.name)) reaches.add(stack[stack.length - 1]!.name);\n }\n }\n }\n return reaches;\n}\n\n/**\n * The reporting walk, exactly the recursive one it replaces: depth-first over a\n * value's references in order, one report per frame that meets a name already on\n * the path (the frame then abandons its remaining references; siblings continue\n * from the parent). Iterative so a definition chain as deep as the document cannot\n * overflow the call stack; the shared path array is pushed/popped instead of copied\n * per step, and membership is a Set — the array `includes` plus the per-step copy\n * made one 1600-definition cycle cost tens of seconds.\n */\nfunction detectCycle(\n root: string,\n defs: Map<string, string>,\n refsOf: Map<string, string[]>,\n reachesCycle: Set<string>,\n rootPos: Pos,\n out: Diagnostic[],\n): void {\n if (!reachesCycle.has(root)) return; // the root frame could only report ref === root, which it skips\n\n interface Frame { name: string; refs: string[]; i: number }\n const path: string[] = [root];\n const onPath = new Set<string>([root]);\n const stack: Frame[] = [{ name: root, refs: refsOf.get(root) ?? [], i: 0 }];\n\n const leave = (frame: Frame): void => {\n stack.pop();\n onPath.delete(frame.name);\n path.pop();\n };\n\n while (stack.length > 0) {\n const top = stack[stack.length - 1]!;\n if (top.i >= top.refs.length) {\n leave(top);\n continue;\n }\n const ref = top.refs[top.i]!;\n top.i += 1;\n if (ref === top.name) continue; // self-reference already reported\n if (onPath.has(ref)) {\n out.push(err('variable.circular-reference', `Circular variable reference: ${[...path, ref].join(' → ')}.`, rootPos));\n leave(top); // the recursive walk returned from the whole frame here\n continue;\n }\n if (defs.has(ref) && reachesCycle.has(ref)) {\n stack.push({ name: ref, refs: refsOf.get(ref) ?? [], i: 0 });\n onPath.add(ref);\n path.push(ref);\n }\n }\n}\n\n/** Unknown `#include` targets — only when a slug list is supplied. Raw `/m` scan. */\nfunction checkIncludeTargets(text: string, idx: LineIndex, known: readonly string[], out: Diagnostic[]): void {\n const set = new Set(known);\n INCLUDE_RE.lastIndex = 0;\n for (const m of text.matchAll(INCLUDE_RE)) {\n const ref = m[1] ?? '';\n if (!set.has(ref)) {\n const refOffset = (m.index ?? 0) + m[0].indexOf('\"') + 1; // inside the quotes\n out.push(err('include.unknown-target', `#include target '${ref}' does not match any known template.`,\n { ...span(idx, refOffset, ref.length), data: { target: ref } }));\n }\n }\n}\n","/**\n * Variable / #set / #include enumeration for `extract()` (spec §9.2).\n *\n * Raw-text scan (like the validator) rather than an AST walk, so it is complete:\n * it catches `%var%` inside a `{plural <count>: …}` count slot and inside a\n * `[…]` permutation body — both of which the AST leaves as raw strings. The\n * `#set` definition target (`#set %name% =` LHS) is a *definition*, not a\n * reference, so it is stripped before collecting `refs`.\n *\n * Variable names (`refs`, `sets`) are LOWER-CASED — the engine's variable\n * identity is case-insensitive, so cross-referencing sets against refs (the\n * two-phase-include / host-provisioning use) works. `includes` slugs are left\n * as authored (host-resolved, not case-folded). Arrays are de-duplicated;\n * order is insertion (the corpus compares order-normalized).\n *\n * NOTE (best-effort on malformed input): the conditional-name scan keys off the\n * `{?NAME?` prefix without requiring the brace to close, so an unclosed\n * `{?foo?…` yields a phantom `foo` ref. Acceptable for an extraction API.\n */\nimport { stripComments } from './parser';\n\nexport interface ExtractResult {\n refs: string[];\n sets: string[];\n defs: string[];\n includes: string[];\n}\n\n// Directives use [ \\t] (single-line), matching the parser's DIRECTIVE_RE — NOT \\s, which would\n// let a malformed multi-line directive be read as a definition.\nconst SET_DEF_RE = /^[ \\t]*#set[ \\t]+%(\\w+)%[ \\t]*=/gmu;\nconst DEF_DEF_RE = /^[ \\t]*#def[ \\t]+%(\\w+)%[ \\t]*=/gmu;\nconst DEFINITION_LHS_RE = /^[ \\t]*#(?:set|def)[ \\t]+%\\w+%[ \\t]*=/gmu;\n// The gap class is spelled out because no dialect's `\\s` is this set — PHP's under /u is\n// UCP-Unicode (measured, #55), not the ASCII this comment once claimed. Corpus-pinned.\nconst INCLUDE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\nconst VARIABLE_RE = /%(\\w+)%/gu;\nconst CONDITIONAL_REF_RE = /\\{\\?!?([A-Za-z_]\\w*)\\?/gu;\n\nexport function extractFromSource(src: string): ExtractResult {\n const text = stripComments(src);\n\n const sets = collect(text, SET_DEF_RE, true);\n const defs = collect(text, DEF_DEF_RE, true);\n const includes = collect(text, INCLUDE_RE, false);\n\n // Drop each `#set`/`#def … =` LHS (keep the value) so a definition target is not a ref. Missing\n // the `#def` half here would report every definition name as a phantom reference.\n const body = text.replace(DEFINITION_LHS_RE, '');\n const refs = new Set<string>();\n addAll(refs, body, VARIABLE_RE, true);\n addAll(refs, body, CONDITIONAL_REF_RE, true);\n\n return { refs: [...refs], sets, defs, includes };\n}\n\nfunction collect(text: string, re: RegExp, fold: boolean): string[] {\n const seen = new Set<string>();\n addAll(seen, text, re, fold);\n return [...seen];\n}\n\nfunction addAll(target: Set<string>, text: string, re: RegExp, fold: boolean): void {\n for (const m of text.matchAll(re)) {\n const value = m[1];\n if (value !== undefined && value !== '') target.add(fold ? value.toLowerCase() : value);\n }\n}\n","/**\n * Error hierarchy for @spintax/core (spec §9.3 — minimal, not a taxonomy).\n * `render()` throws these only on programmer error, never on template content.\n */\n\n/** Base class for programmer-error throws from render(). */\nexport class SpintaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SpintaxError';\n }\n}\n\n/** A host-injected includeResolver itself threw. */\nexport class IncludeResolverError extends SpintaxError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = 'IncludeResolverError';\n if (options && 'cause' in options) {\n (this as { cause?: unknown }).cause = options.cause;\n }\n }\n}\n\n// NOTE: there is deliberately NO MaxDepthExceededError. Exceeding maxDepth\n// (circular / too-deep #include, runaway variable recursion) is LENIENT — the\n// guard resolves to '' rather than throwing, matching the plugin (which logs +\n// returns ''). render() throwing on a depth breach would break the lenient\n// contract, so no such error type is part of the public surface (§9.2/§9.3).\n\n/** An Ast produced by an incompatible engine version was passed back in. */\nexport class AstVersionError extends SpintaxError {\n constructor(message: string) {\n super(message);\n this.name = 'AstVersionError';\n }\n}\n\n/** Thrown by not-yet-implemented ops / node kinds until the engine lands. */\nexport class NotImplementedError extends SpintaxError {\n constructor(what: string) {\n super(`${what} is not implemented yet.`);\n this.name = 'NotImplementedError';\n }\n}\n","/**\n * Tree-walk renderer with the plugin's staged semantics layered on (parity with\n * Renderer::process_template). Not a naive walk — the deterministic stages are\n * reproduced in order:\n * - #set is a global pre-pass (parser) → setDefs; those enum values are\n * COLLAPSED ONCE here (buildVars), skipping values with `{?`/`{plural ` (they\n * reference vars and defer to the body) — plugin Stage 4b.\n * - variables resolve against the merged map (runtime context > #set); a value\n * that itself contains constructs is re-parsed and rendered (recursive, depth\n * capped) — this covers conditionals/plurals introduced by a variable value\n * (Stages 6b–6c), so a separate pre/post conditional pass isn't needed.\n * - conditionals test truthiness against the raw var map; plurals resolve the\n * count (vars already expanded) then pick the bucket, lenient fullwidth\n * fallback (Stage 6d, after vars).\n * - #include (post-tree string pass) and post-process are later PRs.\n *\n * RNG note: cross-engine RNG-sequence parity is a non-goal (§3.2). Enumerations\n * render outer-first and LAZILY (only the picked branch's nested RNG is used) vs\n * the plugin's eager innermost-out; corpus-safe because deterministic nested-enum\n * cases use order-independent sequences. Permutation matches the plugin's exact\n * pick→Fisher-Yates, so its rng-strategy cases are exact.\n */\nimport type { Node, ParsedAst, PermutationNode, PluralNode, ConditionalNode } from './ast';\nimport { IncludeResolverError } from './errors';\nimport { parseSequence, parseTemplate, recognizeConditional } from './parser';\nimport { normalizeBaseLang, pluralArity, pluralFor } from './plurals';\nimport type { Rng } from './rng';\n\nconst MAX_VARIABLE_DEPTH = 50;\n// ASCII whitespace only, spelled out — no dialect's `\\s` is this set. This comment used to\n// claim PHP's `\\s` under /u is ASCII; measured (#55), it is the opposite: /u turns on\n// PCRE2_UCP, so PHP matched NBSP and all of \\p{Z} here until it spelled the class out too.\n// The contract is this regex, pinned by the corpus (extract/include-*).\nconst INCLUDE_LINE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\n\n/** Document-level render context (threads through nested #include resolution). */\n/**\n * A `{plural …}` block the renderer could not resolve, reported through\n * {@link RenderCtx.onPluralError}. Observation only — the render still degrades\n * exactly as it always has (§0.1 lenient contract); the host decides whether a\n * report is fatal. Mirrors the plugin's `on_error` callable.\n */\nexport interface PluralIssue {\n /**\n * `plural.nested-brackets` and `plural.arity` are the same codes `validate()`\n * emits. `plural.count` has no validate counterpart on purpose — an unresolved\n * count is a runtime-value fact, invisible to static analysis.\n */\n readonly code: 'plural.nested-brackets' | 'plural.arity' | 'plural.count';\n readonly message: string;\n /** The construct as the renderer saw it, AFTER variable expansion. */\n readonly construct: string;\n /** Normalized base language the arity was judged against. */\n readonly locale: string;\n /** Arity verdicts only. */\n readonly expected?: number;\n readonly got?: number;\n}\n\nexport interface RenderCtx {\n /** Runtime/host variable map — inherited by child #includes (NOT parent #set). */\n readonly runtimeContext: Readonly<Record<string, string>>;\n readonly rng: Rng;\n readonly locale: string;\n readonly resolver: ((ref: string) => string | null) | undefined;\n readonly maxDepth: number;\n /** #include ref chain for circular-reference detection. */\n readonly includeStack: readonly string[];\n /** Optional observer for unresolvable plural blocks; never affects output. */\n readonly onPluralError: ((issue: PluralIssue) => void) | undefined;\n}\n\n/**\n * Render a parsed template: build vars → roll `#def` → tree-walk → resolve `#includes`\n * (post-tree string pass, like the plugin's Stage 9 resolve_nested, AFTER\n * enum/perm). Post-process (Stage 10) is layered on by the public render().\n */\nexport function renderAst(ast: ParsedAst, ctx: RenderCtx): string {\n const base = buildVars(ast.setDefs, ctx.runtimeContext);\n const walkOpts = {\n rng: ctx.rng,\n locale: ctx.locale,\n depth: 0,\n onPluralError: ctx.onPluralError,\n };\n // The roll happens here and not inside buildVars: a definition is rendered against the FULL\n // context, globals and runtime included, so it must wait until that context exists.\n const vars =\n Object.keys(ast.defDefs).length > 0\n ? { ...base, ...rollDefinitions(ast.defDefs, base, ctx.runtimeContext, walkOpts) }\n : base;\n const text = renderNodes(ast.nodes, { ...walkOpts, vars });\n return ctx.resolver ? resolveIncludes(text, ctx) : text;\n}\n\n/**\n * Replace each `#include \"ref\"` (line-anchored) with the host-resolved child\n * template, rendered with a CHILD scope: inherits runtime context but NOT the\n * parent's #set locals (plugin `for_child_render`). Circular refs / runaway\n * depth resolve to '' (lenient); a resolver that throws surfaces as\n * IncludeResolverError (programmer error).\n *\n * NOTE: cycles are detected by the ref STRING (the engine has no template\n * identity beyond the host-supplied ref, §4.1), so two aliased refs for one\n * template aren't seen as a cycle and recurse until `maxDepth`. `maxDepth` also\n * caps deep ACYCLIC chains (silently → ''), a guard the plugin lacks.\n */\nfunction resolveIncludes(text: string, ctx: RenderCtx): string {\n INCLUDE_LINE_RE.lastIndex = 0;\n return text.replace(INCLUDE_LINE_RE, (_m, ref: string): string => {\n if (ctx.includeStack.includes(ref) || ctx.includeStack.length >= ctx.maxDepth) return '';\n let included: string | null;\n try {\n included = ctx.resolver!(ref);\n } catch (cause) {\n throw new IncludeResolverError(`includeResolver threw for \"${ref}\"`, { cause });\n }\n if (included === null) return '';\n return renderAst(parseTemplate(included), {\n ...ctx,\n runtimeContext: ctx.runtimeContext, // child inherits runtime, not parent #set\n includeStack: [...ctx.includeStack, ref],\n });\n });\n}\n\nexport interface RenderInternalOptions {\n /** Merged variable map, keys LOWER-CASED (runtime context wins over #set). */\n readonly vars: Readonly<Record<string, string>>;\n readonly rng: Rng;\n /** Plural-bucket locale (raw; normalized per lookup). Empty ⇒ default 2-form. */\n readonly locale: string;\n /** Variable re-processing depth (guards runaway/circular expansion). */\n readonly depth: number;\n /** Optional observer for unresolvable plural blocks; never affects output. */\n readonly onPluralError: ((issue: PluralIssue) => void) | undefined;\n}\n\n/**\n * Build the merged variable map: `#set` values go in RAW, then the runtime context overlays them\n * (and wins). Context keys are lowercased.\n *\n * A `#set` is a macro — its value is re-parsed and re-rendered at every `%var%` reference, so any\n * brackets it holds re-roll each time. Nothing is resolved here. (Until 0.3.0 this collapsed\n * enumeration-valued `#set`s once at set-time; that behaviour moved to `#def`.)\n */\nexport function buildVars(\n setDefs: Readonly<Record<string, string>>,\n context: Readonly<Record<string, string>>,\n): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const [name, value] of Object.entries(setDefs)) {\n vars[name] = value;\n }\n for (const [name, value] of Object.entries(context)) {\n vars[name.toLowerCase()] = value;\n }\n return vars;\n}\n\n/**\n * Render each `#def` value ONCE and return the frozen results, to be merged over `vars`.\n *\n * A definition value is rendered as if it were a miniature body — the same tree walk the document\n * gets — and the result is held for every reference. This runs only after the merged context\n * exists, so a definition can read globals and runtime variables; a runtime variable of the same\n * name outranks it and the definition is then never rolled at all.\n *\n * Values are rendered in dependency order, and that order follows aliases: a `#def` can reach\n * another `#def` through a `#set`, which is expanded at reference time and therefore invisible in\n * the first definition's own text.\n */\nexport function rollDefinitions(\n defDefs: Readonly<Record<string, string>>,\n vars: Readonly<Record<string, string>>,\n context: Readonly<Record<string, string>>,\n opts: Omit<RenderInternalOptions, 'vars'>,\n): Record<string, string> {\n const outranked = new Set(Object.keys(context).map((key) => key.toLowerCase()));\n const rolled: Record<string, string> = {};\n\n // The alias map is every macro value a definition can see, minus the definitions that will\n // actually be rolled — a `#def` shadows a same-named global, and hopping through the shadowed\n // value computes the wrong graph. A definition the runtime outranks is NOT removed: it is never\n // rolled, so the runtime value is what really gets substituted and the graph must follow it.\n const aliases: Record<string, string> = {};\n for (const [name, value] of Object.entries(vars)) {\n if (name in defDefs && !outranked.has(name)) continue;\n aliases[name] = value;\n }\n\n for (const name of orderDefinitions(defDefs, aliases)) {\n if (outranked.has(name)) continue;\n const value = defDefs[name] ?? '';\n rolled[name] = renderNodes(parseSequence(value), { ...opts, vars: { ...vars, ...rolled } });\n }\n\n return rolled;\n}\n\n/** Definition names, dependencies first. A cycle cannot be ordered, so its members come last. */\nfunction orderDefinitions(\n defDefs: Readonly<Record<string, string>>,\n aliases: Readonly<Record<string, string>>,\n): string[] {\n const names = Object.keys(defDefs);\n const blocked = new Map<string, Set<string>>();\n\n for (const name of names) {\n const reached = referencedNames(defDefs[name] ?? '', aliases);\n blocked.set(name, new Set(names.filter((candidate) => reached.has(candidate))));\n }\n\n const ordered: string[] = [];\n let pending = names;\n\n while (pending.length > 0) {\n const ready = pending.filter((name) => {\n const deps = blocked.get(name);\n return !deps || ![...deps].some((dep) => dep !== name && pending.includes(dep));\n });\n if (ready.length === 0) return [...ordered, ...pending];\n ordered.push(...ready);\n pending = pending.filter((name) => !ready.includes(name));\n }\n\n return ordered;\n}\n\n/** Every variable name a value reaches, hopping through macro (alias) values to a fixpoint. */\nfunction referencedNames(value: string, aliases: Readonly<Record<string, string>>): Set<string> {\n const seen = new Set<string>();\n const queue = directReferences(value);\n\n while (queue.length > 0) {\n const name = queue.shift() as string;\n if (seen.has(name)) continue;\n seen.add(name);\n const alias = aliases[name];\n if (alias !== undefined) queue.push(...directReferences(alias));\n }\n\n return seen;\n}\n\n/** The `%var%` names written literally in a string, lowercased. */\nfunction directReferences(text: string): string[] {\n return [...text.matchAll(/%(\\w+)%/gu)].map((match) => (match[1] ?? '').toLowerCase());\n}\n\nexport function renderNodes(nodes: readonly Node[], opts: RenderInternalOptions): string {\n let out = '';\n for (const node of nodes) out += renderNode(node, opts);\n return out;\n}\n\nfunction renderNode(node: Node, opts: RenderInternalOptions): string {\n switch (node.type) {\n case 'literal':\n return node.value;\n case 'variable':\n return resolveVariable(node.name, opts);\n case 'enumeration':\n return renderEnumeration(node.options, opts);\n case 'permutation':\n return renderPermutation(node, opts);\n case 'conditional':\n return renderConditional(node, opts);\n case 'plural':\n return renderPlural(node, opts);\n }\n}\n\n/** `min === max` short-circuits WITHOUT consuming the RNG (plugin `random_int`). */\nfunction randomInt(rng: Rng, min: number, max: number): number {\n return min === max ? min : rng(min, max);\n}\n\n/**\n * Resolve a `%var%`. A value containing constructs is re-parsed and rendered\n * (recursive, depth-capped) so nested vars / conditionals / plurals introduced by\n * the value are resolved; a plain value is returned as-is; unresolved ⇒ verbatim.\n */\nfunction resolveVariable(name: string, opts: RenderInternalOptions): string {\n const value = opts.vars[name.toLowerCase()];\n if (value === undefined) return `%${name}%`;\n // At the cap, stop expanding (lenient: partial output, never throws — unlike the\n // plugin which throws→'' on runaway; §9.2 render never throws on content).\n if (opts.depth >= MAX_VARIABLE_DEPTH || !/[{[%]/u.test(value)) return value;\n // parseSequence, NOT parseTemplate: a value must not be re-comment-stripped or\n // re-#set-extracted (those are one-time body passes in the plugin).\n return renderNodes(parseSequence(value), { ...opts, depth: opts.depth + 1 });\n}\n\n/** Variable-expansion ONLY (plugin `expand_variables` fixpoint) — leaves enums/perms literal. */\nfunction expandVarsOnly(text: string, opts: RenderInternalOptions): string {\n let out = text;\n for (let i = 0; i < MAX_VARIABLE_DEPTH; i += 1) {\n let changed = false;\n out = out.replace(/%(\\w+)%/gu, (m, name: string): string => {\n const value = opts.vars[name.toLowerCase()];\n if (value === undefined) return m;\n changed = true;\n return value;\n });\n if (!changed) break;\n }\n return out;\n}\n\n/** Truthy = the raw var value is set and has a non-whitespace char (plugin is_truthy). */\nfunction conditionalTakesThen(name: string, inverted: boolean, opts: RenderInternalOptions): boolean {\n const value = opts.vars[name.toLowerCase()];\n const baseTruthy = value !== undefined && /\\S/u.test(value);\n return inverted ? !baseTruthy : baseTruthy;\n}\n\nfunction renderConditional(node: ConditionalNode, opts: RenderInternalOptions): string {\n const truthy = conditionalTakesThen(node.name, node.inverted, opts);\n return renderNodes(truthy ? node.then : node.else, opts);\n}\n\n/**\n * Resolve conditionals in the plural COUNT slot, textually — the branch is\n * substituted, never rendered (spintax-js#67).\n *\n * Why this exists: the plugin runs its conditional stage over the whole text\n * before plurals, so `#set %n% = {?flag?1|2}` reaches the count slot as a plain\n * number and the block renders. This engine parses the count slot into a raw\n * string and expanded VARIABLES only, so the conditional survived, failed the\n * numeric test, and the block was ERASED — `validate()` meanwhile returned no\n * diagnostic at all, and `plural.count-macro` documents conditionals as exempt\n * *because* they resolve before plurals. Valid input, silently deleted output.\n *\n * Textual, and only the taken branch's text, because the stage order still holds\n * around it: enums and permutations resolve AFTER plurals, so a branch yielding\n * `{a|b}` must reach the numeric test as `{a|b}` and erase the block, exactly as\n * the plugin does. Rendering the branch would spin it into `a` and invent a\n * count neither engine has.\n *\n * The FORM slot is deliberately not touched: there the engines genuinely\n * disagree and no side has been chosen yet (spintax-js#67).\n *\n * Iterative, over spans, for two reasons paid for in review: recursing into the\n * taken branch made `render()` throw `RangeError` at ~9000 levels of nesting —\n * §9.2 says render never throws on content, and the parsers were made iterative\n * for this exact reason — and re-scanning per `{?` was quadratic (see\n * {@link matchBraces}). Both are reachable from template text through the live\n * public Worker.\n */\nfunction resolveCountConditionals(text: string, opts: RenderInternalOptions): string {\n if (!text.includes('{?')) return text;\n\n const close = matchBraces(text);\n const out: string[] = [];\n // Spans of `text` still to emit, in order. A taken branch is a SPAN of the same\n // string, never a copy, and the untaken one is skipped — so every character is\n // visited at most once and the pass stays linear.\n const pending: [number, number][] = [[0, text.length]];\n\n while (pending.length > 0) {\n const segment = pending.pop() as [number, number];\n const segEnd = segment[1];\n let i = segment[0];\n\n while (i < segEnd) {\n const open = text.indexOf('{?', i);\n // `{?` found past this span belongs to the text around it, not to this span.\n if (open === -1 || open + 1 >= segEnd) {\n out.push(text.slice(i, segEnd));\n break;\n }\n\n // A close outside the span is no close at all: the branch it would reach\n // into is not ours to read.\n const shut = close[open] ?? -1;\n const head = shut === -1 || shut >= segEnd ? null : recognizeConditional(text, open + 1, shut);\n if (head === null) {\n // Unclosed, or `{?` that is not a conditional — a malformed one is an\n // enumeration to the parser, and enumerations are not this pass's business.\n out.push(text.slice(i, Math.min(open + 2, segEnd)));\n i = open + 2;\n continue;\n }\n\n out.push(text.slice(i, open));\n const branchEnd = head.sepIndex < 0 ? shut : head.sepIndex;\n const [from, to] = conditionalTakesThen(head.name, head.inverted, opts)\n ? [head.bodyStart, branchEnd]\n : [head.sepIndex < 0 ? shut : head.sepIndex + 1, shut];\n // Continuation first, branch second: the stack pops the branch back out\n // ahead of it, which is what keeps the output in source order.\n pending.push([shut + 1, segEnd]);\n pending.push([from, to]);\n break;\n }\n }\n\n return out.join('');\n}\n\n/**\n * Match `{` to `}` across the whole string in ONE pass — index of the closing\n * brace for every opening one, or -1.\n *\n * Equivalent to calling `findMatchingClose` per `{`, and that is the point: the\n * per-brace call rescans to the end of the string every time it fails to match,\n * so an unbalanced count slot (legal — only the whole `{plural …}` block has to\n * balance, and the slot is cut at the first `:`) made this pass quadratic. A\n * 78 KB slot took 3 seconds, and the public Worker renders untrusted templates.\n */\nfunction matchBraces(text: string): Int32Array {\n const close = new Int32Array(text.length).fill(-1);\n const opens: number[] = [];\n\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '{') {\n opens.push(i);\n } else if (ch === '}') {\n const open = opens.pop();\n if (open !== undefined) close[open] = i;\n }\n }\n\n return close;\n}\n\n/**\n * Plural agreement (Stage 6d — after variable-expansion, before enum/perm). The\n * count/forms are expanded with VARIABLES ONLY, so the checks (nested-bracket,\n * numeric erase, arity) see the same state the plugin does — enums/perms still\n * literal. Order: bracket check → numeric erase → arity → bucket pick. The two\n * error paths emit the (var-expanded) construct verbatim with fullwidth braces.\n */\nfunction renderPlural(node: PluralNode, opts: RenderInternalOptions): string {\n const countRaw = resolveCountConditionals(expandVarsOnly(node.countRaw, opts), opts);\n const formsRaw = expandVarsOnly(node.formsRaw, opts);\n const base = normalizeBaseLang(opts.locale);\n const report = (issue: PluralIssue): void => opts.onPluralError?.(issue);\n\n if (/[{}[\\]]/u.test(formsRaw)) {\n report({\n code: 'plural.nested-brackets',\n message:\n 'Plural form slot contains nested spintax brackets; extract via #def first — a #set is '\n + 'substituted verbatim and would put the brackets straight back.',\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n });\n return fullwidthVerbatim(countRaw, formsRaw);\n }\n\n const count = phpTrim(countRaw);\n if (!/^-?\\d+$/u.test(count)) {\n // Erasing leaves no trace in the output, so this report is the ONLY way a\n // host can tell an intentionally-empty sentence from an unsubstituted %Var%.\n report({\n code: 'plural.count',\n message: `Plural count slot is empty or non-numeric (${JSON.stringify(count)}); block erased.`,\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n });\n return '';\n }\n\n const forms = formsRaw.split('|').map((f) => phpTrim(f));\n if (forms.length !== pluralArity(base)) {\n report({\n code: 'plural.arity',\n message: `Plural has ${forms.length} form(s); locale \"${base}\" takes ${pluralArity(base)}.`,\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n expected: pluralArity(base),\n got: forms.length,\n });\n return fullwidthVerbatim(countRaw, formsRaw);\n }\n\n // The picked form re-enters the pipeline (its enums/perms resolve after plurals).\n const picked = pluralFor(base, Number.parseInt(count, 10), forms);\n return renderNodes(parseSequence(picked), opts);\n}\n\n/** The construct as the renderer saw it — ASCII braces, for reports and logs. */\nfunction rawConstruct(countRaw: string, formsRaw: string): string {\n return `{plural ${countRaw}:${formsRaw}}`;\n}\n\n/** Emit the plural construct verbatim with fullwidth braces so later passes leave it alone. */\nfunction fullwidthVerbatim(countRaw: string, formsRaw: string): string {\n return rawConstruct(countRaw, formsRaw).replace(/\\{/gu, '{').replace(/\\}/gu, '}');\n}\n\n/** Pick one option (outer-first) and render it. */\nfunction renderEnumeration(options: readonly (readonly Node[])[], opts: RenderInternalOptions): string {\n if (options.length === 0) return '';\n const picked = options[randomInt(opts.rng, 0, options.length - 1)];\n return picked ? renderNodes(picked, opts) : '';\n}\n\ninterface Element {\n text: string;\n sep: string | null;\n}\n\nfunction renderPermutation(node: PermutationNode, opts: RenderInternalOptions): string {\n const elements: Element[] = node.options.map((o) => ({\n text: renderNodes(o.nodes, opts),\n sep: o.separator,\n }));\n const total = elements.length;\n if (total === 0) return '';\n\n const { config } = node;\n const hasMin = config.minsize !== null;\n const hasMax = config.maxsize !== null;\n let min: number;\n let max: number;\n if (hasMin && hasMax) {\n min = config.minsize as number;\n max = config.maxsize as number;\n } else if (hasMin) {\n min = config.minsize as number;\n max = total;\n } else if (hasMax) {\n min = 1;\n max = config.maxsize as number;\n } else {\n min = total;\n max = total;\n }\n min = Math.max(1, Math.min(min, total));\n max = Math.max(min, Math.min(max, total));\n\n const pick = randomInt(opts.rng, min, max);\n shuffle(elements, opts.rng);\n return joinWithSeparators(elements.slice(0, pick), config.sep, config.lastsep ?? config.sep);\n}\n\n/** Fisher-Yates, matching the plugin: i = n-1 … 1, j = randomInt(0, i), swap. */\nfunction shuffle(arr: Element[], rng: Rng): void {\n for (let i = arr.length - 1; i > 0; i -= 1) {\n const j = randomInt(rng, 0, i);\n const tmp = arr[i] as Element;\n arr[i] = arr[j] as Element;\n arr[j] = tmp;\n }\n}\n\nfunction joinWithSeparators(elements: readonly Element[], globalSep: string, globalLastsep: string): string {\n const count = elements.length;\n if (count === 0) return '';\n if (count === 1) return (elements[0] as Element).text;\n\n let out = (elements[0] as Element).text;\n for (let i = 1; i < count; i += 1) {\n const el = elements[i] as Element;\n const sep = el.sep ?? (i === count - 1 ? globalLastsep : globalSep);\n out += padSeparator(sep) + el.text;\n }\n return out;\n}\n\n/** Purely-alphabetic separators get space-padded; others pass through (plugin). */\nfunction padSeparator(sep: string): string {\n const trimmed = phpTrim(sep);\n if (trimmed === '') return sep;\n if (/^\\p{L}+$/u.test(trimmed)) return ` ${trimmed} `;\n return sep;\n}\n\nconst PHP_LTRIM_RE = /^[ \\t\\n\\r\\0\\x0B]+/u;\nconst PHP_RTRIM_RE = /[ \\t\\n\\r\\0\\x0B]+$/u;\nfunction phpTrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '').replace(PHP_RTRIM_RE, '');\n}\n","/**\n * Cosmetic post-process — faithful port of the plugin's `Parser::post_process`\n * (parity-target §5). Order matters: URLs / emails / domains / decimals /\n * abbreviations are shielded to `\\x00…\\x00` placeholders FIRST so the\n * spacing/capitalization passes don't corrupt them, then restored + trimmed.\n *\n * This is the COSMETIC stage (gated by `postProcess`). The mandatory neutralize\n * safety-restore (§6) is separate (M2e) and always runs.\n */\n\n// Single-token abbreviations (case-insensitive) that would otherwise look like a\n// sentence end. Multi-dot forms (т.д.) are handled by the 5a regex.\nconst SINGLE_ABBREVS = [\n // Russian editorial / address / unit shorthands.\n 'соц', 'эл', 'см', 'ср', 'ст', 'ул', 'пр', 'пер', 'г', 'р', 'руб', 'коп',\n 'тыс', 'млн', 'млрд', 'трлн', 'доп', 'напр', 'прим', 'изд', 'обл', 'респ',\n 'стр', 'табл', 'рис', 'мин', 'макс', 'тел', 'факс',\n // English titles / business suffixes / editorial.\n 'etc', 'vs', 'Mr', 'Mrs', 'Ms', 'Dr', 'Prof', 'Sr', 'Jr', 'Inc', 'Ltd', 'Co',\n 'Corp', 'No', 'St', 'Ave', 'Blvd',\n];\n\n// ASCII whitespace only — PHP `\\s`/`\\b` under /u (no PCRE_UCP) are ASCII, while\n// JS `\\s` is Unicode. Using `\\s` would diverge around NBSP / thin spaces, so every\n// whitespace class below is the explicit ASCII set. (`\\b` in JS is already ASCII.)\nconst WS = ' \\\\t\\\\r\\\\n\\\\f\\\\x0B';\nconst S = `[${WS}]`;\n\nconst DOMAIN_PART =\n '(?:(?:(?:xn--)?[\\\\p{L}\\\\p{N}]+(?:-[\\\\p{L}\\\\p{N}]+)*)\\\\.)+(?:xn--[a-z0-9\\\\-]{2,59}|[\\\\p{L}][\\\\p{L}\\\\p{N}-]{1,62})';\n/**\n * URIs — `https?`/`ftp` (with a `//` authority) and `mailto:`/`tel:` (without one) — shielded\n * in ONE pass, deliberately.\n *\n * They used to be two passes, URLs then `mailto:`/`tel:`. A URI body runs to the first\n * delimiter, so the two match sets overlap whenever one URI contains the other's scheme, and\n * with two passes the second one runs into a placeholder the first already minted:\n * `mailto:sales@x.com?body=see%20https://shop.x.com/cart` shielded the URL first, then stored\n * a `mailto:` value with URL_0's key inside it. Restore was past that key by the time the value\n * landed, so the engine emitted a raw U+0000 — illegal in XML, U+FFFD to an HTML parser,\n * rejected by Postgres `text`, and a live key again as soon as an edit detaches it from the\n * prefix that was shielding it (spintax-js#53).\n *\n * Neither pass order fixes that, because whichever runs second is the one that gets split:\n * ordering `mailto:` first instead only moves the damage onto a URL whose path carries a\n * `mailto:`, where the leading half then loses its trailing dot to the punctuation pass\n * (`https://x.io/a.mailto:…` → `https://x.io/a. mailto:…`). A single alternation has no second\n * pass to damage: the leftmost match wins and takes the whole token, whichever scheme it is.\n *\n * `\\x00` stays out of the body class regardless. Nothing is shielded yet when this pass runs,\n * so on ordinary input it never bites; it is there for a caller-supplied U+0000, which would\n * otherwise let a URI match run through the delimiters of a placeholder minted after it.\n */\nconst URI_BODY = `[^\\\\x00${WS}<>\"')\\\\]]`;\nconst URI_RE = new RegExp(`(?:(?:https?|ftp):\\\\/\\\\/|(?:mailto|tel):)${URI_BODY}+`, 'giu');\n// Which placeholder prefix a match gets. Kept distinct (URL vs URI) even though one pass mints\n// both: the prefixes are what the other engines' fixtures and #52's restore regex speak.\nconst MAILTEL_PREFIX_RE = /^(?:mailto|tel):/iu;\nconst EMAIL_RE = new RegExp(`[a-z0-9._%+\\\\-]+@${DOMAIN_PART}\\\\b`, 'giu');\nconst DOMAIN_RE = new RegExp(`\\\\b${DOMAIN_PART}\\\\b`, 'giu');\nconst DECIMAL_RE = /\\b\\d+\\.\\d+\\b/gu;\nconst MULTI_ABBR_RE = new RegExp(`\\\\b(?:\\\\p{L}{1,2}\\\\.${S}*){2,}`, 'gu');\nconst SINGLE_ABBR_RE = new RegExp(`(?<![\\\\p{L}\\\\p{N}])(?:${SINGLE_ABBREVS.join('|')})\\\\.(?=${S}|$|<)`, 'giu');\nconst TRAILING_PUNCT_RE = /([.,;:!]+)$/u;\n\n/**\n * SENTENCE OPENERS — the inverted marks that OPEN a Spanish question/exclamation.\n *\n * Every other European language only ever *closes* with punctuation, which is why the spacing and\n * capitalization passes below were written as if a sentence always begins with a letter. In Spanish\n * it does not: `¿cómo estás?` begins with `¿`, and the capitalizer — which upper-cases the first\n * *character* after a boundary — hits a mark that has no uppercase form and silently leaves the\n * real first letter lowercase.\n *\n * Named explicitly, and deliberately NOT widened to quotes/brackets/«»: those both open and close,\n * and capitalizing after them would mangle list markers (\"Elige. (a) primero\" → \"(A) primero\").\n * This constant encodes the language semantics of Spanish punctuation, not a general \"skip anything\n * that isn't a letter\" rule.\n */\nconst SENTENCE_OPENERS = '¿¡';\n/**\n * The LEAD — everything that can sit between a sentence boundary and the first letter: HTML tags,\n * sentence openers and whitespace, in any order and any number.\n *\n * A single optional opener is not enough. `¡¿Qué haces?!` — RAE's form for a sentence that is both\n * a question and an exclamation — opens with TWO marks, and the opened word is routinely wrapped in\n * markup (`<p>¿<a href=\"/ayuda\">Necesitas ayuda</a>?</p>`), which puts a tag AFTER the opener.\n * Whatever the lead fails to cover silently keeps a lowercase first letter.\n */\nconst LEAD = `(?:<[^>]+>|[${SENTENCE_OPENERS}]|${S})*`;\n\n// Spacing + capitalization (all ASCII-whitespace).\nconst SPACE_BEFORE_PUNCT_RE = new RegExp(`${S}+([,;:!?.])`, 'gu');\nconst SPACE_AFTER_COMMA_RE = new RegExp(`([,;:])(?!\\\\d)(?!${S}|$|<)`, 'gu');\n// A run of sentence punctuation is ONE sentence end, not several: \"...\" and \"?!\" have to survive\n// intact, so the space goes after the whole run. `(?![.!?])` is what completes the run — a greedy\n// `+` on its own still backtracks INTO it to satisfy the lookaheads, turning \"Wow!!!\" into\n// \"Wow!! !\". (JS has no possessive quantifiers, and PHP must match this shape exactly.)\nconst SPACE_AFTER_SENTENCE_RE = new RegExp(`([.!?]+)(?![.!?])(?!\\\\d)(?!${S}|$|<)`, 'gu');\n// An opener binds to the word it opens: \"¿ qué tal ?\" → \"¿qué tal?\". MUST run before the\n// capitalization passes, so they see the real first letter instead of a space.\nconst SPACE_AFTER_OPENER_RE = new RegExp(`([${SENTENCE_OPENERS}])${S}+`, 'gu');\nconst CAP_FIRST_RE = new RegExp(`^(${LEAD})(\\\\p{Ll})`, 'u');\nconst CAP_AFTER_SENTENCE_RE = new RegExp(`([.!?…])(${LEAD})(\\\\p{Ll})`, 'gu');\nconst CAP_AFTER_BLOCK_RE = new RegExp(\n `(<\\\\/?(?:p|h[1-6]|li|blockquote|div|td|th)[^>]*>${LEAD})(\\\\p{Ll})`,\n 'giu',\n);\nconst CAP_AFTER_BREAK_RE = new RegExp(`(\\\\n${LEAD})(\\\\p{Ll})`, 'gu');\n\nconst up = (ch: string): string => ch.toUpperCase();\n\n// The shield's placeholder prefixes, in one place: RESTORE_RE below is built from this\n// list, so a new shield pass cannot mint a key shape the single-pass restore fails to\n// recognise. Keep the two in step by construction, not by memory.\nconst SHIELD_PREFIXES = ['URL', 'URI', 'EMAIL', 'DOM', 'NUM', 'ABBR'] as const;\ntype ShieldPrefix = (typeof SHIELD_PREFIXES)[number];\nconst RESTORE_RE = new RegExp(`\\\\x00(?:${SHIELD_PREFIXES.join('|')})_\\\\d+\\\\x00`, 'gu');\n\n/**\n * Restore the shielded values (step 12).\n *\n * The reference form is one `split(key).join(value)` per key — a full scan of the text\n * per placeholder, so O(text × placeholders). Every URL, URI, email, domain, decimal and\n * abbreviation is shielded, so on shield-heavy output the placeholder count grows with\n * the text and this stage comes to dominate the render: 39 s on a 950 KB render, against\n * 0.07 s with `postProcess: false` (spintax-js#52).\n *\n * A single left-to-right pass is NOT the same function, because the loop is a repeated\n * SUBSTRING substitution and the pass is a token substitution. `split/join` rewrites every\n * occurrence of a key, not only the one the shield placed. Three shapes make them differ:\n * the caller's own text spells a key the shield goes on to mint; an unpaired `\\x00` from\n * the input pairs with a real placeholder's delimiter; and — needing no `\\x00` from the\n * caller at all — two adjacent placeholders sandwich caller text that spells a key, so one\n * token's CLOSING delimiter, that text, and the next token's OPENING delimiter form a\n * third occurrence of a key that really was minted. Delimiters are not owned by the token\n * that placed them.\n *\n * The guard therefore removes the `\\x00`-borne disagreements; it does not make the two\n * functions equal, and an earlier version of this comment claimed a proof that does not\n * hold (spintax-js#54). Measured over a 456 976-input differential sweep whose fragments\n * include bare key names: 13 266 inputs distinguish the two restores, 12 of them carrying\n * no `\\x00`. On every one of those 12 it is the LOOP that is wrong — it emits a raw U+0000\n * from `\\x00`-free input, wrecking two real tokens to serve a forged one — and the single\n * pass returns the text intact. So the fast path is not merely faster on the shape that\n * survives the guard; it is the answer we want there, and the guard's whole remaining\n * effect is the 13 254 `\\x00`-carrying inputs where the loop's reading is the defensible\n * one. Real text carries no `\\x00`, so the fast path is what actually runs.\n *\n * Neither path rescans a value it inserted, which is what makes them agree even if a stored\n * value ever came to contain another key. On `\\x00`-free input none can: URI_BODY excludes\n * `\\x00` and every other shield class is letters/digits/dots, so no match can span a\n * placeholder (spintax-js#53). The property is worth stating because it is the one an\n * ordering change could quietly take away.\n */\nfunction restore(text: string, input: string, placeholders: Map<string, string>): string {\n if (!input.includes('\\x00')) {\n return text.replace(RESTORE_RE, (key) => placeholders.get(key) ?? key);\n }\n let out = text;\n for (const [key, value] of placeholders) {\n out = out.split(key).join(value);\n }\n return out;\n}\n\nexport function postProcess(input: string): string {\n const placeholders = new Map<string, string>();\n let counter = 0;\n\n const store = (value: string, prefix: ShieldPrefix): string => {\n const key = `\\x00${prefix}_${counter}\\x00`;\n placeholders.set(key, value);\n counter += 1;\n return key;\n };\n const storeWithTrailingPunct = (value: string, prefix: ShieldPrefix): string => {\n const m = TRAILING_PUNCT_RE.exec(value);\n if (m) {\n const suffix = m[1] ?? '';\n const body = value.slice(0, value.length - suffix.length);\n return body === '' ? suffix : store(body, prefix) + suffix;\n }\n return store(value, prefix);\n };\n\n let text = input;\n\n // 1-5: shield. URIs go first and in one pass, so an overlapping pair is never split\n // (spintax-js#53), and always before EMAIL/DOMAIN, so the whole `mailto:` survives\n // instead of the address being carved out from under its prefix (spintax-js#41).\n text = text.replace(URI_RE, (m) =>\n storeWithTrailingPunct(m, MAILTEL_PREFIX_RE.test(m) ? 'URI' : 'URL'),\n );\n text = text.replace(EMAIL_RE, (m) => store(m, 'EMAIL'));\n text = text.replace(DOMAIN_RE, (m) => store(m, 'DOM'));\n text = text.replace(DECIMAL_RE, (m) => store(m, 'NUM'));\n text = text.replace(MULTI_ABBR_RE, (m) => store(m, 'ABBR'));\n text = text.replace(SINGLE_ABBR_RE, (m) => store(m, 'ABBR'));\n\n // 6: collapse duplicate spaces/tabs.\n text = text.replace(/[ \\t]{2,}/gu, ' ');\n\n // 7: punctuation spacing. Remove whitespace before punctuation, then add a\n // space after ,;: and after a RUN of .!? unless followed by a digit / space / end / tag.\n text = text.replace(SPACE_BEFORE_PUNCT_RE, '$1');\n text = text.replace(SPACE_AFTER_COMMA_RE, '$1 ');\n text = text.replace(SPACE_AFTER_SENTENCE_RE, '$1 ');\n // 7a: a Spanish opener binds to the word it opens. Before capitalization, deliberately.\n text = text.replace(SPACE_AFTER_OPENER_RE, '$1');\n\n // 8: capitalize the first letter (skipping leading HTML tags and sentence openers).\n text = text.replace(CAP_FIRST_RE, (_m, lead: string, ch: string) => lead + up(ch));\n // 9: capitalize after sentence punctuation (through HTML tags).\n text = text.replace(CAP_AFTER_SENTENCE_RE, (_m, p: string, gap: string, ch: string) => p + gap + up(ch));\n // 10: capitalize after block-level HTML tags.\n text = text.replace(CAP_AFTER_BLOCK_RE, (_m, tag: string, ch: string) => tag + up(ch));\n // 11: capitalize after line breaks.\n text = text.replace(CAP_AFTER_BREAK_RE, (_m, br: string, ch: string) => br + up(ch));\n\n // 12: restore placeholders, then trim.\n return restore(text, input, placeholders).trim();\n}\n","/**\n * The full render pipeline with an INJECTED rng — the seam shared by the public\n * render() (which seeds the rng from RenderOptions.seed) and the corpus harness\n * (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what\n * lets the deterministic parity fixtures assert exact output.\n *\n * Order: strip stray sentinels → build vars, roll #def, tree-walk (+ #include) →\n * cosmetic post-process (if on) → mandatory neutralize safety-restore (always).\n */\nimport { renderAst, type PluralIssue, type RenderCtx } from './render';\nimport { postProcess } from './postprocess';\nimport { safetyRestore } from './neutralize';\nimport { parseTemplate } from './parser';\nimport { isParsedAst, type Ast, type ParsedAst } from './ast';\nimport { AstVersionError } from './errors';\nimport type { Rng } from './rng';\n\n/** Default for {@link PipelineOptions.maxDepth} (#include + parse-nesting guard). */\nexport const DEFAULT_MAX_DEPTH = 20;\n\nexport interface PipelineOptions {\n context?: Record<string, string>;\n locale?: string;\n includeResolver?: (ref: string) => string | null;\n postProcess?: boolean;\n maxDepth?: number;\n onPluralError?: (issue: PluralIssue) => void;\n}\n\nexport function renderWith(input: string | Ast, rng: Rng, opts: PipelineOptions = {}): string {\n const ctx: RenderCtx = {\n runtimeContext: opts.context ?? {},\n rng,\n locale: opts.locale ?? '',\n resolver: opts.includeResolver,\n maxDepth: opts.maxDepth ?? DEFAULT_MAX_DEPTH,\n includeStack: [],\n onPluralError: opts.onPluralError,\n };\n // parseTemplate sanitises author markup itself now (see its docblock), so the sentinel strip\n // that used to live here — and only here, missing parse() and analyze() — is gone.\n const ast = resolveAst(input);\n let out = renderAst(ast, ctx);\n // Cosmetic post-process defaults ON (§0.1); false skips it. It runs on the still-\n // shielded form (neutralize sentinels are inert here).\n if (opts.postProcess !== false) out = postProcess(out);\n // Mandatory neutralize safety-restore (§6) — ALWAYS runs, even with postProcess:false.\n return safetyRestore(out);\n}\n\n/** Resolve a `string | Ast` input to a parsed AST (parses a string fresh). */\nfunction resolveAst(input: string | Ast): ParsedAst {\n if (typeof input === 'string') return parseTemplate(input);\n if (isParsedAst(input)) return input;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n","/**\n * RNG seam. Signature `(min, max) => int` inclusive — mirrors the plugin's\n * injectable `$random_fn`. The engine short-circuits `min === max` (see\n * `randomInt` in render.ts), so this is only invoked when a real choice exists.\n */\nexport type Rng = (min: number, max: number) => number;\n\n/**\n * Build an RNG from a `seed` (deterministic PRNG — reproducible within THIS\n * engine; cross-engine sequence parity is a non-goal §3.2) or, when omitted,\n * from `Math.random` (universal on Workers / Node / browser).\n */\nexport function makeRng(seed: number | string | undefined): Rng {\n const next =\n seed === undefined\n ? Math.random\n : mulberry32(typeof seed === 'number' ? seed >>> 0 : hashString(seed));\n return (min, max) => min + Math.floor(next() * (max - min + 1));\n}\n\n/** mulberry32 — tiny, fast, well-distributed 32-bit PRNG. */\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** FNV-1a hash of a string seed → 32-bit uint. */\nfunction hashString(s: string): number {\n let h = 2166136261;\n for (let i = 0; i < s.length; i += 1) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return h >>> 0;\n}\n","/**\n * @spintax/core — framework-agnostic Spintax engine (parse / render / validate /\n * extract / analyze / neutralize). Public API contract per spec §9.2 / §9.3.\n *\n * STATUS: M3. The full §9.2 surface — parse / render / validate / extract /\n * analyze / neutralize — is implemented.\n */\n\nimport { parseTemplate } from './internal/parser';\nimport { validateTemplate } from './internal/validator';\nimport { extractFromSource } from './internal/extract';\nimport { renderWith } from './internal/pipeline';\nimport { neutralize as neutralizeValue } from './internal/neutralize';\nimport { makeRng } from './internal/rng';\nimport { AstVersionError } from './internal/errors';\nimport { isParsedAst, walk, type Ast, type ParsedAst } from './internal/ast';\nimport type { PluralIssue } from './internal/render';\nimport {\n normalizeBaseLang as normalizeBaseLangInternal,\n pluralArity as pluralArityForBase,\n} from './internal/plurals';\n\n// ─── Public types (§9.2) ─────────────────────────────────────────────────────\n\n/**\n * Opaque, versioned parse result. NOT a public data contract in v1 — consumers\n * pass it back to render/validate/extract/analyze, they do not introspect it.\n * An in-memory perf handle, not a serialization format (do not persist across\n * engine versions).\n */\nexport type { Ast };\n\n/** Reported through {@link RenderOptions.onPluralError}; never thrown. */\nexport type { PluralIssue };\n\nexport interface RenderOptions {\n /** Variable map (T1, author-controlled by default — §6). */\n context?: Record<string, string>;\n /** Deterministic RNG seed; omit ⇒ nondeterministic. */\n seed?: number | string;\n /** Plural-bucket locale (§3.1); omit ⇒ default EN-style 2-form. */\n locale?: string;\n /** Host-injected, SYNCHRONOUS #include resolver (§4.1); omit ⇒ #include disabled. */\n includeResolver?: (ref: string) => string | null;\n /** Default TRUE (§0.1). false skips cosmetic post-process only; the mandatory neutralize safety-restore still runs (§6). */\n postProcess?: boolean;\n /** #include + parse-nesting guard; defaults to {@link DEFAULT_MAX_DEPTH}. */\n maxDepth?: number;\n /**\n * Observer for `{plural …}` blocks the renderer could not resolve — the port of\n * the plugin's `on_error` callable. Observation ONLY: output degrades exactly as\n * it does without it (§0.1 lenient contract — `render()` never throws on template\n * content), and the host decides whether a report is fatal.\n *\n * Worth wiring when a render is PERSISTED rather than shown: an unresolved count\n * erases its block, which is indistinguishable in the output from copy that was\n * meant to be empty.\n */\n onPluralError?: (issue: PluralIssue) => void;\n}\n\nexport interface ValidateOptions {\n /** Plural-bucket locale for arity verdicts (§3.1); omit ⇒ default 2-form. */\n locale?: string;\n /** Slug/id allow-list; enables \"unknown #include target\" verdicts. */\n knownIncludes?: readonly string[];\n /**\n * Variable names the host will supply at render (globals / context keys).\n * Suppresses the `variable.undefined` WARNING for them — verdict is unaffected\n * (an undefined var is never an error). Case-insensitive.\n */\n knownVariables?: readonly string[];\n}\n\nexport interface Diagnostic {\n severity: 'error' | 'warning';\n /** Stable machine code — parity-gated (wording/position are not). */\n code: string;\n message: string;\n /** 1-based. */\n line: number;\n /** 1-based. */\n column: number;\n endLine?: number;\n endColumn?: number;\n /** Structured specifics keyed off `code`, e.g. { expected: 3, got: 2 }. */\n data?: Record<string, unknown>;\n}\n\nexport interface ExtractResult {\n refs: string[];\n /** Names defined by `#set` — macros, re-picked at every reference. */\n sets: string[];\n /** Names defined by `#def` — rolled once per render and held. */\n defs: string[];\n includes: string[];\n}\n\nexport interface Analysis extends ExtractResult {\n diagnostics: Diagnostic[];\n /** Best-effort construct counts — NOT a variant-cardinality promise (§9.3). */\n constructs: Record<string, number>;\n}\n\n/** Default value for {@link RenderOptions.maxDepth}. */\nexport { DEFAULT_MAX_DEPTH } from './internal/pipeline';\n\n// ─── Locale helpers ──────────────────────────────────────────────────────────\n//\n// Exported so a consumer that must AGREE with the engine about plurals can ask\n// it, instead of keeping a copy of the table. A copy is not hypothetical: this\n// repo's own authoring prompt kept one, and it drifted twice — once on content\n// (a new locale added in one place) and once on shape (`locale.slice(0, 2)`\n// instead of this normalization, which disagrees on any 3-letter tag).\n//\n// `findPluralBlocks` is deliberately NOT exported alongside these: it returns\n// byte offsets into the source, i.e. parser internals, and publishing it would\n// freeze that shape and invite consumers to build on the parse layer — the same\n// reason `Ast` is opaque (see its doc above).\n\n/**\n * A locale's base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. Absent or\n * empty gives `''`.\n *\n * Knows nothing of ISO-639-3, so a 3-letter tag is returned whole (`srp`→`srp`)\n * and is NOT recognized as its 2-letter language.\n */\nexport function normalizeBaseLang(locale?: string | null): string {\n return normalizeBaseLangInternal(locale ?? '');\n}\n\n/**\n * How many `{plural …}` forms this locale takes — 3 for the Slavic one/few/other\n * family (ru/uk/be + sr/hr/bs), 2 for everything else.\n *\n * Takes a RAW locale and normalizes internally, unlike the internal helper of the\n * same name: a public function that silently answered 2 for `sr-Latn` would be a\n * trap. Accepts an absent locale, and unknown tags fall back to 2 rather than\n * throwing (§3.1), so the same optional value `RenderOptions.locale` carries can be\n * passed straight through.\n *\n * NOTE the asymmetry with {@link validate}: an absent or empty locale makes the\n * validator skip the arity check ENTIRELY (structural verdicts only), whereas this\n * answers the 2-form default that {@link render} would then apply. Ask this what\n * render will do; do not read it as \"what validate will enforce\".\n */\nexport function pluralArity(locale?: string | null): number {\n return pluralArityForBase(normalizeBaseLang(locale));\n}\n\n// ─── Errors (§9.3 — minimal, not a taxonomy) ─────────────────────────────────\n\nexport { SpintaxError, IncludeResolverError, AstVersionError, NotImplementedError } from './internal/errors';\n\n// ─── Public API surface (§9.2) ───────────────────────────────────────────────\n\nexport function parse(src: string): Ast {\n return parseTemplate(src);\n}\n\nexport function render(input: string | Ast, opts: RenderOptions = {}): string {\n // Public entry: seed the rng, then run the shared pipeline (internal/pipeline).\n return renderWith(input, makeRng(opts.seed), opts);\n}\n\nexport function validate(input: string | Ast, opts: ValidateOptions = {}): Diagnostic[] {\n return validateTemplate(resolveSource(input), opts);\n}\n\n/** Resolve a `string | Ast` input to its source text (for the raw-text checks). */\nfunction resolveSource(input: string | Ast): string {\n if (typeof input === 'string') return input;\n if (isParsedAst(input)) return input.source;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n\nexport function extract(input: string | Ast): ExtractResult {\n return extractFromSource(resolveSource(input));\n}\n\nexport function analyze(input: string | Ast, opts: ValidateOptions = {}): Analysis {\n const ast = resolveAst(input);\n const extracted = extractFromSource(ast.source);\n return {\n ...extracted,\n diagnostics: validateTemplate(ast.source, opts),\n constructs: countConstructs(ast, extracted.includes.length),\n };\n}\n\n/** Resolve a `string | Ast` input to a parsed AST (parses a string fresh). */\nfunction resolveAst(input: string | Ast): ParsedAst {\n if (typeof input === 'string') return parseTemplate(input);\n if (isParsedAst(input)) return input;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n\n/**\n * Best-effort construct census (§9.3) — counts author-visible constructs, NOT a\n * variant-cardinality promise. `set`/`include` are directive counts; the rest are\n * AST node types (nested nodes included; literals excluded).\n */\nfunction countConstructs(ast: ParsedAst, includeCount: number): Record<string, number> {\n const counts: Record<string, number> = {\n enumeration: 0,\n permutation: 0,\n variable: 0,\n conditional: 0,\n plural: 0,\n };\n walk(ast.nodes, (n) => {\n if (n.type in counts) counts[n.type] = (counts[n.type] ?? 0) + 1;\n });\n counts.set = Object.keys(ast.setDefs).length;\n counts.include = includeCount;\n return counts;\n}\n\nexport function neutralize(value: string): string {\n return neutralizeValue(value);\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/internal/ast.ts","../src/internal/neutralize.ts","../src/internal/parser.ts","../src/internal/plurals.ts","../src/internal/validator.ts","../src/internal/extract.ts","../src/internal/errors.ts","../src/internal/render.ts","../src/internal/postprocess.ts","../src/internal/pipeline.ts","../src/internal/rng.ts","../src/index.ts"],"names":["PLURAL_PREFIX","text","INCLUDE_RE","VARIABLE_RE","phpTrim","PHP_LTRIM_RE","PHP_RTRIM_RE","RESTORE_RE","normalizeBaseLang","pluralArity","resolveAst","neutralize"],"mappings":";AAyBO,IAAM,WAAA,GAAc,CAAA;AAyGpB,SAAS,IAAA,CAAK,OAAwB,KAAA,EAAgC;AAC3E,EAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,IAAA,KAAA,CAAM,CAAC,CAAA;AACP,IAAA,QAAQ,EAAE,IAAA;AAAM,MACd,KAAK,aAAA;AACH,QAAA,KAAA,MAAW,GAAA,IAAO,CAAA,CAAE,OAAA,EAAS,IAAA,CAAK,KAAK,KAAK,CAAA;AAC5C,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,IAAA,CAAK,CAAA,CAAE,MAAM,KAAK,CAAA;AAClB,QAAA,IAAA,CAAK,CAAA,CAAE,MAAM,KAAK,CAAA;AAClB,QAAA;AAAA,MACF,KAAK,aAAA;AACH,QAAA,KAAA,MAAW,OAAO,CAAA,CAAE,OAAA,EAAS,IAAA,CAAK,GAAA,CAAI,OAAO,KAAK,CAAA;AAClD,QAAA;AAEA;AACJ,EACF;AACF;AAGO,SAAS,YAAY,KAAA,EAAoC;AAC9D,EAAA,OACE,OAAO,KAAA,KAAU,QAAA,IACjB,KAAA,KAAU,QACT,KAAA,CAAmC,UAAA,KAAe,WAAA,IACnD,OAAQ,MAA+B,MAAA,KAAW,QAAA,IAClD,KAAA,CAAM,OAAA,CAAS,MAA8B,KAAK,CAAA;AAEtD;;;AC3IA,IAAM,aAAa,CAAC,GAAA,EAAK,KAAK,GAAA,EAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AAChD,IAAM,aAAA,GAAgB,KAAA;AAEtB,IAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,IAAM,OAAA,uBAAc,GAAA,EAAoB;AACxC,UAAA,CAAW,OAAA,CAAQ,CAAC,EAAA,EAAI,CAAA,KAAM;AAC5B,EAAA,MAAM,QAAA,GAAW,MAAA,CAAO,YAAA,CAAa,aAAA,GAAgB,CAAC,CAAA;AACtD,EAAA,MAAA,CAAO,GAAA,CAAI,IAAI,QAAQ,CAAA;AACvB,EAAA,OAAA,CAAQ,GAAA,CAAI,UAAU,EAAE,CAAA;AAC1B,CAAC,CAAA;AAED,IAAM,SAAA,GAAY,aAAA;AAClB,IAAM,aAAa,IAAI,MAAA;AAAA,EACrB,CAAA,CAAA,EAAI,MAAA,CAAO,YAAA,CAAa,aAAa,CAAC,CAAA,CAAA,EAAI,MAAA,CAAO,YAAA,CAAa,aAAA,GAAgB,UAAA,CAAW,MAAA,GAAS,CAAC,CAAC,CAAA,CAAA,CAAA;AAAA,EACpG;AACF,CAAA;AAGO,SAAS,WAAW,KAAA,EAAuB;AAChD,EAAA,OAAO,KAAA,CAAM,QAAQ,SAAA,EAAW,CAAC,OAAO,MAAA,CAAO,GAAA,CAAI,EAAE,CAAA,IAAK,EAAE,CAAA;AAC9D;AAGO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,QAAQ,UAAA,EAAY,CAAC,OAAO,OAAA,CAAQ,GAAA,CAAI,EAAE,CAAA,IAAK,EAAE,CAAA;AAC/D;AAIO,SAAS,eAAe,IAAA,EAAsB;AACnD,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,UAAA,EAAY,EAAE,CAAA;AACpC;;;AChCA,IAAM,WAAA,GAAc,UAAA;AAOb,IAAM,YAAA,GAAe,+DAAA;AAC5B,IAAM,mBAAA,GAAsB,eAAA;AAC5B,IAAM,aAAA,GAAgB,SAAA;AAmBf,SAAS,cAAc,GAAA,EAAwB;AACpD,EAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,OAAA,EAAQ,GAAI,kBAAkB,aAAA,CAAc,cAAA,CAAe,GAAG,CAAC,CAAC,CAAA;AACvF,EAAA,OAAO,EAAE,UAAA,EAAY,WAAA,EAAa,MAAA,EAAQ,GAAA,EAAK,SAAS,OAAA,EAAS,KAAA,EAAO,aAAA,CAAc,IAAI,CAAA,EAAE;AAC9F;AAkBO,SAAS,kBAAkB,IAAA,EAKhC;AACA,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,MAAM,cAAqC,EAAC;AAK5C,EAAA,IAAI,YAAA,GAAe,CAAA;AACnB,EAAA,IAAI,UAAA,GAAa,CAAA;AACjB,EAAA,MAAM,MAAA,GAAS,CAAC,MAAA,KAA2B;AACzC,IAAA,KAAA,IAAS,CAAA,GAAI,YAAA,EAAc,CAAA,GAAI,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC7C,MAAA,IAAI,IAAA,CAAK,UAAA,CAAW,CAAC,CAAA,KAAM,IAAI,UAAA,IAAc,CAAA;AAAA,IAC/C;AACA,IAAA,YAAA,GAAe,MAAA;AACf,IAAA,OAAO,UAAA;AAAA,EACT,CAAA;AAEA,EAAA,YAAA,CAAa,SAAA,GAAY,CAAA;AACzB,EAAA,MAAM,WAAW,IAAA,CAAK,OAAA;AAAA,IACpB,YAAA;AAAA,IACA,CAAC,IAAA,EAAc,IAAA,EAAc,OAAA,EAAiB,OAAe,MAAA,KAA2B;AACtF,MAAA,MAAM,IAAA,GAAO,QAAQ,WAAA,EAAY;AACjC,MAAA,WAAA,CAAY,IAAA,CAAK;AAAA,QACf,IAAA;AAAA,QACA,IAAA;AAAA,QACA,KAAA;AAAA,QACA,IAAA,EAAM,OAAO,MAAM;AAAA,OACpB,CAAA;AACD,MAAA,IAAI,IAAA,KAAS,KAAA,EAAO,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA;AAAA,WAC/B,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA;AACrB,MAAA,OAAO,EAAA;AAAA,IACT;AAAA,GACF;AAEA,EAAA,OAAO,EAAE,MAAM,QAAA,CAAS,OAAA,CAAQ,YAAY,MAAM,CAAA,EAAG,OAAA,EAAS,OAAA,EAAS,WAAA,EAAY;AACrF;AAGO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,iBAAA,EAAmB,EAAE,CAAA;AAC3C;AAIO,SAAS,cAAc,IAAA,EAAsB;AAClD,EAAA,MAAM,QAAgB,EAAC;AACvB,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,IAAI,CAAA,GAAI,CAAA;AAER,EAAA,MAAM,eAAe,MAAY;AAC/B,IAAA,IAAI,YAAY,EAAA,EAAI;AAClB,MAAA,KAAA,CAAM,KAAK,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,SAAS,CAAA;AAC9C,MAAA,OAAA,GAAU,EAAA;AAAA,IACZ;AAAA,EACF,CAAA;AAEA,EAAA,OAAO,CAAA,GAAI,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AAExB,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,IAAA,EAAM,CAAA,EAAG,KAAK,GAAG,CAAA;AAC/C,MAAA,IAAI,QAAQ,EAAA,EAAI;AACd,QAAA,OAAA,IAAW,EAAA;AACX,QAAA,CAAA,IAAK,CAAA;AACL,QAAA;AAAA,MACF;AACA,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,KAAA,CAAM,CAAA,GAAI,GAAG,GAAG,CAAA;AACrC,MAAA,YAAA,EAAa;AACb,MAAA,KAAA,CAAM,IAAA,CAAK,mBAAA,CAAoB,OAAO,CAAC,CAAA;AACvC,MAAA,CAAA,GAAI,GAAA,GAAM,CAAA;AACV,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,MAAM,GAAA,GAAM,iBAAA,CAAkB,IAAA,EAAM,CAAA,EAAG,KAAK,GAAG,CAAA;AAC/C,MAAA,IAAI,QAAQ,EAAA,EAAI;AACd,QAAA,OAAA,IAAW,EAAA;AACX,QAAA,CAAA,IAAK,CAAA;AACL,QAAA;AAAA,MACF;AACA,MAAA,YAAA,EAAa;AACb,MAAA,KAAA,CAAM,IAAA,CAAK,iBAAiB,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA,EAAG,GAAG,CAAC,CAAC,CAAA;AACnD,MAAA,CAAA,GAAI,GAAA,GAAM,CAAA;AACV,MAAA;AAAA,IACF;AAEA,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,MAAM,IAAA,GAAO,YAAY,IAAA,CAAK,IAAA,CAAK,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;AAChD,MAAA,IAAI,SAAS,MAAA,EAAW;AACtB,QAAA,YAAA,EAAa;AACb,QAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,MAAM,CAAA;AACrC,QAAA,CAAA,IAAK,KAAK,MAAA,GAAS,CAAA;AACnB,QAAA;AAAA,MACF;AAAA,IACF;AAEA,IAAA,OAAA,IAAW,EAAA;AACX,IAAA,CAAA,IAAK,CAAA;AAAA,EACP;AAEA,EAAA,YAAA,EAAa;AACb,EAAA,OAAO,KAAA;AACT;AAOA,SAAS,oBAAoB,OAAA,EAAuB;AAClD,EAAA,IAAI,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,GAAA,EAAK;AAC7B,IAAA,MAAM,IAAA,GAAO,oBAAoB,OAAO,CAAA;AACxC,IAAA,IAAI,MAAM,OAAO,IAAA;AAAA,EAEnB,CAAA,MAAA,IAAW,OAAA,CAAQ,UAAA,CAAW,aAAa,CAAA,IAAK,OAAA,CAAQ,KAAA,CAAM,aAAA,CAAc,MAAM,CAAA,CAAE,QAAA,CAAS,GAAG,CAAA,EAAG;AACjG,IAAA,OAAO,WAAA,CAAY,OAAA,CAAQ,KAAA,CAAM,aAAA,CAAc,MAAM,CAAC,CAAA;AAAA,EACxD;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,OAAA,EAAS,aAAA,CAAc,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAM,aAAA,CAAc,CAAC,CAAC,CAAA,EAAE;AAC7F;AAoCO,SAAS,oBAAA,CACd,IAAA,EACA,YAAA,EACA,UAAA,EACwB;AACxB,EAAA,IAAI,IAAI,YAAA,GAAe,CAAA;AACvB,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,GAAA,EAAK;AAC1B,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,CAAA,IAAK,CAAA;AAAA,EACP;AAEA,EAAA,mBAAA,CAAoB,SAAA,GAAY,CAAA;AAChC,EAAA,MAAM,IAAA,GAAO,mBAAA,CAAoB,IAAA,CAAK,IAAI,IAAI,CAAC,CAAA;AAC/C,EAAA,IAAI,SAAS,MAAA,IAAa,CAAA,GAAI,IAAA,CAAK,MAAA,GAAS,YAAY,OAAO,IAAA;AAC/D,EAAA,CAAA,IAAK,IAAA,CAAK,MAAA;AAEV,EAAA,IAAI,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA,KAAM,KAAK,OAAO,IAAA;AACnC,EAAA,CAAA,IAAK,CAAA;AAEL,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,SAAA,EAAW,CAAA,EAAG,UAAU,iBAAA,CAAkB,IAAA,EAAM,CAAA,EAAG,UAAU,CAAA,EAAE;AAC1F;AAEO,SAAS,iBAAiB,OAAA,EAA0C;AACzE,EAAA,MAAM,IAAA,GAAO,oBAAA,CAAqB,OAAA,EAAS,CAAA,EAAG,QAAQ,MAAM,CAAA;AAC5D,EAAA,IAAI,IAAA,KAAS,MAAM,OAAO,IAAA;AAE1B,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,KAAA,CAAM,IAAA,CAAK,SAAS,CAAA;AACzC,EAAA,MAAM,MAAM,IAAA,CAAK,QAAA,GAAW,IAAI,EAAA,GAAK,IAAA,CAAK,WAAW,IAAA,CAAK,SAAA;AAE1D,EAAA,OAAO;AAAA,IACL,MAAM,IAAA,CAAK,IAAA;AAAA,IACX,UAAU,IAAA,CAAK,QAAA;AAAA,IACf,SAAS,GAAA,GAAM,CAAA,GAAI,OAAO,IAAA,CAAK,KAAA,CAAM,GAAG,GAAG,CAAA;AAAA,IAC3C,SAAS,GAAA,GAAM,CAAA,GAAI,KAAK,IAAA,CAAK,KAAA,CAAM,MAAM,CAAC;AAAA,GAC5C;AACF;AAGA,SAAS,oBAAoB,OAAA,EAA8B;AACzD,EAAA,MAAM,KAAA,GAAQ,iBAAiB,OAAO,CAAA;AACtC,EAAA,IAAI,KAAA,KAAU,MAAM,OAAO,IAAA;AAE3B,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,MAAM,KAAA,CAAM,IAAA;AAAA,IACZ,UAAU,KAAA,CAAM,QAAA;AAAA,IAChB,IAAA,EAAM,aAAA,CAAc,KAAA,CAAM,OAAO,CAAA;AAAA,IACjC,IAAA,EAAM,aAAA,CAAc,KAAA,CAAM,OAAO;AAAA,GACnC;AACF;AAGA,SAAS,YAAY,WAAA,EAA2B;AAC9C,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,OAAA,CAAQ,GAAG,CAAA;AAGrC,EAAA,OAAO,EAAE,IAAA,EAAM,QAAA,EAAU,QAAA,EAAU,YAAY,KAAA,CAAM,CAAA,EAAG,KAAK,CAAA,EAAG,QAAA,EAAU,WAAA,CAAY,KAAA,CAAM,KAAA,GAAQ,CAAC,CAAA,EAAE;AACzG;AAIA,IAAM,aAAA,GAAgB,wCAAA;AACtB,IAAM,UAAA,GAAa,sBAAA;AACnB,IAAM,UAAA,GAAa,sBAAA;AACnB,IAAM,MAAA,GAAS,+BAAA;AACf,IAAM,UAAA,GAAa,0BAAA;AACnB,IAAM,WAAA,GAAc,2CAAA;AACpB,IAAM,gBAAA,GAAmB,yBAAA;AAEzB,SAAS,iBAAA,GAAgC;AACvC,EAAA,OAAO,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,GAAA,EAAK,GAAA,EAAK,SAAS,IAAA,EAAK;AACjE;AAGA,SAAS,iBAAiB,QAAA,EAAwB;AAChD,EAAA,MAAM,EAAE,MAAA,EAAQ,OAAA,EAAQ,GAAI,yBAAyB,QAAQ,CAAA;AAC7D,EAAA,MAAM,OAAA,GAAU,2BAAA,CAA4B,aAAA,CAAc,OAAO,CAAC,CAAA;AAClE,EAAA,OAAO,EAAE,IAAA,EAAM,aAAA,EAAe,MAAA,EAAQ,OAAA,EAAQ;AAChD;AAGA,SAAS,yBAAyB,OAAA,EAA0D;AAC1F,EAAA,MAAM,OAAA,GAAU,SAAS,OAAO,CAAA;AAChC,EAAA,IAAI,YAAY,EAAA,IAAM,OAAA,CAAQ,MAAA,CAAO,CAAC,MAAM,GAAA,EAAK;AAC/C,IAAA,OAAO,EAAE,MAAA,EAAQ,iBAAA,EAAkB,EAAG,OAAA,EAAQ;AAAA,EAChD;AACA,EAAA,MAAM,GAAA,GAAM,cAAc,OAAO,CAAA;AACjC,EAAA,IAAI,QAAQ,EAAA,EAAI,OAAO,EAAE,MAAA,EAAQ,iBAAA,IAAqB,OAAA,EAAQ;AAE9D,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,CAAA,EAAG,GAAG,CAAA;AACtC,EAAA,MAAM,SAAA,GAAY,OAAA,CAAQ,KAAA,CAAM,GAAA,GAAM,CAAC,CAAA;AAEvC,EAAA,IAAI,qBAAA,CAAsB,SAAA,EAAW,SAAS,CAAA,EAAG;AAC/C,IAAA,OAAO,EAAE,MAAA,EAAQ,iBAAA,EAAkB,EAAG,OAAA,EAAQ;AAAA,EAChD;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,iBAAA,CAAkB,SAAS,CAAA,EAAG,SAAS,SAAA,EAAU;AACpE;AAGA,SAAS,cAAc,IAAA,EAAsB;AAC3C,EAAA,IAAI,OAAA,GAAU,KAAA;AACd,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AACvC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACxB,IAAA,IAAI,EAAA,KAAO,GAAA,EAAK,OAAA,GAAU,CAAC,OAAA;AAC3B,IAAA,IAAI,EAAA,KAAO,GAAA,IAAO,CAAC,OAAA,EAAS,OAAO,CAAA;AAAA,EACrC;AACA,EAAA,OAAO,EAAA;AACT;AAEA,SAAS,kBAAkB,GAAA,EAAyB;AAClD,EAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,GAAG,CAAA,EAAG;AAE5B,IAAA,OAAO,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,GAAA,EAAK,GAAA,EAAK,SAAS,GAAA,EAAI;AAAA,EAChE;AACA,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,QAAA,CAAS,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACtC,OAAA,EAAS,QAAA,CAAS,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC,CAAA;AAAA,IACtC,KAAK,QAAA,CAAS,MAAA,CAAO,IAAA,CAAK,GAAG,CAAC,CAAA,IAAK,GAAA;AAAA,IACnC,OAAA,EAAS,QAAA,CAAS,UAAA,CAAW,IAAA,CAAK,GAAG,CAAC;AAAA,GACxC;AACF;AAEA,SAAS,qBAAA,CAAsB,SAAiB,SAAA,EAA4B;AAC1E,EAAA,MAAM,OAAA,GAAU,QAAQ,OAAO,CAAA;AAC/B,EAAA,IAAI,OAAA,KAAY,IAAI,OAAO,KAAA;AAC3B,EAAA,MAAM,CAAA,GAAI,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AAClC,EAAA,IAAI,CAAC,GAAG,OAAO,KAAA;AACf,EAAA,IAAI,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAAG,OAAO,IAAA;AAClC,EAAA,MAAM,OAAA,GAAA,CAAW,CAAA,CAAE,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AACzC,EAAA,OAAO,IAAI,MAAA,CAAO,CAAA,EAAA,EAAK,YAAA,CAAa,OAAO,CAAC,CAAA,KAAA,CAAA,EAAS,IAAI,CAAA,CAAE,IAAA,CAAK,SAAS,CAAA;AAC3E;AAOA,SAAS,4BAA4B,QAAA,EAAkC;AACrE,EAAA,MAAM,UAAwB,EAAC;AAC/B,EAAA,IAAI,UAAA,GAA4B,IAAA;AAEhC,EAAA,QAAA,CAAS,OAAA,CAAQ,CAAC,IAAA,EAAM,CAAA,KAAM;AAC5B,IAAA,IAAI,IAAA,GAAO,IAAA;AACX,IAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,IAAA,IAAI,CAAA,GAAI,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG;AAC3B,MAAA,MAAM,SAAA,GAAY,mBAAmB,IAAI,CAAA;AACzC,MAAA,IAAI,SAAA,EAAW;AACb,QAAA,IAAA,GAAO,SAAA,CAAU,IAAA;AACjB,QAAA,WAAA,GAAc,SAAA,CAAU,GAAA;AAAA,MAC1B;AAAA,IACF;AACA,IAAA,MAAM,OAAA,GAAU,QAAQ,IAAI,CAAA;AAC5B,IAAA,IAAI,YAAY,EAAA,EAAI;AAClB,MAAA,OAAA,CAAQ,IAAA,CAAK,EAAE,KAAA,EAAO,aAAA,CAAc,OAAO,CAAA,EAAG,SAAA,EAAW,YAAY,CAAA;AAAA,IACvE;AACA,IAAA,UAAA,GAAa,WAAA;AAAA,EACf,CAAC,CAAA;AAED,EAAA,OAAO,OAAA;AACT;AAGA,SAAS,mBAAmB,IAAA,EAAoD;AAC9E,EAAA,MAAM,OAAA,GAAU,SAAS,IAAI,CAAA;AAC7B,EAAA,MAAM,MAAM,OAAA,CAAQ,MAAA;AACpB,EAAA,IAAI,GAAA,KAAQ,KAAK,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAC,CAAA,KAAM,KAAK,OAAO,IAAA;AAEzD,EAAA,IAAI,OAAA,GAAU,EAAA;AACd,EAAA,KAAA,IAAS,IAAI,GAAA,GAAM,CAAA,EAAG,CAAA,IAAK,CAAA,EAAG,KAAK,CAAA,EAAG;AACpC,IAAA,MAAM,EAAA,GAAK,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA;AAC3B,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,OAAA,GAAU,CAAA;AACV,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,KAAO,KAAK,OAAO,IAAA;AAAA,EACzB;AACA,EAAA,IAAI,OAAA,KAAY,IAAI,OAAO,IAAA;AAE3B,EAAA,MAAM,QAAQ,OAAA,CAAQ,KAAA,CAAM,OAAA,GAAU,CAAA,EAAG,MAAM,CAAC,CAAA;AAChD,EAAA,MAAM,YAAA,GAAe,QAAQ,KAAK,CAAA;AAElC,EAAA,IAAI,YAAA,CAAa,UAAA,CAAW,GAAG,CAAA,IAAK,YAAA,CAAa,QAAA,CAAS,GAAG,CAAA,IAAK,gBAAA,CAAiB,IAAA,CAAK,YAAY,CAAA,EAAG;AACrG,IAAA,OAAO,IAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,MAAM,OAAA,CAAQ,KAAA,CAAM,GAAG,OAAO,CAAA,EAAG,KAAK,KAAA,EAAM;AACvD;AAEA,SAAS,SAAS,CAAA,EAA0C;AAC1D,EAAA,OAAO,CAAA,IAAK,CAAA,CAAE,CAAC,CAAA,KAAM,MAAA,GAAY,MAAA,CAAO,QAAA,CAAS,CAAA,CAAE,CAAC,CAAA,EAAG,EAAE,CAAA,GAAI,IAAA;AAC/D;AACA,SAAS,SAAS,CAAA,EAA0C;AAC1D,EAAA,OAAO,KAAK,CAAA,CAAE,CAAC,MAAM,MAAA,GAAY,CAAA,CAAE,CAAC,CAAA,GAAI,IAAA;AAC1C;AACA,SAAS,aAAa,CAAA,EAAmB;AACvC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,sBAAA,EAAwB,MAAM,CAAA;AACjD;AAKA,IAAM,YAAA,GAAe,oBAAA;AACrB,IAAM,YAAA,GAAe,oBAAA;AACrB,SAAS,QAAQ,CAAA,EAAmB;AAClC,EAAA,OAAO,EAAE,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA,CAAE,OAAA,CAAQ,cAAc,EAAE,CAAA;AAC7D;AACA,SAAS,SAAS,CAAA,EAAmB;AACnC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AACnC;AACA,SAAS,SAAS,CAAA,EAAmB;AACnC,EAAA,OAAO,CAAA,CAAE,OAAA,CAAQ,YAAA,EAAc,EAAE,CAAA;AACnC;AAMA,SAAS,iBAAA,CAAkB,IAAA,EAAc,OAAA,EAAiB,IAAA,EAAc,KAAA,EAAuB;AAC7F,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,IAAS,IAAI,OAAA,EAAS,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AAC7C,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACxB,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,KAAA,IAAS,CAAA;AAAA,IACX,CAAA,MAAA,IAAW,OAAO,KAAA,EAAO;AACvB,MAAA,KAAA,IAAS,CAAA;AACT,MAAA,IAAI,KAAA,KAAU,GAAG,OAAO,CAAA;AAAA,IAC1B;AAAA,EACF;AACA,EAAA,OAAO,EAAA;AACT;AAOO,SAAS,cAAc,KAAA,EAAyB;AACrD,EAAA,MAAM,QAAkB,EAAC;AACzB,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,IAAI,OAAA,GAAU,CAAA;AACd,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,MAAM,KAAA,EAAO;AACtB,IAAA,IAAI,EAAA,KAAO,KAAK,KAAA,IAAS,CAAA;AAAA,SAAA,IAChB,EAAA,KAAO,KAAK,KAAA,IAAS,CAAA;AAAA,SAAA,IACrB,EAAA,KAAO,KAAK,OAAA,IAAW,CAAA;AAAA,SAAA,IACvB,EAAA,KAAO,KAAK,OAAA,IAAW,CAAA;AAEhC,IAAA,IAAI,EAAA,KAAO,GAAA,IAAO,KAAA,KAAU,CAAA,IAAK,YAAY,CAAA,EAAG;AAC9C,MAAA,KAAA,CAAM,KAAK,GAAG,CAAA;AACd,MAAA,GAAA,GAAM,EAAA;AAAA,IACR,CAAA,MAAO;AACL,MAAA,GAAA,IAAO,EAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,KAAA,CAAM,KAAK,GAAG,CAAA;AACd,EAAA,OAAO,KAAA;AACT;AAOA,SAAS,kBAAkB,IAAA,EAAc,IAAA,GAAO,CAAA,EAAG,EAAA,GAAK,KAAK,MAAA,EAAgB;AAC3E,EAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,EAAA,KAAA,IAAS,CAAA,GAAI,IAAA,EAAM,CAAA,GAAI,EAAA,EAAI,KAAK,CAAA,EAAG;AACjC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACxB,IAAA,IAAI,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,EAAK;AAC5B,MAAA,KAAA,IAAS,CAAA;AAAA,IACX,CAAA,MAAA,IAAW,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,EAAK;AACnC,MAAA,IAAI,KAAA,GAAQ,GAAG,KAAA,IAAS,CAAA;AAAA,IAC1B,CAAA,MAAA,IAAW,EAAA,KAAO,GAAA,IAAO,KAAA,KAAU,CAAA,EAAG;AACpC,MAAA,OAAO,CAAA;AAAA,IACT;AAAA,EACF;AACA,EAAA,OAAO,EAAA;AACT;;;ACnfA,IAAMA,cAAAA,GAAgB,UAAA;AAiBf,SAAS,iBAAiB,IAAA,EAA6B;AAC5D,EAAA,MAAM,SAAwB,EAAC;AAC/B,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,OAAO,CAAA,GAAI,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,OAAA,CAAQA,cAAAA,EAAe,CAAC,CAAA;AAC3C,IAAA,IAAI,UAAU,EAAA,EAAI;AAElB,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,CAAA,GAAI,QAAQA,cAAAA,CAAc,MAAA;AAC9B,IAAA,OAAO,CAAA,GAAI,KAAK,MAAA,EAAQ;AACtB,MAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACxB,MAAA,IAAI,EAAA,KAAO,KAAK,KAAA,IAAS,CAAA;AAAA,WAAA,IAChB,OAAO,GAAA,EAAK;AACnB,QAAA,KAAA,IAAS,CAAA;AACT,QAAA,IAAI,UAAU,CAAA,EAAG;AAAA,MACnB;AACA,MAAA,CAAA,IAAK,CAAA;AAAA,IACP;AACA,IAAA,IAAI,UAAU,CAAA,EAAG;AACf,MAAA,CAAA,GAAI,QAAQA,cAAAA,CAAc,MAAA;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQA,cAAAA,CAAc,QAAQ,CAAC,CAAA;AACxD,IAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,GAAG,CAAA;AAC/B,IAAA,IAAI,UAAU,EAAA,EAAI;AAChB,MAAA,CAAA,GAAI,CAAA,GAAI,CAAA;AACR,MAAA;AAAA,IACF;AACA,IAAA,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,KAAK,CAAA,GAAI,CAAA,EAAG,WAAW,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,KAAK,GAAG,QAAA,EAAU,KAAA,CAAM,MAAM,KAAA,GAAQ,CAAC,GAAG,CAAA;AACrG,IAAA,CAAA,GAAI,CAAA,GAAI,CAAA;AAAA,EACV;AACA,EAAA,OAAO,MAAA;AACT;AAGO,SAAS,kBAAkB,MAAA,EAAwB;AACxD,EAAA,MAAM,KAAA,GAAQ,OAAO,WAAA,EAAY,CAAE,MAAM,MAAA,EAAQ,CAAC,EAAE,CAAC,CAAA;AACrD,EAAA,OAAO,KAAA,IAAS,EAAA;AAClB;AASO,SAAS,YAAY,QAAA,EAA0B;AACpD,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AACH,MAAA,OAAO,CAAA;AAAA,IACT;AACE,MAAA,OAAO,CAAA;AAAA;AAEb;AASO,IAAM,oBAAA,GAAuB,YAAY,EAAE,CAAA;AAW3C,SAAS,SAAA,CAAU,QAAA,EAAkB,CAAA,EAAW,KAAA,EAAkC;AACvF,EAAA,MAAM,GAAA,GAAM,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AACtB,EAAA,MAAM,QAAQ,GAAA,GAAM,EAAA;AACpB,EAAA,MAAM,SAAS,GAAA,GAAM,GAAA;AAErB,EAAA,QAAQ,QAAA;AAAU,IAChB,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AAAA,IACL,KAAK,IAAA;AACH,MAAA,IAAI,UAAU,CAAA,IAAK,MAAA,KAAW,IAAI,OAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AACrD,MAAA,IAAI,KAAA,IAAS,CAAA,IAAK,KAAA,IAAS,CAAA,KAAM,MAAA,GAAS,EAAA,IAAM,MAAA,GAAS,EAAA,CAAA,EAAK,OAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AACjF,MAAA,OAAO,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA;AAAA,IACrB;AACE,MAAA,OAAA,CAAQ,QAAQ,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,GAAI,KAAA,CAAM,CAAC,CAAA,KAAM,EAAA;AAAA;AAElD;;;ACxGA,IAAM,iBAAA,uBAAwB,GAAA,CAAI,CAAC,WAAW,SAAA,EAAW,KAAA,EAAO,SAAS,CAAC,CAAA;AAG1E,IAAM,UAAA,GAAa,8DAAA;AAOZ,SAAS,gBAAA,CAAiB,GAAA,EAAa,IAAA,GAAwB,EAAC,EAAiB;AACtF,EAAA,MAAM,cAA4B,EAAC;AACnC,EAAA,MAAM,IAAA,GAAO,cAAc,GAAG,CAAA;AAC9B,EAAA,MAAM,GAAA,GAAM,eAAe,IAAI,CAAA;AAE/B,EAAA,aAAA,CAAc,MAAM,WAAW,CAAA;AAC/B,EAAA,eAAA,CAAgB,MAAM,WAAW,CAAA;AACjC,EAAA,uBAAA,CAAwB,IAAA,EAAM,KAAK,WAAW,CAAA;AAC9C,EAAA,YAAA,CAAa,MAAM,GAAA,EAAK,IAAA,CAAK,MAAA,EAAQ,IAAA,CAAK,gBAAgB,WAAW,CAAA;AACrE,EAAA,uBAAA,CAAwB,IAAA,EAAM,GAAA,EAAK,IAAA,CAAK,cAAA,EAAgB,WAAW,CAAA;AACnE,EAAA,IAAI,IAAA,CAAK,aAAA,IAAiB,IAAA,CAAK,aAAA,CAAc,SAAS,CAAA,EAAG;AACvD,IAAA,mBAAA,CAAoB,IAAA,EAAM,GAAA,EAAK,IAAA,CAAK,aAAA,EAAe,WAAW,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,WAAA;AACT;AAKA,SAAS,GAAA,CAAI,IAAA,EAAc,OAAA,EAAiB,GAAA,EAAsB;AAChE,EAAA,OAAO,EAAE,QAAA,EAAU,OAAA,EAAS,IAAA,EAAM,OAAA,EAAS,GAAG,GAAA,EAAI;AACpD;AACA,SAAS,IAAA,CAAK,IAAA,EAAc,OAAA,EAAiB,GAAA,EAAsB;AACjE,EAAA,OAAO,EAAE,QAAA,EAAU,SAAA,EAAW,IAAA,EAAM,OAAA,EAAS,GAAG,GAAA,EAAI;AACtD;AASA,SAAS,eAAe,IAAA,EAAyB;AAC/C,EAAA,MAAM,MAAA,GAAS,CAAC,CAAC,CAAA;AACjB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AACvC,IAAA,IAAI,IAAA,CAAK,WAAW,CAAC,CAAA,KAAM,IAAI,MAAA,CAAO,IAAA,CAAK,IAAI,CAAC,CAAA;AAAA,EAClD;AACA,EAAA,OAAO,EAAE,MAAA,EAAQ,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAO;AACvC;AAGA,SAAS,eAAA,CAAgB,KAAgB,MAAA,EAAkD;AACzF,EAAA,MAAM,GAAA,GAAM,KAAK,GAAA,CAAI,IAAA,CAAK,IAAI,MAAA,EAAQ,CAAC,CAAA,EAAG,GAAA,CAAI,MAAM,CAAA;AACpD,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,GAAA,CAAI,MAAA,CAAO,MAAA,GAAS,CAAA;AAC7B,EAAA,OAAO,KAAK,EAAA,EAAI;AACd,IAAA,MAAM,GAAA,GAAO,EAAA,GAAK,EAAA,GAAK,CAAA,IAAM,CAAA;AAC7B,IAAA,IAAA,CAAK,IAAI,MAAA,CAAO,GAAG,CAAA,IAAK,CAAA,KAAM,KAAK,EAAA,GAAK,GAAA;AAAA,cAC9B,GAAA,GAAM,CAAA;AAAA,EAClB;AACA,EAAA,OAAO,EAAE,IAAA,EAAM,EAAA,GAAK,CAAA,EAAG,MAAA,EAAQ,GAAA,IAAO,GAAA,CAAI,MAAA,CAAO,EAAE,CAAA,IAAK,CAAA,CAAA,GAAK,CAAA,EAAE;AACjE;AAGA,SAAS,IAAA,CAAK,GAAA,EAAgB,MAAA,EAAgB,MAAA,EAAqB;AACjE,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,GAAA,EAAK,MAAM,CAAA;AACrC,EAAA,MAAM,CAAA,GAAI,eAAA,CAAgB,GAAA,EAAK,MAAA,GAAS,MAAM,CAAA;AAC9C,EAAA,OAAO,EAAE,IAAA,EAAM,CAAA,CAAE,IAAA,EAAM,MAAA,EAAQ,CAAA,CAAE,MAAA,EAAQ,OAAA,EAAS,CAAA,CAAE,IAAA,EAAM,SAAA,EAAW,CAAA,CAAE,MAAA,EAAO;AAChF;AAGA,SAAS,aAAA,CAAc,MAAc,GAAA,EAAyB;AAC5D,EAAA,MAAM,KAAA,GAAgC,EAAE,GAAA,EAAK,GAAA,EAAK,KAAK,GAAA,EAAI;AAC3D,EAAA,MAAM,QAA+E,EAAC;AACtF,EAAA,IAAI,IAAA,GAAO,CAAA;AACX,EAAA,IAAI,MAAA,GAAS,CAAA;AAEb,EAAA,KAAA,MAAW,MAAM,IAAA,EAAM;AACrB,IAAA,IAAI,OAAO,IAAA,EAAM;AACf,MAAA,IAAA,IAAQ,CAAA;AACR,MAAA,MAAA,GAAS,CAAA;AACT,MAAA;AAAA,IACF;AACA,IAAA,IAAI,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,EAAK;AAC5B,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,EAAA,EAAI,MAAA,EAAQ,MAAM,EAAE,CAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,IAC3D,CAAA,MAAA,IAAW,EAAA,KAAO,GAAA,IAAO,EAAA,KAAO,GAAA,EAAK;AACnC,MAAA,MAAM,GAAA,GAAM,MAAM,GAAA,EAAI;AACtB,MAAA,IAAI,QAAQ,MAAA,EAAW;AACrB,QAAA,GAAA,CAAI,IAAA,CAAK,IAAI,4BAAA,EAA8B,CAAA,oBAAA,EAAuB,EAAE,CAAA,EAAA,CAAA,EAAM,EAAE,MAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,SAAA,EAAW,MAAA,GAAS,GAAG,IAAA,EAAM,EAAE,SAAS,EAAA,EAAG,EAAG,CAAC,CAAA;AAAA,MAC1J,CAAA,MAAA,IAAW,GAAA,CAAI,MAAA,KAAW,EAAA,EAAI;AAC5B,QAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,oBAAA,EAAsB,CAAA,CAAA,EAAI,GAAA,CAAI,IAAI,CAAA,aAAA,EAAgB,EAAE,CAAA,EAAA,CAAA,EAAM,EAAE,IAAA,EAAM,MAAA,EAAQ,OAAA,EAAS,MAAM,SAAA,EAAW,MAAA,GAAS,CAAA,EAAG,IAAA,EAAM,EAAE,IAAA,EAAM,GAAA,CAAI,IAAA,EAAM,KAAA,EAAO,EAAA,EAAG,EAAG,CAAC,CAAA;AAAA,MACrK;AAAA,IACF;AACA,IAAA,MAAA,IAAU,CAAA;AAAA,EACZ;AAEA,EAAA,KAAA,MAAW,YAAY,KAAA,EAAO;AAC5B,IAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,kBAAA,EAAoB,CAAA,UAAA,EAAa,QAAA,CAAS,IAAI,CAAA,EAAA,CAAA,EAAM,EAAE,IAAA,EAAM,QAAA,CAAS,IAAA,EAAM,MAAA,EAAQ,QAAA,CAAS,MAAA,EAAQ,OAAA,EAAS,QAAA,CAAS,IAAA,EAAM,SAAA,EAAW,QAAA,CAAS,MAAA,GAAS,CAAA,EAAG,IAAA,EAAM,EAAE,OAAA,EAAS,QAAA,CAAS,IAAA,EAAK,EAAG,CAAC,CAAA;AAAA,EAC9M;AACF;AAWA,SAAS,eAAA,CAAgB,MAAc,GAAA,EAAyB;AAC9D,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,IAAI,CAAA;AAC7B,EAAA,KAAA,CAAM,OAAA,CAAQ,CAAC,QAAA,EAAU,GAAA,KAAQ;AAC/B,IAAA,MAAM,OAAA,GAAU,QAAA,CAAS,OAAA,CAAQ,SAAA,EAAW,EAAE,CAAA;AAC9C,IAAA,MAAM,IAAA,GAAQ,CAAC,MAAA,EAAQ,MAAM,CAAA,CAAY,IAAA;AAAA,MACvC,CAAC,SAAA,KAAc,OAAA,CAAQ,UAAA,CAAW,CAAA,EAAG,SAAS,CAAA,CAAA,CAAG,CAAA,IAAK,OAAA,CAAQ,UAAA,CAAW,CAAA,EAAG,SAAS,CAAA,CAAA,CAAI;AAAA,KAC3F;AACA,IAAA,IAAI,CAAC,IAAA,EAAM;AAEX,IAAA,YAAA,CAAa,SAAA,GAAY,CAAA;AACzB,IAAA,IAAI,CAAC,YAAA,CAAa,IAAA,CAAK,OAAO,CAAA,EAAG;AAC/B,MAAA,MAAM,MAAA,GAAS,QAAA,CAAS,MAAA,GAAS,OAAA,CAAQ,MAAA,GAAS,CAAA;AAClD,MAAA,MAAM,OAAO,GAAA,GAAM,CAAA;AACnB,MAAA,MAAM,IAAA,GAAO,IAAA,KAAS,MAAA,GAAS,eAAA,GAAkB,eAAA;AACjD,MAAA,GAAA,CAAI,KAAK,GAAA,CAAI,IAAA,EAAM,aAAa,IAAI,CAAA,YAAA,EAAe,IAAI,CAAA,eAAA,CAAA,EAAmB,EAAE,IAAA,EAAM,MAAA,EAAQ,SAAS,IAAA,EAAM,SAAA,EAAW,SAAS,MAAA,GAAS,CAAA,EAAG,CAAC,CAAA;AAAA,IAC5I;AAAA,EACF,CAAC,CAAA;AAED,EAAA,MAAM,EAAE,WAAA,EAAY,GAAI,iBAAA,CAAkB,IAAI,CAAA;AAC9C,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAoB;AAErC,EAAA,KAAA,MAAW,cAAc,WAAA,EAAa;AAIpC,IAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA;AACtC,IAAA,IAAI,UAAU,MAAA,EAAW;AACvB,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QACP,2BAAA;AAAA,QACA,CAAA,UAAA,EAAa,UAAA,CAAW,IAAI,CAAA,2CAAA,EAA8C,KAAK,CAAA,yCAAA,CAAA;AAAA,QAC/E,EAAE,IAAA,EAAM,UAAA,CAAW,IAAA,EAAM,QAAQ,CAAA;AAAE,OACpC,CAAA;AAAA,IACH,CAAA,MAAO;AACL,MAAA,IAAA,CAAK,GAAA,CAAI,UAAA,CAAW,IAAA,EAAM,UAAA,CAAW,IAAI,CAAA;AAAA,IAC3C;AAKA,IAAA,IAAI,WAAW,IAAA,KAAS,KAAA,IAAS,cAAc,IAAA,CAAK,UAAA,CAAW,KAAK,CAAA,EAAG;AACrE,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QACP,sBAAA;AAAA,QACA,CAAA,yCAAA,EAA4C,WAAW,IAAI,CAAA,0FAAA,CAAA;AAAA,QAC3D,EAAE,IAAA,EAAM,UAAA,CAAW,IAAA,EAAM,QAAQ,CAAA;AAAE,OACpC,CAAA;AAAA,IACH;AAAA,EACF;AACF;AAGA,SAAS,uBAAA,CAAwB,IAAA,EAAc,GAAA,EAAgB,GAAA,EAAyB;AACtF,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,gBAAgB,CAAA,EAAG;AAC/C,IAAA,MAAM,SAAA,GAAY,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AAC1B,IAAA,IAAI,CAAC,SAAA,CAAU,IAAA,CAAK,SAAS,CAAA,EAAG;AAChC,IAAA,MAAM,UAAA,GAAA,CAAc,CAAA,CAAE,KAAA,IAAS,CAAA,IAAK,CAAA;AAEpC,IAAA,KAAA,MAAW,EAAA,IAAM,SAAA,CAAU,QAAA,CAAS,aAAa,CAAA,EAAG;AAClD,MAAA,MAAM,GAAA,GAAA,CAAO,EAAA,CAAG,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AACtC,MAAA,IAAI,CAAC,iBAAA,CAAkB,GAAA,CAAI,GAAG,CAAA,EAAG;AAC/B,QAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,UAAI,yBAAA;AAAA,UAA2B,CAAA,iCAAA,EAAoC,EAAA,CAAG,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,UAC/E,EAAE,GAAG,IAAA,CAAK,GAAA,EAAK,cAAc,EAAA,CAAG,KAAA,IAAS,KAAK,EAAA,CAAG,CAAC,KAAK,EAAA,EAAI,MAAM,GAAG,IAAA,EAAM,EAAE,KAAK,EAAA,CAAG,CAAC,GAAE;AAAE,SAAE,CAAA;AAAA,MAC/F;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,2BAAA,CAA4B,IAAA,CAAK,SAAS,CAAA;AACtD,IAAA,IAAI,GAAA,IAAO,CAAC,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,IAAK,EAAE,CAAA,EAAG;AACtC,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QAAI,iCAAA;AAAA,QAAmC,CAAA,yCAAA,EAA4C,GAAA,CAAI,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,QAChG,EAAE,GAAG,IAAA,CAAK,KAAK,UAAA,GAAa,GAAA,CAAI,OAAO,GAAA,CAAI,CAAC,CAAA,CAAE,MAAM,GAAG,IAAA,EAAM,EAAE,OAAO,GAAA,CAAI,CAAC,GAAE;AAAE,OAAE,CAAA;AAAA,IACrF;AACA,IAAA,MAAM,GAAA,GAAM,2BAAA,CAA4B,IAAA,CAAK,SAAS,CAAA;AACtD,IAAA,IAAI,GAAA,IAAO,CAAC,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,IAAK,EAAE,CAAA,EAAG;AACtC,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QAAI,iCAAA;AAAA,QAAmC,CAAA,yCAAA,EAA4C,GAAA,CAAI,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,QAChG,EAAE,GAAG,IAAA,CAAK,KAAK,UAAA,GAAa,GAAA,CAAI,OAAO,GAAA,CAAI,CAAC,CAAA,CAAE,MAAM,GAAG,IAAA,EAAM,EAAE,OAAO,GAAA,CAAI,CAAC,GAAE;AAAE,OAAE,CAAA;AAAA,IACrF;AAAA,EACF;AACF;AAGA,SAAS,YAAA,CACP,IAAA,EACA,GAAA,EACA,MAAA,EACA,gBACA,GAAA,EACM;AAGN,EAAA,MAAM,OAAO,MAAA,IAAU,MAAA,KAAW,EAAA,GAAK,iBAAA,CAAkB,MAAM,CAAA,GAAI,EAAA;AACnE,EAAA,MAAM,KAAA,GAAQ,IAAA,KAAS,EAAA,GAAK,WAAA,CAAY,IAAI,CAAA,GAAI,CAAA;AAEhD,EAAA,MAAM,OAAA,GAAU,kBAAkB,IAAI,CAAA;AACtC,EAAA,MAAM,EAAE,OAAA,EAAS,MAAA,EAAQ,SAAS,IAAA,EAAK,GAAI,kBAAkB,IAAI,CAAA;AAIjE,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAA,CAAK,cAAA,IAAkB,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AAE5E,EAAA,KAAA,MAAW,KAAA,IAAS,gBAAA,CAAiB,IAAI,CAAA,EAAG;AAC1C,IAAA,MAAM,EAAA,GAAK,KAAK,GAAA,EAAK,KAAA,CAAM,OAAO,KAAA,CAAM,GAAA,GAAM,MAAM,KAAK,CAAA;AAKzD,IAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,SAAA,CAAU,QAAA,CAAS,WAAW,CAAA,EAAG;AACrD,MAAA,MAAM,IAAA,GAAA,CAAQ,CAAA,CAAE,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AACtC,MAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACxB,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QACP,oBAAA;AAAA,QACA,CAAA,yBAAA,EAA4B,CAAA,CAAE,CAAC,CAAC,CAAA,yIAAA,CAAA;AAAA,QAChC;AAAA,OACD,CAAA;AAAA,IACH;AAEA,IAAA,IAAI,SAAA,CAAU,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,EAAG;AAClC,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,wBAAA,EAA0B,sKAAA,EAAmK,EAAE,CAAC,CAAA;AAC7M,MAAA;AAAA,IACF;AAQA,IAAA,MAAM,WAAW,sBAAA,CAAuB,KAAA,CAAM,QAAA,EAAU,IAAA,EAAM,QAAQ,SAAS,CAAA;AAK/E,IAAA,IAAI,SAAS,kBAAA,EAAoB;AAC/B,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,wBAAA,EAA0B,sKAAA,EAAmK,EAAE,CAAC,CAAA;AAC7M,MAAA;AAAA,IACF;AAKA,IAAA,IAAI,SAAS,UAAA,EAAY;AAEzB,IAAA,MAAM,QAAQ,QAAA,CAAS,KAAA;AACvB,IAAA,IAAI,QAAQ,CAAA,EAAG;AACb,MAAA,IAAI,UAAU,KAAA,EAAO;AACnB,QAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,UAAI,cAAA;AAAA,UAAgB,CAAA,uBAAA,EAA0B,KAAK,CAAA,YAAA,EAAe,KAAK,CAAA,CAAA,CAAA;AAAA,UAC9E,EAAE,GAAG,EAAA,EAAI,IAAA,EAAM,EAAE,QAAA,EAAU,KAAA,EAAO,GAAA,EAAK,KAAA,EAAM;AAAE,SAAE,CAAA;AAAA,MACrD;AAAA,IACF,CAAA,MAAA,IAAW,UAAU,oBAAA,EAAsB;AAWzC,MAAA,MAAM,QAAA,GAAW,MAAA,KAAW,MAAA,IAAa,MAAA,KAAW,EAAA;AACpD,MAAA,GAAA,CAAI,IAAA,CAAK,IAAA;AAAA,QACP,uBAAA;AAAA,QACA,QAAA,GACI,CAAA,cAAA,EAAiB,KAAK,CAAA,wBAAA,EAA2B,MAAM,CAAA,6EAAA,EACD,oBAAoB,CAAA,oFAAA,CAAA,GAE1E,CAAA,cAAA,EAAiB,KAAK,CAAA,uDAAA,EACnB,oBAAoB,CAAA,oFAAA,CAAA;AAAA,QAC3B;AAAA,UACE,GAAG,EAAA;AAAA,UACH,IAAA,EAAM;AAAA,YACJ,GAAA,EAAK,KAAA;AAAA,YACL,YAAA,EAAc,oBAAA;AAAA,YACd,GAAI,QAAA,GAAW,EAAE,MAAA,KAAW;AAAC;AAC/B;AACF,OACD,CAAA;AAAA,IACH;AAAA,EACF;AACF;AAgBA,IAAM,yBAAA,GAA4B,cAAA;AAkBlC,IAAM,WAAA,GAAc,UAAA;AAWpB,IAAM,qBAAA,GAAwB,EAAA;AAc9B,IAAM,4BAA4B,EAAA,GAAK,IAAA;AA6BvC,SAAS,sBAAA,CACP,QAAA,EACA,IAAA,EACA,MAAA,EACA,SAAA,EACqE;AACrE,EAAA,MAAM,OAAA,GAAU,CACd,kBAAA,GAAqB,KAAA,MACoD;AAAA,IACzE,KAAA,EAAO,CAAA;AAAA,IACP,UAAA,EAAY,IAAA;AAAA,IACZ;AAAA,GACF,CAAA;AAMA,EAAA,MAAM,SAAA,uBAAgB,GAAA,EAAY;AAClC,EAAA,MAAM,SAAS,CAACC,KAAAA,KACd,CAAC,GAAGA,KAAAA,CAAK,SAAS,WAAW,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,CAAA,KAAA,CAAO,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA,EAAI,aAAa,CAAA;AAcvE,EAAA,MAAM,UAAA,GAAa,CAAC,MAAA,KAAoD;AACtE,IAAA,MAAM,KAAA,GAAyC,CAAC,EAAE,IAAA,EAAM,OAAO,MAAM,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA;AAE9E,IAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,MAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AACpC,MAAA,IAAI,KAAA,CAAM,CAAA,IAAK,KAAA,CAAM,IAAA,CAAK,MAAA,EAAQ;AAChC,QAAA,KAAA,CAAM,GAAA,EAAI;AACV,QAAA;AAAA,MACF;AACA,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,CAAA;AAGjC,MAAA,IAAI,KAAK,IAAI,CAAA,KAAM,UAAa,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AACrD,MAAA,MAAM,KAAA,GAAQ,OAAO,IAAI,CAAA;AACzB,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AAChD,MAAA,SAAA,CAAU,IAAI,IAAI,CAAA;AAKlB,MAAA,IAAI,OAAA,CAAQ,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,QAAA;AAChC,MAAA,IAAI,WAAA,CAAY,IAAA,CAAK,KAAK,CAAA,EAAG,OAAO,UAAA;AACpC,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,CAAO,KAAK,CAAA,EAAG,CAAA,EAAG,GAAG,CAAA;AAAA,IAC1C;AAEA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AACA,EAAA,MAAM,QAAA,GAAW,WAAW,QAAQ,CAAA;AACpC,EAAA,IAAI,QAAA,KAAa,UAAA,EAAY,OAAO,OAAA,CAAQ,IAAI,CAAA;AAChD,EAAA,IAAI,QAAA,KAAa,QAAA,EAAU,OAAO,OAAA,EAAQ;AAE1C,EAAA,IAAI,IAAA,GAAO,QAAA;AACX,EAAA,MAAM,MAAA,GAAS,SAAS,MAAA,GAAS,yBAAA;AACjC,EAAA,KAAA,IAAS,IAAA,GAAO,CAAA,EAAG,IAAA,GAAO,qBAAA,EAAuB,IAAA,EAAA,EAAQ;AACvD,IAAA,IAAI,YAAA,GAAe,KAAA;AACnB,IAAA,IAAI,MAAA,GAAS,KAAA;AASb,IAAA,MAAM,QAAkB,EAAC;AACzB,IAAA,IAAI,KAAA,GAAQ,CAAA;AACZ,IAAA,IAAI,MAAA,GAAS,CAAA;AACb,IAAA,MAAM,EAAA,GAAK,WAAA;AACX,IAAA,IAAI,CAAA;AACJ,IAAA,OAAA,CAAQ,CAAA,GAAI,EAAA,CAAG,IAAA,CAAK,IAAI,OAAO,IAAA,EAAM;AACnC,MAAA,YAAA,GAAe,IAAA;AACf,MAAA,MAAM,IAAA,GAAA,CAAQ,CAAA,CAAE,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AAGtC,MAAA,MAAM,KAAA,GAAQ,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,GAAI,SAAY,IAAA,CAAK,IAAI,CAAA,IAAK,MAAA,CAAO,IAAI,CAAA;AAGzE,MAAA,IAAI,KAAA,KAAU,MAAA,IAAa,WAAA,CAAY,IAAA,CAAK,KAAK,CAAA,EAAG;AAClD,QAAA,MAAA,GAAS,IAAA;AACT,QAAA;AAAA,MACF;AACA,MAAA,KAAA,CAAM,KAAK,IAAA,CAAK,KAAA,CAAM,QAAQ,CAAA,CAAE,KAAK,GAAG,KAAK,CAAA;AAC7C,MAAA,KAAA,IAAS,CAAA,CAAE,KAAA,GAAQ,MAAA,GAAS,KAAA,CAAM,MAAA;AAClC,MAAA,MAAA,GAAS,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,CAAC,CAAA,CAAE,MAAA;AACxB,MAAA,IAAI,KAAA,GAAQ,MAAA,EAAQ,OAAO,OAAA,EAAQ;AAAA,IACrC;AAEA,IAAA,IAAI,MAAA,SAAe,OAAA,EAAQ;AAC3B,IAAA,KAAA,CAAM,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,MAAM,CAAC,CAAA;AAC7B,IAAA,KAAA,IAAS,KAAK,MAAA,GAAS,MAAA;AACvB,IAAA,IAAI,KAAA,GAAQ,MAAA,EAAQ,OAAO,OAAA,EAAQ;AACnC,IAAA,IAAA,GAAO,KAAA,CAAM,KAAK,EAAE,CAAA;AAEpB,IAAA,IAAI,CAAC,YAAA,EAAc;AAEjB,MAAA,OAAO,EAAE,KAAA,EAAO,IAAA,CAAK,KAAA,CAAM,GAAG,EAAE,MAAA,EAAQ,UAAA,EAAY,KAAA,EAAO,kBAAA,EAAoB,KAAA,EAAM;AAAA,IACvF;AAAA,EACF;AAEA,EAAA,OAAO,OAAA,EAAQ;AACjB;AAEA,SAAS,kBAAkB,IAAA,EAA2B;AACpD,EAAA,MAAM,MAAA,GAAS,iBAAA,CAAkB,IAAI,CAAA,CAAE,OAAA;AACvC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAChC,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClD,IAAA,IAAI,yBAAA,CAA0B,IAAA,CAAK,KAAK,CAAA,EAAG;AACzC,MAAA,OAAA,CAAQ,IAAI,IAAI,CAAA;AAChB,MAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,IACjB;AAAA,EACF;AAIA,EAAA,MAAM,UAAA,uBAAiB,GAAA,EAAsB;AAC7C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClD,IAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3C,MAAA,MAAM,GAAA,GAAA,CAAO,CAAA,CAAE,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AACrC,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,GAAA,CAAI,GAAG,CAAA;AAC/B,MAAA,IAAI,SAAS,MAAA,EAAW,UAAA,CAAW,IAAI,GAAA,EAAK,CAAC,IAAI,CAAC,CAAA;AAAA,WAC7C,IAAA,CAAK,KAAK,IAAI,CAAA;AAAA,IACrB;AAAA,EACF;AACA,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,MAAA,GAAS,MAAM,GAAA,EAAI;AACzB,IAAA,KAAA,MAAW,QAAQ,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA,IAAK,EAAC,EAAG;AAC/C,MAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA,EAAG;AACtB,QAAA,OAAA,CAAQ,IAAI,IAAI,CAAA;AAChB,QAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;AAGA,SAAS,uBAAA,CAAwB,IAAA,EAAc,GAAA,EAAgB,KAAA,EAAsC,GAAA,EAAyB;AAC5H,EAAA,MAAM,QAAA,GAAW,IAAI,GAAA,CAAA,CAAK,KAAA,IAAS,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,EAAa,CAAC,CAAA;AAGlE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAoB;AACrC,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAiB;AACpC,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,wDAAwD,CAAA,EAAG;AACvF,IAAA,MAAM,IAAA,GAAA,CAAQ,CAAA,CAAE,CAAC,CAAA,IAAK,IAAI,WAAA,EAAY;AACtC,IAAA,IAAA,CAAK,GAAA,CAAI,IAAA,EAAM,CAAA,CAAE,CAAC,KAAK,EAAE,CAAA;AACzB,IAAA,MAAM,UAAA,GAAA,CAAc,EAAE,KAAA,IAAS,CAAA,IAAK,EAAE,CAAC,CAAA,CAAE,QAAQ,GAAG,CAAA;AACpD,IAAA,MAAA,CAAO,GAAA,CAAI,MAAM,IAAA,CAAK,GAAA,EAAK,YAAY,IAAA,CAAK,MAAA,GAAS,CAAC,CAAC,CAAA;AAAA,EACzD;AAEA,EAAA,MAAM,SAAA,GAAiB,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAC5C,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,IAAA,EAAM;AAChC,IAAA,IAAI,MAAM,WAAA,EAAY,CAAE,SAAS,CAAA,CAAA,EAAI,IAAI,GAAG,CAAA,EAAG;AAC7C,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,yBAAA,EAA2B,CAAA,UAAA,EAAa,IAAI,CAAA,oBAAA,CAAA,EAAwB,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,IAAK,SAAS,CAAC,CAAA;AAAA,IACjH;AAAA,EACF;AAIA,EAAA,MAAM,MAAA,uBAAa,GAAA,EAAsB;AACzC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,CAAA,IAAK,IAAA,EAAM;AAChC,IAAA,MAAM,OAAiB,EAAC;AACxB,IAAA,KAAA,MAAW,CAAA,IAAK,KAAA,CAAM,QAAA,CAAS,WAAW,CAAA,EAAG,IAAA,CAAK,IAAA,CAAA,CAAM,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA,EAAI,WAAA,EAAa,CAAA;AACjF,IAAA,MAAA,CAAO,GAAA,CAAI,MAAM,IAAI,CAAA;AAAA,EACvB;AAEA,EAAA,MAAM,YAAA,GAAe,oBAAA,CAAqB,IAAA,EAAM,MAAM,CAAA;AACtD,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,IAAA,EAAK,EAAG;AAC9B,IAAA,WAAA,CAAY,IAAA,EAAM,MAAM,MAAA,EAAQ,YAAA,EAAc,OAAO,GAAA,CAAI,IAAI,CAAA,IAAK,SAAA,EAAW,GAAG,CAAA;AAAA,EAClF;AAIA,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,oDAAA,EAAsD,CAAC,MAAM,CAAA,CAAE,OAAA,CAAQ,QAAA,EAAU,GAAG,CAAC,CAAA;AAC/G,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,EAAc,MAAA,EAAgB,MAAA,KAAyB;AAC1E,IAAA,MAAM,GAAA,GAAM,KAAK,WAAA,EAAY;AAC7B,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,IAAK,QAAA,CAAS,GAAA,CAAI,GAAG,CAAA,IAAK,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AACzD,IAAA,IAAA,CAAK,IAAI,GAAG,CAAA;AACZ,IAAA,GAAA,CAAI,IAAA,CAAK,IAAA;AAAA,MAAK,oBAAA;AAAA,MAAsB,aAAa,IAAI,CAAA,kDAAA,CAAA;AAAA,MACnD,EAAE,GAAG,IAAA,CAAK,GAAA,EAAK,MAAA,EAAQ,MAAM,CAAA,EAAG,IAAA,EAAM,EAAE,IAAA,EAAK;AAAE,KAAE,CAAA;AAAA,EACrD,CAAA;AACA,EAAA,KAAA,MAAW,KAAK,IAAA,CAAK,QAAA,CAAS,WAAW,CAAA,cAAe,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA,EAAI,EAAE,KAAA,IAAS,CAAA,EAAG,CAAA,CAAE,CAAC,EAAE,MAAM,CAAA;AAC7F,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,0BAA0B,CAAA,EAAG;AACzD,IAAA,WAAA,CAAY,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA,EAAA,CAAK,EAAE,KAAA,IAAS,CAAA,IAAK,EAAE,CAAC,CAAA,CAAE,QAAQ,CAAA,CAAE,CAAC,KAAK,EAAE,CAAA,EAAA,CAAI,EAAE,CAAC,CAAA,IAAK,IAAI,MAAM,CAAA;AAAA,EACxF;AACF;AAeA,SAAS,oBAAA,CAAqB,MAA2B,MAAA,EAA4C;AACnG,EAAA,MAAM,IAAA,GAAO,CAAA;AACb,EAAA,MAAM,KAAA,GAAQ,CAAA;AACd,EAAA,MAAM,KAAA,uBAAY,GAAA,EAAoB;AACtC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAY;AAGhC,EAAA,KAAA,MAAW,IAAA,IAAQ,IAAA,CAAK,IAAA,EAAK,EAAG;AAC9B,IAAA,IAAI,KAAA,CAAM,GAAA,CAAI,IAAI,CAAA,EAAG;AACrB,IAAA,MAAM,KAAA,GAAiB,CAAC,EAAE,IAAA,EAAM,MAAM,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,IAAK,EAAC,EAAG,CAAA,EAAG,GAAG,CAAA;AAC1E,IAAA,KAAA,CAAM,GAAA,CAAI,MAAM,IAAI,CAAA;AACpB,IAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,MAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AAClC,MAAA,IAAI,GAAA,CAAI,CAAA,GAAI,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ;AAC3B,QAAA,MAAM,GAAA,GAAM,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AAC1B,QAAA,GAAA,CAAI,CAAA,IAAK,CAAA;AACT,QAAA,IAAI,QAAQ,GAAA,CAAI,IAAA,IAAQ,CAAC,IAAA,CAAK,GAAA,CAAI,GAAG,CAAA,EAAG;AACxC,QAAA,MAAM,CAAA,GAAI,KAAA,CAAM,GAAA,CAAI,GAAG,CAAA;AACvB,QAAA,IAAI,CAAA,KAAM,IAAA,EAAM,OAAA,CAAQ,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,aAAA,IAC3B,MAAM,KAAA,EAAO;AAAE,UAAA,IAAI,QAAQ,GAAA,CAAI,GAAG,GAAG,OAAA,CAAQ,GAAA,CAAI,IAAI,IAAI,CAAA;AAAA,QAAG,CAAA,MAChE;AACH,UAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,IAAK,EAAC,EAAG,CAAA,EAAG,GAAG,CAAA;AAC3D,UAAA,KAAA,CAAM,GAAA,CAAI,KAAK,IAAI,CAAA;AAAA,QACrB;AAAA,MACF,CAAA,MAAO;AACL,QAAA,KAAA,CAAM,GAAA,EAAI;AACV,QAAA,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,KAAK,CAAA;AACzB,QAAA,IAAI,KAAA,CAAM,MAAA,GAAS,CAAA,IAAK,OAAA,CAAQ,IAAI,GAAA,CAAI,IAAI,CAAA,EAAG,OAAA,CAAQ,IAAI,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,EAAG,IAAI,CAAA;AAAA,MAC1F;AAAA,IACF;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;AAWA,SAAS,YACP,IAAA,EACA,IAAA,EACA,MAAA,EACA,YAAA,EACA,SACA,GAAA,EACM;AACN,EAAA,IAAI,CAAC,YAAA,CAAa,GAAA,CAAI,IAAI,CAAA,EAAG;AAG7B,EAAA,MAAM,IAAA,GAAiB,CAAC,IAAI,CAAA;AAC5B,EAAA,MAAM,MAAA,mBAAS,IAAI,GAAA,CAAY,CAAC,IAAI,CAAC,CAAA;AACrC,EAAA,MAAM,KAAA,GAAiB,CAAC,EAAE,IAAA,EAAM,MAAM,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,IAAI,CAAA,IAAK,EAAC,EAAG,CAAA,EAAG,GAAG,CAAA;AAE1E,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAuB;AACpC,IAAA,KAAA,CAAM,GAAA,EAAI;AACV,IAAA,MAAA,CAAO,MAAA,CAAO,MAAM,IAAI,CAAA;AACxB,IAAA,IAAA,CAAK,GAAA,EAAI;AAAA,EACX,CAAA;AAEA,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,KAAA,CAAM,MAAA,GAAS,CAAC,CAAA;AAClC,IAAA,IAAI,GAAA,CAAI,CAAA,IAAK,GAAA,CAAI,IAAA,CAAK,MAAA,EAAQ;AAC5B,MAAA,KAAA,CAAM,GAAG,CAAA;AACT,MAAA;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA;AAC1B,IAAA,GAAA,CAAI,CAAA,IAAK,CAAA;AACT,IAAA,IAAI,GAAA,KAAQ,IAAI,IAAA,EAAM;AACtB,IAAA,IAAI,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,EAAG;AACnB,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA,CAAI,6BAAA,EAA+B,CAAA,6BAAA,EAAgC,CAAC,GAAG,IAAA,EAAM,GAAG,CAAA,CAAE,IAAA,CAAK,UAAK,CAAC,CAAA,CAAA,CAAA,EAAK,OAAO,CAAC,CAAA;AACnH,MAAA,KAAA,CAAM,GAAG,CAAA;AACT,MAAA;AAAA,IACF;AACA,IAAA,IAAI,KAAK,GAAA,CAAI,GAAG,KAAK,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,EAAG;AAC1C,MAAA,KAAA,CAAM,IAAA,CAAK,EAAE,IAAA,EAAM,GAAA,EAAK,IAAA,EAAM,MAAA,CAAO,GAAA,CAAI,GAAG,CAAA,IAAK,EAAC,EAAG,CAAA,EAAG,GAAG,CAAA;AAC3D,MAAA,MAAA,CAAO,IAAI,GAAG,CAAA;AACd,MAAA,IAAA,CAAK,KAAK,GAAG,CAAA;AAAA,IACf;AAAA,EACF;AACF;AAGA,SAAS,mBAAA,CAAoB,IAAA,EAAc,GAAA,EAAgB,KAAA,EAA0B,GAAA,EAAyB;AAC5G,EAAA,MAAM,GAAA,GAAM,IAAI,GAAA,CAAI,KAAK,CAAA;AACzB,EAAA,UAAA,CAAW,SAAA,GAAY,CAAA;AACvB,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,UAAU,CAAA,EAAG;AACzC,IAAA,MAAM,GAAA,GAAM,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AACpB,IAAA,IAAI,CAAC,GAAA,CAAI,GAAA,CAAI,GAAG,CAAA,EAAG;AACjB,MAAA,MAAM,SAAA,GAAA,CAAa,EAAE,KAAA,IAAS,CAAA,IAAK,EAAE,CAAC,CAAA,CAAE,OAAA,CAAQ,GAAG,CAAA,GAAI,CAAA;AACvD,MAAA,GAAA,CAAI,IAAA,CAAK,GAAA;AAAA,QAAI,wBAAA;AAAA,QAA0B,oBAAoB,GAAG,CAAA,oCAAA,CAAA;AAAA,QAC5D,EAAE,GAAG,IAAA,CAAK,GAAA,EAAK,SAAA,EAAW,GAAA,CAAI,MAAM,CAAA,EAAG,IAAA,EAAM,EAAE,MAAA,EAAQ,GAAA,EAAI;AAAE,OAAE,CAAA;AAAA,IACnE;AAAA,EACF;AACF;;;ACpqBA,IAAM,UAAA,GAAa,oCAAA;AACnB,IAAM,UAAA,GAAa,oCAAA;AACnB,IAAM,iBAAA,GAAoB,0CAAA;AAG1B,IAAMC,WAAAA,GAAa,8DAAA;AACnB,IAAMC,YAAAA,GAAc,WAAA;AACpB,IAAM,kBAAA,GAAqB,0BAAA;AAEpB,SAAS,kBAAkB,GAAA,EAA4B;AAC5D,EAAA,MAAM,IAAA,GAAO,cAAc,GAAG,CAAA;AAE9B,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,EAAM,UAAA,EAAY,IAAI,CAAA;AAC3C,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,IAAA,EAAM,UAAA,EAAY,IAAI,CAAA;AAC3C,EAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,EAAMD,WAAAA,EAAY,KAAK,CAAA;AAIhD,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,iBAAA,EAAmB,EAAE,CAAA;AAC/C,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAA,CAAO,IAAA,EAAM,IAAA,EAAMC,YAAAA,EAAa,IAAI,CAAA;AACpC,EAAA,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,kBAAA,EAAoB,IAAI,CAAA;AAE3C,EAAA,OAAO,EAAE,MAAM,CAAC,GAAG,IAAI,CAAA,EAAG,IAAA,EAAM,MAAM,QAAA,EAAS;AACjD;AAEA,SAAS,OAAA,CAAQ,IAAA,EAAc,EAAA,EAAY,IAAA,EAAyB;AAClE,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAA,CAAO,IAAA,EAAM,IAAA,EAAM,EAAA,EAAI,IAAI,CAAA;AAC3B,EAAA,OAAO,CAAC,GAAG,IAAI,CAAA;AACjB;AAEA,SAAS,MAAA,CAAO,MAAA,EAAqB,IAAA,EAAc,EAAA,EAAY,IAAA,EAAqB;AAClF,EAAA,KAAA,MAAW,CAAA,IAAK,IAAA,CAAK,QAAA,CAAS,EAAE,CAAA,EAAG;AACjC,IAAA,MAAM,KAAA,GAAQ,EAAE,CAAC,CAAA;AACjB,IAAA,IAAI,KAAA,KAAU,MAAA,IAAa,KAAA,KAAU,EAAA,EAAI,MAAA,CAAO,IAAI,IAAA,GAAO,KAAA,CAAM,WAAA,EAAY,GAAI,KAAK,CAAA;AAAA,EACxF;AACF;;;AC7DO,IAAM,YAAA,GAAN,cAA2B,KAAA,CAAM;AAAA,EACtC,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,cAAA;AAAA,EACd;AACF;AAGO,IAAM,oBAAA,GAAN,cAAmC,YAAA,CAAa;AAAA,EACrD,WAAA,CAAY,SAAiB,OAAA,EAA+B;AAC1D,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,sBAAA;AACZ,IAAA,IAAI,OAAA,IAAW,WAAW,OAAA,EAAS;AACjC,MAAC,IAAA,CAA6B,QAAQ,OAAA,CAAQ,KAAA;AAAA,IAChD;AAAA,EACF;AACF;AASO,IAAM,eAAA,GAAN,cAA8B,YAAA,CAAa;AAAA,EAChD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAGO,IAAM,mBAAA,GAAN,cAAkC,YAAA,CAAa;AAAA,EACpD,YAAY,IAAA,EAAc;AACxB,IAAA,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,wBAAA,CAA0B,CAAA;AACvC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;;;AChBA,IAAM,kBAAA,GAAqB,EAAA;AAK3B,IAAM,eAAA,GAAkB,8DAAA;AA4CjB,SAAS,SAAA,CAAU,KAAgB,GAAA,EAAwB;AAChE,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,GAAA,CAAI,OAAA,EAAS,IAAI,cAAc,CAAA;AACtD,EAAA,MAAM,QAAA,GAAW;AAAA,IACf,KAAK,GAAA,CAAI,GAAA;AAAA,IACT,QAAQ,GAAA,CAAI,MAAA;AAAA,IACZ,KAAA,EAAO,CAAA;AAAA,IACP,eAAe,GAAA,CAAI;AAAA,GACrB;AAGA,EAAA,MAAM,IAAA,GACJ,OAAO,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,CAAE,MAAA,GAAS,IAC9B,EAAE,GAAG,MAAM,GAAG,eAAA,CAAgB,IAAI,OAAA,EAAS,IAAA,EAAM,IAAI,cAAA,EAAgB,QAAQ,GAAE,GAC/E,IAAA;AACN,EAAA,MAAM,IAAA,GAAO,YAAY,GAAA,CAAI,KAAA,EAAO,EAAE,GAAG,QAAA,EAAU,MAAM,CAAA;AACzD,EAAA,OAAO,GAAA,CAAI,QAAA,GAAW,eAAA,CAAgB,IAAA,EAAM,GAAG,CAAA,GAAI,IAAA;AACrD;AAcA,SAAS,eAAA,CAAgB,MAAc,GAAA,EAAwB;AAC7D,EAAA,eAAA,CAAgB,SAAA,GAAY,CAAA;AAC5B,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,eAAA,EAAiB,CAAC,IAAI,GAAA,KAAwB;AAChE,IAAA,IAAI,GAAA,CAAI,YAAA,CAAa,QAAA,CAAS,GAAG,CAAA,IAAK,IAAI,YAAA,CAAa,MAAA,IAAU,GAAA,CAAI,QAAA,EAAU,OAAO,EAAA;AACtF,IAAA,IAAI,QAAA;AACJ,IAAA,IAAI;AACF,MAAA,QAAA,GAAW,GAAA,CAAI,SAAU,GAAG,CAAA;AAAA,IAC9B,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,oBAAA,CAAqB,CAAA,2BAAA,EAA8B,GAAG,CAAA,CAAA,CAAA,EAAK,EAAE,OAAO,CAAA;AAAA,IAChF;AACA,IAAA,IAAI,QAAA,KAAa,MAAM,OAAO,EAAA;AAC9B,IAAA,OAAO,SAAA,CAAU,aAAA,CAAc,QAAQ,CAAA,EAAG;AAAA,MACxC,GAAG,GAAA;AAAA,MACH,gBAAgB,GAAA,CAAI,cAAA;AAAA;AAAA,MACpB,YAAA,EAAc,CAAC,GAAG,GAAA,CAAI,cAAc,GAAG;AAAA,KACxC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAsBO,SAAS,SAAA,CACd,SACA,OAAA,EACwB;AACxB,EAAA,MAAM,OAA+B,EAAC;AACtC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACnD,IAAA,IAAA,CAAK,IAAI,CAAA,GAAI,KAAA;AAAA,EACf;AACA,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACnD,IAAA,IAAA,CAAK,IAAA,CAAK,WAAA,EAAa,CAAA,GAAI,KAAA;AAAA,EAC7B;AACA,EAAA,OAAO,IAAA;AACT;AAcO,SAAS,eAAA,CACd,OAAA,EACA,IAAA,EACA,OAAA,EACA,IAAA,EACwB;AACxB,EAAA,MAAM,SAAA,GAAY,IAAI,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,GAAA,CAAI,CAAC,GAAA,KAAQ,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AAC9E,EAAA,MAAM,SAAiC,EAAC;AAMxC,EAAA,MAAM,UAAkC,EAAC;AACzC,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,IAAI,CAAA,EAAG;AAChD,IAAA,IAAI,QAAQ,OAAA,IAAW,CAAC,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AAC7C,IAAA,OAAA,CAAQ,IAAI,CAAA,GAAI,KAAA;AAAA,EAClB;AAEA,EAAA,KAAA,MAAW,IAAA,IAAQ,gBAAA,CAAiB,OAAA,EAAS,OAAO,CAAA,EAAG;AACrD,IAAA,IAAI,SAAA,CAAU,GAAA,CAAI,IAAI,CAAA,EAAG;AACzB,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,IAAI,CAAA,IAAK,EAAA;AAC/B,IAAA,MAAA,CAAO,IAAI,CAAA,GAAI,WAAA,CAAY,aAAA,CAAc,KAAK,GAAG,EAAE,GAAG,IAAA,EAAM,IAAA,EAAM,EAAE,GAAG,IAAA,EAAM,GAAG,MAAA,IAAU,CAAA;AAAA,EAC5F;AAEA,EAAA,OAAO,MAAA;AACT;AAGA,SAAS,gBAAA,CACP,SACA,OAAA,EACU;AACV,EAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA;AACjC,EAAA,MAAM,OAAA,uBAAc,GAAA,EAAyB;AAE7C,EAAA,KAAA,MAAW,QAAQ,KAAA,EAAO;AACxB,IAAA,MAAM,UAAU,eAAA,CAAgB,OAAA,CAAQ,IAAI,CAAA,IAAK,IAAI,OAAO,CAAA;AAC5D,IAAA,OAAA,CAAQ,GAAA,CAAI,IAAA,EAAM,IAAI,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,CAAC,SAAA,KAAc,OAAA,CAAQ,GAAA,CAAI,SAAS,CAAC,CAAC,CAAC,CAAA;AAAA,EAChF;AAEA,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,IAAI,OAAA,GAAU,KAAA;AAEd,EAAA,OAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzB,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,MAAA,CAAO,CAAC,IAAA,KAAS;AACrC,MAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAC7B,MAAA,OAAO,CAAC,IAAA,IAAQ,CAAC,CAAC,GAAG,IAAI,CAAA,CAAE,IAAA,CAAK,CAAC,QAAQ,GAAA,KAAQ,IAAA,IAAQ,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAC,CAAA;AAAA,IAChF,CAAC,CAAA;AACD,IAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG,OAAO,CAAC,GAAG,OAAA,EAAS,GAAG,OAAO,CAAA;AACtD,IAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,KAAK,CAAA;AACrB,IAAA,OAAA,GAAU,OAAA,CAAQ,OAAO,CAAC,IAAA,KAAS,CAAC,KAAA,CAAM,QAAA,CAAS,IAAI,CAAC,CAAA;AAAA,EAC1D;AAEA,EAAA,OAAO,OAAA;AACT;AAGA,SAAS,eAAA,CAAgB,OAAe,OAAA,EAAwD;AAC9F,EAAA,MAAM,IAAA,uBAAW,GAAA,EAAY;AAC7B,EAAA,MAAM,KAAA,GAAQ,iBAAiB,KAAK,CAAA;AAEpC,EAAA,OAAO,KAAA,CAAM,SAAS,CAAA,EAAG;AACvB,IAAA,MAAM,IAAA,GAAO,MAAM,KAAA,EAAM;AACzB,IAAA,IAAI,IAAA,CAAK,GAAA,CAAI,IAAI,CAAA,EAAG;AACpB,IAAA,IAAA,CAAK,IAAI,IAAI,CAAA;AACb,IAAA,MAAM,KAAA,GAAQ,QAAQ,IAAI,CAAA;AAC1B,IAAA,IAAI,UAAU,MAAA,EAAW,KAAA,CAAM,KAAK,GAAG,gBAAA,CAAiB,KAAK,CAAC,CAAA;AAAA,EAChE;AAEA,EAAA,OAAO,IAAA;AACT;AAGA,SAAS,iBAAiB,IAAA,EAAwB;AAChD,EAAA,OAAO,CAAC,GAAG,IAAA,CAAK,QAAA,CAAS,WAAW,CAAC,CAAA,CAAE,GAAA,CAAI,CAAC,WAAW,KAAA,CAAM,CAAC,CAAA,IAAK,EAAA,EAAI,aAAa,CAAA;AACtF;AAEO,SAAS,WAAA,CAAY,OAAwB,IAAA,EAAqC;AACvF,EAAA,IAAI,GAAA,GAAM,EAAA;AACV,EAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,GAAA,IAAO,UAAA,CAAW,MAAM,IAAI,CAAA;AACtD,EAAA,OAAO,GAAA;AACT;AAEA,SAAS,UAAA,CAAW,MAAY,IAAA,EAAqC;AACnE,EAAA,QAAQ,KAAK,IAAA;AAAM,IACjB,KAAK,SAAA;AACH,MAAA,OAAO,IAAA,CAAK,KAAA;AAAA,IACd,KAAK,UAAA;AACH,MAAA,OAAO,eAAA,CAAgB,IAAA,CAAK,IAAA,EAAM,IAAI,CAAA;AAAA,IACxC,KAAK,aAAA;AACH,MAAA,OAAO,iBAAA,CAAkB,IAAA,CAAK,OAAA,EAAS,IAAI,CAAA;AAAA,IAC7C,KAAK,aAAA;AACH,MAAA,OAAO,iBAAA,CAAkB,MAAM,IAAI,CAAA;AAAA,IACrC,KAAK,aAAA;AACH,MAAA,OAAO,iBAAA,CAAkB,MAAM,IAAI,CAAA;AAAA,IACrC,KAAK,QAAA;AACH,MAAA,OAAO,YAAA,CAAa,MAAM,IAAI,CAAA;AAAA;AAEpC;AAGA,SAAS,SAAA,CAAU,GAAA,EAAU,GAAA,EAAa,GAAA,EAAqB;AAC7D,EAAA,OAAO,GAAA,KAAQ,GAAA,GAAM,GAAA,GAAM,GAAA,CAAI,KAAK,GAAG,CAAA;AACzC;AAOA,SAAS,eAAA,CAAgB,MAAc,IAAA,EAAqC;AAC1E,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA;AAC1C,EAAA,IAAI,KAAA,KAAU,MAAA,EAAW,OAAO,CAAA,CAAA,EAAI,IAAI,CAAA,CAAA,CAAA;AAGxC,EAAA,IAAI,IAAA,CAAK,SAAS,kBAAA,IAAsB,CAAC,SAAS,IAAA,CAAK,KAAK,GAAG,OAAO,KAAA;AAGtE,EAAA,OAAO,WAAA,CAAY,aAAA,CAAc,KAAK,CAAA,EAAG,EAAE,GAAG,IAAA,EAAM,KAAA,EAAO,IAAA,CAAK,KAAA,GAAQ,CAAA,EAAG,CAAA;AAC7E;AAGA,SAAS,cAAA,CAAe,MAAc,IAAA,EAAqC;AACzE,EAAA,IAAI,GAAA,GAAM,IAAA;AACV,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,kBAAA,EAAoB,KAAK,CAAA,EAAG;AAC9C,IAAA,IAAI,OAAA,GAAU,KAAA;AACd,IAAA,GAAA,GAAM,GAAA,CAAI,OAAA,CAAQ,WAAA,EAAa,CAAC,GAAG,IAAA,KAAyB;AAC1D,MAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA;AAC1C,MAAA,IAAI,KAAA,KAAU,QAAW,OAAO,CAAA;AAChC,MAAA,OAAA,GAAU,IAAA;AACV,MAAA,OAAO,KAAA;AAAA,IACT,CAAC,CAAA;AACD,IAAA,IAAI,CAAC,OAAA,EAAS;AAAA,EAChB;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,oBAAA,CAAqB,IAAA,EAAc,QAAA,EAAmB,IAAA,EAAsC;AACnG,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,aAAa,CAAA;AAC1C,EAAA,MAAM,UAAA,GAAa,KAAA,KAAU,MAAA,IAAa,KAAA,CAAM,KAAK,KAAK,CAAA;AAC1D,EAAA,OAAO,QAAA,GAAW,CAAC,UAAA,GAAa,UAAA;AAClC;AAEA,SAAS,iBAAA,CAAkB,MAAuB,IAAA,EAAqC;AACrF,EAAA,MAAM,SAAS,oBAAA,CAAqB,IAAA,CAAK,IAAA,EAAM,IAAA,CAAK,UAAU,IAAI,CAAA;AAClE,EAAA,OAAO,YAAY,MAAA,GAAS,IAAA,CAAK,IAAA,GAAO,IAAA,CAAK,MAAM,IAAI,CAAA;AACzD;AA8BA,SAAS,wBAAA,CAAyB,MAAc,IAAA,EAAqC;AACnF,EAAA,IAAI,CAAC,IAAA,CAAK,QAAA,CAAS,IAAI,GAAG,OAAO,IAAA;AAEjC,EAAA,MAAM,KAAA,GAAQ,YAAY,IAAI,CAAA;AAC9B,EAAA,MAAM,MAAgB,EAAC;AAIvB,EAAA,MAAM,UAA8B,CAAC,CAAC,CAAA,EAAG,IAAA,CAAK,MAAM,CAAC,CAAA;AAErD,EAAA,OAAO,OAAA,CAAQ,SAAS,CAAA,EAAG;AACzB,IAAA,MAAM,OAAA,GAAU,QAAQ,GAAA,EAAI;AAC5B,IAAA,MAAM,MAAA,GAAS,QAAQ,CAAC,CAAA;AACxB,IAAA,IAAI,CAAA,GAAI,QAAQ,CAAC,CAAA;AAEjB,IAAA,OAAO,IAAI,MAAA,EAAQ;AACjB,MAAA,MAAM,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,CAAC,CAAA;AAEjC,MAAA,IAAI,IAAA,KAAS,EAAA,IAAM,IAAA,GAAO,CAAA,IAAK,MAAA,EAAQ;AACrC,QAAA,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,MAAM,CAAC,CAAA;AAC9B,QAAA;AAAA,MACF;AAIA,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,IAAI,CAAA,IAAK,EAAA;AAC5B,MAAA,MAAM,IAAA,GAAO,IAAA,KAAS,EAAA,IAAM,IAAA,IAAQ,MAAA,GAAS,OAAO,oBAAA,CAAqB,IAAA,EAAM,IAAA,GAAO,CAAA,EAAG,IAAI,CAAA;AAC7F,MAAA,IAAI,SAAS,IAAA,EAAM;AAGjB,QAAA,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAA,CAAK,IAAI,IAAA,GAAO,CAAA,EAAG,MAAM,CAAC,CAAC,CAAA;AAClD,QAAA,CAAA,GAAI,IAAA,GAAO,CAAA;AACX,QAAA;AAAA,MACF;AAEA,MAAA,GAAA,CAAI,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,CAAA,EAAG,IAAI,CAAC,CAAA;AAC5B,MAAA,MAAM,SAAA,GAAY,IAAA,CAAK,QAAA,GAAW,CAAA,GAAI,OAAO,IAAA,CAAK,QAAA;AAClD,MAAA,MAAM,CAAC,IAAA,EAAM,EAAE,CAAA,GAAI,oBAAA,CAAqB,KAAK,IAAA,EAAM,IAAA,CAAK,QAAA,EAAU,IAAI,CAAA,GAClE,CAAC,KAAK,SAAA,EAAW,SAAS,CAAA,GAC1B,CAAC,IAAA,CAAK,QAAA,GAAW,IAAI,IAAA,GAAO,IAAA,CAAK,QAAA,GAAW,CAAA,EAAG,IAAI,CAAA;AAGvD,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,IAAA,GAAO,CAAA,EAAG,MAAM,CAAC,CAAA;AAC/B,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAC,IAAA,EAAM,EAAE,CAAC,CAAA;AACvB,MAAA;AAAA,IACF;AAAA,EACF;AAEA,EAAA,OAAO,GAAA,CAAI,KAAK,EAAE,CAAA;AACpB;AAYA,SAAS,YAAY,IAAA,EAA0B;AAC7C,EAAA,MAAM,QAAQ,IAAI,UAAA,CAAW,KAAK,MAAM,CAAA,CAAE,KAAK,EAAE,CAAA;AACjD,EAAA,MAAM,QAAkB,EAAC;AAEzB,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,IAAA,CAAK,MAAA,EAAQ,KAAK,CAAA,EAAG;AACvC,IAAA,MAAM,EAAA,GAAK,IAAA,CAAK,MAAA,CAAO,CAAC,CAAA;AACxB,IAAA,IAAI,OAAO,GAAA,EAAK;AACd,MAAA,KAAA,CAAM,KAAK,CAAC,CAAA;AAAA,IACd,CAAA,MAAA,IAAW,OAAO,GAAA,EAAK;AACrB,MAAA,MAAM,IAAA,GAAO,MAAM,GAAA,EAAI;AACvB,MAAA,IAAI,IAAA,KAAS,MAAA,EAAW,KAAA,CAAM,IAAI,CAAA,GAAI,CAAA;AAAA,IACxC;AAAA,EACF;AAEA,EAAA,OAAO,KAAA;AACT;AASA,SAAS,YAAA,CAAa,MAAkB,IAAA,EAAqC;AAC3E,EAAA,MAAM,WAAW,wBAAA,CAAyB,cAAA,CAAe,KAAK,QAAA,EAAU,IAAI,GAAG,IAAI,CAAA;AACnF,EAAA,MAAM,QAAA,GAAW,cAAA,CAAe,IAAA,CAAK,QAAA,EAAU,IAAI,CAAA;AACnD,EAAA,MAAM,IAAA,GAAO,iBAAA,CAAkB,IAAA,CAAK,MAAM,CAAA;AAC1C,EAAA,MAAM,MAAA,GAAS,CAAC,KAAA,KAA6B,IAAA,CAAK,gBAAgB,KAAK,CAAA;AAEvE,EAAA,IAAI,UAAA,CAAW,IAAA,CAAK,QAAQ,CAAA,EAAG;AAC7B,IAAA,MAAA,CAAO;AAAA,MACL,IAAA,EAAM,wBAAA;AAAA,MACN,OAAA,EACE,2JAAA;AAAA,MAEF,SAAA,EAAW,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA;AAAA,MAC1C,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,OAAO,iBAAA,CAAkB,UAAU,QAAQ,CAAA;AAAA,EAC7C;AAEA,EAAA,MAAM,KAAA,GAAQC,SAAQ,QAAQ,CAAA;AAC9B,EAAA,IAAI,CAAC,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA,EAAG;AAG3B,IAAA,MAAA,CAAO;AAAA,MACL,IAAA,EAAM,cAAA;AAAA,MACN,OAAA,EAAS,CAAA,2CAAA,EAA8C,IAAA,CAAK,SAAA,CAAU,KAAK,CAAC,CAAA,gBAAA,CAAA;AAAA,MAC5E,SAAA,EAAW,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA;AAAA,MAC1C,MAAA,EAAQ;AAAA,KACT,CAAA;AACD,IAAA,OAAO,EAAA;AAAA,EACT;AAEA,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,KAAA,CAAM,GAAG,CAAA,CAAE,IAAI,CAAC,CAAA,KAAMA,QAAAA,CAAQ,CAAC,CAAC,CAAA;AACvD,EAAA,IAAI,KAAA,CAAM,MAAA,KAAW,WAAA,CAAY,IAAI,CAAA,EAAG;AACtC,IAAA,MAAA,CAAO;AAAA,MACL,IAAA,EAAM,cAAA;AAAA,MACN,OAAA,EAAS,cAAc,KAAA,CAAM,MAAM,qBAAqB,IAAI,CAAA,QAAA,EAAW,WAAA,CAAY,IAAI,CAAC,CAAA,CAAA,CAAA;AAAA,MACxF,SAAA,EAAW,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA;AAAA,MAC1C,MAAA,EAAQ,IAAA;AAAA,MACR,QAAA,EAAU,YAAY,IAAI,CAAA;AAAA,MAC1B,KAAK,KAAA,CAAM;AAAA,KACZ,CAAA;AACD,IAAA,OAAO,iBAAA,CAAkB,UAAU,QAAQ,CAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,MAAA,GAAS,UAAU,IAAA,EAAM,MAAA,CAAO,SAAS,KAAA,EAAO,EAAE,GAAG,KAAK,CAAA;AAChE,EAAA,OAAO,WAAA,CAAY,aAAA,CAAc,MAAM,CAAA,EAAG,IAAI,CAAA;AAChD;AAGA,SAAS,YAAA,CAAa,UAAkB,QAAA,EAA0B;AAChE,EAAA,OAAO,CAAA,QAAA,EAAW,QAAQ,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA,CAAA;AACxC;AAGA,SAAS,iBAAA,CAAkB,UAAkB,QAAA,EAA0B;AACrE,EAAA,OAAO,YAAA,CAAa,QAAA,EAAU,QAAQ,CAAA,CAAE,OAAA,CAAQ,QAAQ,QAAG,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,QAAG,CAAA;AAClF;AAGA,SAAS,iBAAA,CAAkB,SAAuC,IAAA,EAAqC;AACrG,EAAA,IAAI,OAAA,CAAQ,MAAA,KAAW,CAAA,EAAG,OAAO,EAAA;AACjC,EAAA,MAAM,MAAA,GAAS,QAAQ,SAAA,CAAU,IAAA,CAAK,KAAK,CAAA,EAAG,OAAA,CAAQ,MAAA,GAAS,CAAC,CAAC,CAAA;AACjE,EAAA,OAAO,MAAA,GAAS,WAAA,CAAY,MAAA,EAAQ,IAAI,CAAA,GAAI,EAAA;AAC9C;AAOA,SAAS,iBAAA,CAAkB,MAAuB,IAAA,EAAqC;AACrF,EAAA,MAAM,QAAA,GAAsB,IAAA,CAAK,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACnD,IAAA,EAAM,WAAA,CAAY,CAAA,CAAE,KAAA,EAAO,IAAI,CAAA;AAAA,IAC/B,KAAK,CAAA,CAAE;AAAA,GACT,CAAE,CAAA;AACF,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA;AACvB,EAAA,IAAI,KAAA,KAAU,GAAG,OAAO,EAAA;AAExB,EAAA,MAAM,EAAE,QAAO,GAAI,IAAA;AACnB,EAAA,MAAM,MAAA,GAAS,OAAO,OAAA,KAAY,IAAA;AAClC,EAAA,MAAM,MAAA,GAAS,OAAO,OAAA,KAAY,IAAA;AAClC,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,GAAA;AACJ,EAAA,IAAI,UAAU,MAAA,EAAQ;AACpB,IAAA,GAAA,GAAM,MAAA,CAAO,OAAA;AACb,IAAA,GAAA,GAAM,MAAA,CAAO,OAAA;AAAA,EACf,WAAW,MAAA,EAAQ;AACjB,IAAA,GAAA,GAAM,MAAA,CAAO,OAAA;AACb,IAAA,GAAA,GAAM,KAAA;AAAA,EACR,WAAW,MAAA,EAAQ;AACjB,IAAA,GAAA,GAAM,CAAA;AACN,IAAA,GAAA,GAAM,MAAA,CAAO,OAAA;AAAA,EACf,CAAA,MAAO;AACL,IAAA,GAAA,GAAM,KAAA;AACN,IAAA,GAAA,GAAM,KAAA;AAAA,EACR;AACA,EAAA,GAAA,GAAM,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AACtC,EAAA,GAAA,GAAM,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,GAAA,CAAI,GAAA,EAAK,KAAK,CAAC,CAAA;AAExC,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,IAAA,CAAK,GAAA,EAAK,KAAK,GAAG,CAAA;AACzC,EAAA,OAAA,CAAQ,QAAA,EAAU,KAAK,GAAG,CAAA;AAC1B,EAAA,OAAO,kBAAA,CAAmB,QAAA,CAAS,KAAA,CAAM,CAAA,EAAG,IAAI,CAAA,EAAG,MAAA,CAAO,GAAA,EAAK,MAAA,CAAO,OAAA,IAAW,MAAA,CAAO,GAAG,CAAA;AAC7F;AAGA,SAAS,OAAA,CAAQ,KAAgB,GAAA,EAAgB;AAC/C,EAAA,KAAA,IAAS,IAAI,GAAA,CAAI,MAAA,GAAS,GAAG,CAAA,GAAI,CAAA,EAAG,KAAK,CAAA,EAAG;AAC1C,IAAA,MAAM,CAAA,GAAI,SAAA,CAAU,GAAA,EAAK,CAAA,EAAG,CAAC,CAAA;AAC7B,IAAA,MAAM,GAAA,GAAM,IAAI,CAAC,CAAA;AACjB,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,CAAC,CAAA;AACd,IAAA,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA;AAAA,EACX;AACF;AAEA,SAAS,kBAAA,CAAmB,QAAA,EAA8B,SAAA,EAAmB,aAAA,EAA+B;AAC1G,EAAA,MAAM,QAAQ,QAAA,CAAS,MAAA;AACvB,EAAA,IAAI,KAAA,KAAU,GAAG,OAAO,EAAA;AACxB,EAAA,IAAI,KAAA,KAAU,CAAA,EAAG,OAAQ,QAAA,CAAS,CAAC,CAAA,CAAc,IAAA;AAEjD,EAAA,IAAI,GAAA,GAAO,QAAA,CAAS,CAAC,CAAA,CAAc,IAAA;AACnC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,KAAA,EAAO,KAAK,CAAA,EAAG;AACjC,IAAA,MAAM,EAAA,GAAK,SAAS,CAAC,CAAA;AACrB,IAAA,MAAM,MAAM,EAAA,CAAG,GAAA,KAAQ,CAAA,KAAM,KAAA,GAAQ,IAAI,aAAA,GAAgB,SAAA,CAAA;AACzD,IAAA,GAAA,IAAO,YAAA,CAAa,GAAG,CAAA,GAAI,EAAA,CAAG,IAAA;AAAA,EAChC;AACA,EAAA,OAAO,GAAA;AACT;AAGA,SAAS,aAAa,GAAA,EAAqB;AACzC,EAAA,MAAM,OAAA,GAAUA,SAAQ,GAAG,CAAA;AAC3B,EAAA,IAAI,OAAA,KAAY,IAAI,OAAO,GAAA;AAC3B,EAAA,IAAI,YAAY,IAAA,CAAK,OAAO,CAAA,EAAG,OAAO,IAAI,OAAO,CAAA,CAAA,CAAA;AACjD,EAAA,OAAO,GAAA;AACT;AAEA,IAAMC,aAAAA,GAAe,oBAAA;AACrB,IAAMC,aAAAA,GAAe,oBAAA;AACrB,SAASF,SAAQ,CAAA,EAAmB;AAClC,EAAA,OAAO,EAAE,OAAA,CAAQC,aAAAA,EAAc,EAAE,CAAA,CAAE,OAAA,CAAQC,eAAc,EAAE,CAAA;AAC7D;;;ACpjBA,IAAM,cAAA,GAAiB;AAAA;AAAA,EAErB,oBAAA;AAAA,EAAO,cAAA;AAAA,EAAM,cAAA;AAAA,EAAM,cAAA;AAAA,EAAM,cAAA;AAAA,EAAM,cAAA;AAAA,EAAM,cAAA;AAAA,EAAM,oBAAA;AAAA,EAAO,QAAA;AAAA,EAAK,QAAA;AAAA,EAAK,oBAAA;AAAA,EAAO,oBAAA;AAAA,EACnE,oBAAA;AAAA,EAAO,oBAAA;AAAA,EAAO,0BAAA;AAAA,EAAQ,0BAAA;AAAA,EAAQ,oBAAA;AAAA,EAAO,0BAAA;AAAA,EAAQ,0BAAA;AAAA,EAAQ,oBAAA;AAAA,EAAO,oBAAA;AAAA,EAAO,0BAAA;AAAA,EACnE,oBAAA;AAAA,EAAO,0BAAA;AAAA,EAAQ,oBAAA;AAAA,EAAO,oBAAA;AAAA,EAAO,0BAAA;AAAA,EAAQ,oBAAA;AAAA,EAAO,0BAAA;AAAA;AAAA,EAE5C,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,KAAA;AAAA,EAAO,IAAA;AAAA,EACxE,MAAA;AAAA,EAAQ,IAAA;AAAA,EAAM,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO;AAC7B,CAAA;AAKA,IAAM,EAAA,GAAK,oBAAA;AACX,IAAM,CAAA,GAAI,IAAI,EAAE,CAAA,CAAA,CAAA;AAEhB,IAAM,WAAA,GACJ,kHAAA;AAwBF,IAAM,QAAA,GAAW,UAAU,EAAE,CAAA,SAAA,CAAA;AAC7B,IAAM,SAAS,IAAI,MAAA,CAAO,CAAA,yCAAA,EAA4C,QAAQ,KAAK,KAAK,CAAA;AAGxF,IAAM,iBAAA,GAAoB,oBAAA;AAC1B,IAAM,WAAW,IAAI,MAAA,CAAO,CAAA,iBAAA,EAAoB,WAAW,OAAO,KAAK,CAAA;AACvE,IAAM,YAAY,IAAI,MAAA,CAAO,CAAA,GAAA,EAAM,WAAW,OAAO,KAAK,CAAA;AAC1D,IAAM,UAAA,GAAa,gBAAA;AACnB,IAAM,gBAAgB,IAAI,MAAA,CAAO,CAAA,oBAAA,EAAuB,CAAC,UAAU,IAAI,CAAA;AACvE,IAAM,cAAA,GAAiB,IAAI,MAAA,CAAO,CAAA,sBAAA,EAAyB,cAAA,CAAe,IAAA,CAAK,GAAG,CAAC,CAAA,OAAA,EAAU,CAAC,CAAA,KAAA,CAAA,EAAS,KAAK,CAAA;AAC5G,IAAM,iBAAA,GAAoB,cAAA;AAgB1B,IAAM,gBAAA,GAAmB,UAAA;AAUzB,IAAM,IAAA,GAAO,CAAA,YAAA,EAAe,gBAAgB,CAAA,EAAA,EAAK,CAAC,CAAA,EAAA,CAAA;AAGlD,IAAM,wBAAwB,IAAI,MAAA,CAAO,CAAA,EAAG,CAAC,eAAe,IAAI,CAAA;AAChE,IAAM,uBAAuB,IAAI,MAAA,CAAO,CAAA,iBAAA,EAAoB,CAAC,SAAS,IAAI,CAAA;AAK1E,IAAM,0BAA0B,IAAI,MAAA,CAAO,CAAA,2BAAA,EAA8B,CAAC,SAAS,IAAI,CAAA;AAGvF,IAAM,qBAAA,GAAwB,IAAI,MAAA,CAAO,CAAA,EAAA,EAAK,gBAAgB,CAAA,EAAA,EAAK,CAAC,KAAK,IAAI,CAAA;AAC7E,IAAM,eAAe,IAAI,MAAA,CAAO,CAAA,EAAA,EAAK,IAAI,cAAc,GAAG,CAAA;AAC1D,IAAM,wBAAwB,IAAI,MAAA,CAAO,CAAA,cAAA,EAAY,IAAI,cAAc,IAAI,CAAA;AAC3E,IAAM,qBAAqB,IAAI,MAAA;AAAA,EAC7B,mDAAmD,IAAI,CAAA,UAAA,CAAA;AAAA,EACvD;AACF,CAAA;AACA,IAAM,qBAAqB,IAAI,MAAA,CAAO,CAAA,IAAA,EAAO,IAAI,cAAc,IAAI,CAAA;AAEnE,IAAM,EAAA,GAAK,CAAC,EAAA,KAAuB,EAAA,CAAG,WAAA,EAAY;AAKlD,IAAM,kBAAkB,CAAC,KAAA,EAAO,OAAO,OAAA,EAAS,KAAA,EAAO,OAAO,MAAM,CAAA;AAEpE,IAAMC,WAAAA,GAAa,IAAI,MAAA,CAAO,CAAA,QAAA,EAAW,gBAAgB,IAAA,CAAK,GAAG,CAAC,CAAA,WAAA,CAAA,EAAe,IAAI,CAAA;AAsCrF,SAAS,OAAA,CAAQ,IAAA,EAAc,KAAA,EAAe,YAAA,EAA2C;AACvF,EAAA,IAAI,CAAC,KAAA,CAAM,QAAA,CAAS,IAAM,CAAA,EAAG;AAC3B,IAAA,OAAO,IAAA,CAAK,QAAQA,WAAAA,EAAY,CAAC,QAAQ,YAAA,CAAa,GAAA,CAAI,GAAG,CAAA,IAAK,GAAG,CAAA;AAAA,EACvE;AACA,EAAA,IAAI,GAAA,GAAM,IAAA;AACV,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,YAAA,EAAc;AACvC,IAAA,GAAA,GAAM,GAAA,CAAI,KAAA,CAAM,GAAG,CAAA,CAAE,KAAK,KAAK,CAAA;AAAA,EACjC;AACA,EAAA,OAAO,GAAA;AACT;AAEO,SAAS,YAAY,KAAA,EAAuB;AACjD,EAAA,MAAM,YAAA,uBAAmB,GAAA,EAAoB;AAC7C,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,EAAe,MAAA,KAAiC;AAC7D,IAAA,MAAM,GAAA,GAAM,CAAA,EAAA,EAAO,MAAM,CAAA,CAAA,EAAI,OAAO,CAAA,EAAA,CAAA;AACpC,IAAA,YAAA,CAAa,GAAA,CAAI,KAAK,KAAK,CAAA;AAC3B,IAAA,OAAA,IAAW,CAAA;AACX,IAAA,OAAO,GAAA;AAAA,EACT,CAAA;AACA,EAAA,MAAM,sBAAA,GAAyB,CAAC,KAAA,EAAe,MAAA,KAAiC;AAC9E,IAAA,MAAM,CAAA,GAAI,iBAAA,CAAkB,IAAA,CAAK,KAAK,CAAA;AACtC,IAAA,IAAI,CAAA,EAAG;AACL,MAAA,MAAM,MAAA,GAAS,CAAA,CAAE,CAAC,CAAA,IAAK,EAAA;AACvB,MAAA,MAAM,OAAO,KAAA,CAAM,KAAA,CAAM,GAAG,KAAA,CAAM,MAAA,GAAS,OAAO,MAAM,CAAA;AACxD,MAAA,OAAO,SAAS,EAAA,GAAK,MAAA,GAAS,KAAA,CAAM,IAAA,EAAM,MAAM,CAAA,GAAI,MAAA;AAAA,IACtD;AACA,IAAA,OAAO,KAAA,CAAM,OAAO,MAAM,CAAA;AAAA,EAC5B,CAAA;AAEA,EAAA,IAAI,IAAA,GAAO,KAAA;AAKX,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA;AAAA,IAAQ,MAAA;AAAA,IAAQ,CAAC,MAC3B,sBAAA,CAAuB,CAAA,EAAG,kBAAkB,IAAA,CAAK,CAAC,CAAA,GAAI,KAAA,GAAQ,KAAK;AAAA,GACrE;AACA,EAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,QAAA,EAAU,CAAC,MAAM,KAAA,CAAM,CAAA,EAAG,OAAO,CAAC,CAAA;AACtD,EAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,SAAA,EAAW,CAAC,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAC,CAAA;AACrD,EAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,UAAA,EAAY,CAAC,MAAM,KAAA,CAAM,CAAA,EAAG,KAAK,CAAC,CAAA;AACtD,EAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,aAAA,EAAe,CAAC,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAC,CAAA;AAC1D,EAAA,IAAA,GAAO,IAAA,CAAK,QAAQ,cAAA,EAAgB,CAAC,MAAM,KAAA,CAAM,CAAA,EAAG,MAAM,CAAC,CAAA;AAG3D,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,aAAA,EAAe,GAAG,CAAA;AAItC,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,IAAI,CAAA;AAC/C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,oBAAA,EAAsB,KAAK,CAAA;AAC/C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,uBAAA,EAAyB,KAAK,CAAA;AAElD,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,IAAI,CAAA;AAG/C,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,YAAA,EAAc,CAAC,EAAA,EAAI,MAAc,EAAA,KAAe,IAAA,GAAO,EAAA,CAAG,EAAE,CAAC,CAAA;AAEjF,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,CAAC,EAAA,EAAI,CAAA,EAAW,GAAA,EAAa,EAAA,KAAe,CAAA,GAAI,GAAA,GAAM,EAAA,CAAG,EAAE,CAAC,CAAA;AAEvG,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,kBAAA,EAAoB,CAAC,EAAA,EAAI,KAAa,EAAA,KAAe,GAAA,GAAM,EAAA,CAAG,EAAE,CAAC,CAAA;AAErF,EAAA,IAAA,GAAO,IAAA,CAAK,OAAA,CAAQ,kBAAA,EAAoB,CAAC,EAAA,EAAI,IAAY,EAAA,KAAe,EAAA,GAAK,EAAA,CAAG,EAAE,CAAC,CAAA;AAGnF,EAAA,OAAO,OAAA,CAAQ,IAAA,EAAM,KAAA,EAAO,YAAY,EAAE,IAAA,EAAK;AACjD;;;AC5MO,IAAM,iBAAA,GAAoB;AAW1B,SAAS,UAAA,CAAW,KAAA,EAAqB,GAAA,EAAU,IAAA,GAAwB,EAAC,EAAW;AAC5F,EAAA,MAAM,GAAA,GAAiB;AAAA,IACrB,cAAA,EAAgB,IAAA,CAAK,OAAA,IAAW,EAAC;AAAA,IACjC,GAAA;AAAA,IACA,MAAA,EAAQ,KAAK,MAAA,IAAU,EAAA;AAAA,IACvB,UAAU,IAAA,CAAK,eAAA;AAAA,IACf,QAAA,EAAU,KAAK,QAAA,IAAY,iBAAA;AAAA,IAC3B,cAAc,EAAC;AAAA,IACf,eAAe,IAAA,CAAK;AAAA,GACtB;AAGA,EAAA,MAAM,GAAA,GAAM,WAAW,KAAK,CAAA;AAC5B,EAAA,IAAI,GAAA,GAAM,SAAA,CAAU,GAAA,EAAK,GAAG,CAAA;AAG5B,EAAA,IAAI,IAAA,CAAK,WAAA,KAAgB,KAAA,EAAO,GAAA,GAAM,YAAY,GAAG,CAAA;AAErD,EAAA,OAAO,cAAc,GAAG,CAAA;AAC1B;AAGA,SAAS,WAAW,KAAA,EAAgC;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,cAAc,KAAK,CAAA;AACzD,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG,OAAO,KAAA;AAC/B,EAAA,MAAM,IAAI,gBAAgB,8CAA8C,CAAA;AAC1E;;;AC3CO,SAAS,QAAQ,IAAA,EAAwC;AAC9D,EAAA,MAAM,IAAA,GACJ,IAAA,KAAS,MAAA,GACL,IAAA,CAAK,MAAA,GACL,UAAA,CAAW,OAAO,IAAA,KAAS,QAAA,GAAW,IAAA,KAAS,CAAA,GAAI,UAAA,CAAW,IAAI,CAAC,CAAA;AACzE,EAAA,OAAO,CAAC,GAAA,EAAK,GAAA,KAAQ,GAAA,GAAM,IAAA,CAAK,MAAM,IAAA,EAAK,IAAK,GAAA,GAAM,GAAA,GAAM,CAAA,CAAE,CAAA;AAChE;AAGA,SAAS,WAAW,IAAA,EAA4B;AAC9C,EAAA,IAAI,IAAI,IAAA,KAAS,CAAA;AACjB,EAAA,OAAO,MAAM;AACX,IAAA,CAAA,GAAK,IAAI,UAAA,GAAc,CAAA;AACvB,IAAA,IAAI,IAAI,IAAA,CAAK,IAAA,CAAK,IAAK,CAAA,KAAM,EAAA,EAAK,IAAI,CAAC,CAAA;AACvC,IAAA,CAAA,GAAK,CAAA,GAAI,KAAK,IAAA,CAAK,CAAA,GAAK,MAAM,CAAA,EAAI,EAAA,GAAK,CAAC,CAAA,GAAK,CAAA;AAC7C,IAAA,OAAA,CAAA,CAAS,CAAA,GAAK,CAAA,KAAM,EAAA,MAAS,CAAA,IAAK,UAAA;AAAA,EACpC,CAAA;AACF;AAGA,SAAS,WAAW,CAAA,EAAmB;AACrC,EAAA,IAAI,CAAA,GAAI,UAAA;AACR,EAAA,KAAA,IAAS,IAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,MAAA,EAAQ,KAAK,CAAA,EAAG;AACpC,IAAA,CAAA,IAAK,CAAA,CAAE,WAAW,CAAC,CAAA;AACnB,IAAA,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,CAAA,EAAG,QAAQ,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,CAAA,KAAM,CAAA;AACf;;;ACwFO,SAASC,mBAAkB,MAAA,EAAgC;AAChE,EAAA,OAAO,iBAAA,CAA0B,UAAU,EAAE,CAAA;AAC/C;AAiBO,SAASC,aAAY,MAAA,EAAgC;AAC1D,EAAA,OAAO,WAAA,CAAmBD,kBAAAA,CAAkB,MAAM,CAAC,CAAA;AACrD;AAQO,SAAS,MAAM,GAAA,EAAkB;AACtC,EAAA,OAAO,cAAc,GAAG,CAAA;AAC1B;AAEO,SAAS,MAAA,CAAO,KAAA,EAAqB,IAAA,GAAsB,EAAC,EAAW;AAE5E,EAAA,OAAO,WAAW,KAAA,EAAO,OAAA,CAAQ,IAAA,CAAK,IAAI,GAAG,IAAI,CAAA;AACnD;AAEO,SAAS,QAAA,CAAS,KAAA,EAAqB,IAAA,GAAwB,EAAC,EAAiB;AACtF,EAAA,OAAO,gBAAA,CAAiB,aAAA,CAAc,KAAK,CAAA,EAAG,IAAI,CAAA;AACpD;AAGA,SAAS,cAAc,KAAA,EAA6B;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,KAAA;AACtC,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG,OAAO,KAAA,CAAM,MAAA;AACrC,EAAA,MAAM,IAAI,gBAAgB,8CAA8C,CAAA;AAC1E;AAEO,SAAS,QAAQ,KAAA,EAAoC;AAC1D,EAAA,OAAO,iBAAA,CAAkB,aAAA,CAAc,KAAK,CAAC,CAAA;AAC/C;AAEO,SAAS,OAAA,CAAQ,KAAA,EAAqB,IAAA,GAAwB,EAAC,EAAa;AACjF,EAAA,MAAM,GAAA,GAAME,YAAW,KAAK,CAAA;AAC5B,EAAA,MAAM,SAAA,GAAY,iBAAA,CAAkB,GAAA,CAAI,MAAM,CAAA;AAC9C,EAAA,OAAO;AAAA,IACL,GAAG,SAAA;AAAA,IACH,WAAA,EAAa,gBAAA,CAAiB,GAAA,CAAI,MAAA,EAAQ,IAAI,CAAA;AAAA,IAC9C,UAAA,EAAY,eAAA,CAAgB,GAAA,EAAK,SAAA,CAAU,SAAS,MAAM;AAAA,GAC5D;AACF;AAGA,SAASA,YAAW,KAAA,EAAgC;AAClD,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,EAAU,OAAO,cAAc,KAAK,CAAA;AACzD,EAAA,IAAI,WAAA,CAAY,KAAK,CAAA,EAAG,OAAO,KAAA;AAC/B,EAAA,MAAM,IAAI,gBAAgB,8CAA8C,CAAA;AAC1E;AAOA,SAAS,eAAA,CAAgB,KAAgB,YAAA,EAA8C;AACrF,EAAA,MAAM,MAAA,GAAiC;AAAA,IACrC,WAAA,EAAa,CAAA;AAAA,IACb,WAAA,EAAa,CAAA;AAAA,IACb,QAAA,EAAU,CAAA;AAAA,IACV,WAAA,EAAa,CAAA;AAAA,IACb,MAAA,EAAQ;AAAA,GACV;AACA,EAAA,IAAA,CAAK,GAAA,CAAI,KAAA,EAAO,CAAC,CAAA,KAAM;AACrB,IAAA,IAAI,CAAA,CAAE,IAAA,IAAQ,MAAA,EAAQ,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,GAAA,CAAK,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA,IAAK,CAAA,IAAK,CAAA;AAAA,EACjE,CAAC,CAAA;AACD,EAAA,MAAA,CAAO,GAAA,GAAM,MAAA,CAAO,IAAA,CAAK,GAAA,CAAI,OAAO,CAAA,CAAE,MAAA;AACtC,EAAA,MAAA,CAAO,OAAA,GAAU,YAAA;AACjB,EAAA,OAAO,MAAA;AACT;AAEO,SAASC,YAAW,KAAA,EAAuB;AAChD,EAAA,OAAO,WAAgB,KAAK,CAAA;AAC9B","file":"index.js","sourcesContent":["/**\n * Internal AST for @spintax/core. The public `Ast` (spec §9.2) is the opaque,\n * versioned view; `ParsedAst` is the internal shape carrying the node tree that\n * render/validate/extract/analyze walk. Not a serialization format — never\n * persisted across engine versions.\n *\n * Tree nodes: literal / variable / enumeration / permutation / conditional /\n * plural. Directives are NOT tree nodes (plugin parity):\n * - `#set` is extracted GLOBALLY before the tree is built (line-anchored, like\n * `extract_set_directives`) → {@link ParsedAst.setDefs}; its lines are\n * stripped from the body, so a `#set` on its own line even INSIDE a group is\n * a global definition, not literal text.\n * - `#include` is resolved by the renderer as a post-tree string pass (the\n * plugin's `resolve_includes` runs after enum/perm), so it stays literal in\n * the AST here.\n * Permutation's `<config>` + per-element separators are fully parsed (PR-11b).\n */\n\n/**\n * Bumped only on a breaking change to the node shape (independent of syntax v1).\n *\n * 2 — `ParsedAst` gained `defDefs`. An `Ast` cached by an older version carries no `#def` map, so\n * rendering it would silently drop every definition; the version guard turns that into an\n * `AstVersionError` instead.\n */\nexport const AST_VERSION = 2;\n\n/** Opaque public handle (re-exported as `Ast` from the package index). */\nexport interface Ast {\n readonly astVersion: typeof AST_VERSION;\n}\n\n/** Internal parsed tree. Carries the original source so validate(Ast) can do\n * the raw-text checks (bracket balance etc.) and future offset diagnostics, and\n * the globally-extracted directive definitions (name → raw value, name lowercased).\n *\n * The two maps are separate because the directives have opposite semantics: a `#set` value is a\n * macro, substituted at every reference so its brackets re-roll each time, while a `#def` value\n * is rendered once per render and frozen. Neither is a tree node — both are line-anchored\n * pre-passes over the raw text. */\nexport interface ParsedAst extends Ast {\n readonly source: string;\n readonly setDefs: Readonly<Record<string, string>>;\n readonly defDefs: Readonly<Record<string, string>>;\n readonly nodes: readonly Node[];\n}\n\nexport type Node =\n | LiteralNode\n | VariableNode\n | EnumerationNode\n | PermutationNode\n | ConditionalNode\n | PluralNode;\n\n/** Verbatim text. */\nexport interface LiteralNode {\n readonly type: 'literal';\n readonly value: string;\n}\n\n/** `%name%` reference (name stored verbatim; lookup is case-insensitive at render). */\nexport interface VariableNode {\n readonly type: 'variable';\n readonly name: string;\n}\n\n/** `{a|b|c}` — pick one option. Each option is a node sequence. */\nexport interface EnumerationNode {\n readonly type: 'enumeration';\n readonly options: readonly (readonly Node[])[];\n}\n\n/**\n * `[<config>a|b|c]` — select/shuffle/join. PR-10 captures the raw inner\n * verbatim; PR-11 extracts the `<config>` prefix FIRST (before splitting, so a\n * `|` inside a quoted separator like `sep=\"|\"` isn't a false split — matching\n * the plugin's `extract_permutation_config` → `split_top_level` order) and\n * parses the per-element separators + option node sequences.\n */\n/** Permutation `<config>` (parsed in PR-11b). `null` size ⇒ default rules at render (§4.2). */\nexport interface PermConfig {\n readonly minsize: number | null;\n readonly maxsize: number | null;\n readonly sep: string;\n readonly lastsep: string | null;\n}\n\n/** One permutation element + its per-element separator (a trailing `<sep>` from the PREVIOUS part). */\nexport interface PermOption {\n readonly nodes: readonly Node[];\n readonly separator: string | null;\n}\n\nexport interface PermutationNode {\n readonly type: 'permutation';\n readonly config: PermConfig;\n readonly options: readonly PermOption[];\n}\n\n/**\n * `{?VAR?then|else}` / `{?!VAR?then}` — show `then` when VAR is truthy (or falsy\n * if `inverted`), else `else`. A malformed `{?…}` is NOT a conditional: the\n * parser falls back to treating the braces as an enumeration (matching the\n * plugin, where a bad conditional survives the conditional pass unchanged and\n * is then consumed by the enumeration pass).\n */\nexport interface ConditionalNode {\n readonly type: 'conditional';\n readonly name: string;\n readonly inverted: boolean;\n readonly then: readonly Node[];\n readonly else: readonly Node[];\n}\n\n/**\n * `{plural <count>: one|few|many}`. Both slots are kept RAW (they may hold\n * `%var%`): the renderer expands variables in them first (plurals run after\n * var-expansion, before enum/perm), then splits/checks/pick. The lenient path\n * (nested `{}`/`[]` in a form, or arity mismatch) re-emits\n * `{plural <countRaw>:<formsRaw>}` with fullwidth braces (U+FF5B/FF5D).\n * Discriminated by the literal `{plural ` prefix + a `:`.\n */\nexport interface PluralNode {\n readonly type: 'plural';\n readonly countRaw: string;\n readonly formsRaw: string;\n}\n\n/** Depth-first walk over every node, descending into all child sequences. */\nexport function walk(nodes: readonly Node[], visit: (n: Node) => void): void {\n for (const n of nodes) {\n visit(n);\n switch (n.type) {\n case 'enumeration':\n for (const opt of n.options) walk(opt, visit);\n break;\n case 'conditional':\n walk(n.then, visit);\n walk(n.else, visit);\n break;\n case 'permutation':\n for (const opt of n.options) walk(opt.nodes, visit);\n break;\n default:\n break; // literal / variable / plural (raw slots): no child nodes\n }\n }\n}\n\n/** Type guard: is this an internal ParsedAst produced by this engine version? */\nexport function isParsedAst(value: unknown): value is ParsedAst {\n return (\n typeof value === 'object' &&\n value !== null &&\n (value as { astVersion?: unknown }).astVersion === AST_VERSION &&\n typeof (value as { source?: unknown }).source === 'string' &&\n Array.isArray((value as { nodes?: unknown }).nodes)\n );\n}\n","/**\n * T2 shielding (§6). Text-safe / context-agnostic — NOT the plugin's HTML-entity\n * encoding (that only round-trips in an HTML sink; this engine targets Telegram /\n * plaintext / CLI too). Structural chars `{ } [ ] % #` map to Private-Use-Area\n * sentinels (U+E000–U+E005) the engine's passes never interpret as markup; the\n * mandatory {@link safetyRestore} (always run, even with postProcess:false) maps\n * them back to their literal glyphs. PUA (not the `\\x00…` scheme post-process\n * uses) so the two shielding mechanisms can't collide.\n *\n * \"Text-safe\" = safe against re-interpretation as spintax markup, NOT against an\n * HTML/JS sink — neutralize does not touch `< > &`, so it is not XSS mitigation\n * (an HTML-entity variant is a host concern, §6).\n *\n * RESERVED RANGE: U+E000–U+E005 are engine sentinels. `parseTemplate` strips them\n * from author markup (template source + #include results) via {@link stripSentinels}\n * — every door from author source into a tree, so `parse()`/`analyze()`/`render()`\n * agree — and the restore rewrites them in output, so a RAW (non-neutralized) context\n * value carrying these code points will be altered — hosts should neutralize/strip\n * such data.\n */\nconst STRUCTURAL = ['{', '}', '[', ']', '%', '#'] as const;\nconst SENTINEL_BASE = 0xe000;\n\nconst SHIELD = new Map<string, string>();\nconst RESTORE = new Map<string, string>();\nSTRUCTURAL.forEach((ch, i) => {\n const sentinel = String.fromCharCode(SENTINEL_BASE + i);\n SHIELD.set(ch, sentinel);\n RESTORE.set(sentinel, ch);\n});\n\nconst SHIELD_RE = /[{}[\\]%#]/gu;\nconst RESTORE_RE = new RegExp(\n `[${String.fromCharCode(SENTINEL_BASE)}-${String.fromCharCode(SENTINEL_BASE + STRUCTURAL.length - 1)}]`,\n 'gu',\n);\n\n/** Shield data-derived (T2) input so it can't be re-interpreted as spintax markup. */\nexport function neutralize(value: string): string {\n return value.replace(SHIELD_RE, (ch) => SHIELD.get(ch) ?? ch);\n}\n\n/** Mandatory final stage: restore shielded structural chars to literal glyphs. */\nexport function safetyRestore(text: string): string {\n return text.replace(RESTORE_RE, (ch) => RESTORE.get(ch) ?? ch);\n}\n\n/** Remove stray sentinels from author markup (template / #include) so only\n * neutralize() can introduce them — otherwise safetyRestore would rewrite them. */\nexport function stripSentinels(text: string): string {\n return text.replace(RESTORE_RE, '');\n}\n","/**\n * Recursive-descent parser: template string → {@link ParsedAst}.\n *\n * Lenient by contract (spec §9.2): never throws on malformed markup. Unmatched\n * brackets, malformed `{?…}` / `{plural …}`, and bare `%` degrade gracefully\n * (bad conditional/plural fall back to an enumeration, exactly as the plugin's\n * later passes would consume them). Structural *diagnostics* are the validator's\n * job (PR-12), not the parser's.\n *\n * `#set` is extracted GLOBALLY before the tree is built ({@link extractSetDirectives},\n * line-anchored like the plugin's `extract_set_directives`), so a `#set` on its\n * own line even inside a `{…}`/`[…]` group is a global definition — matching the\n * plugin's brace-oblivious `/m` extraction — not literal text. `#include` stays\n * literal here; the renderer resolves it as a post-tree string pass (like the\n * plugin's post-enum `resolve_includes`).\n */\nimport { AST_VERSION, type Node, type ParsedAst, type PermConfig, type PermOption } from './ast';\nimport { stripSentinels } from './neutralize';\n\nconst VARIABLE_RE = /^%(\\w+)%/;\n// `\\r?` before the multiline `$` so a CRLF line strips cleanly (JS `.` excludes \\r).\n/**\n * The one grammar for `#set` and `#def`. Whitespace is `[ \\t]` (not `\\s`) so a directive is a\n * single line, and the value group is `(.*?)` so an empty value is legal. `\\r?` before the\n * multiline `$` so a CRLF line strips cleanly (JS `.` excludes \\r).\n */\nexport const DIRECTIVE_RE = /^[ \\t]*#(set|def)[ \\t]+%(\\w+)%[ \\t]*=[ \\t]*(.*?)[ \\t]*\\r?$/gmu;\nconst CONDITIONAL_NAME_RE = /[A-Za-z_]\\w*/y;\nconst PLURAL_PREFIX = 'plural ';\n\n/**\n * Parse a full template into an AST (sanitised + comments stripped + directives extracted first).\n *\n * **This is the one door from author source into a tree, and it sanitises.** Stray engine\n * sentinels (U+E000–U+E005) come out first, so a reserved-range character an author typed\n * cannot survive to be rewritten into a brace by the mandatory {@link safetyRestore} — the\n * invariant `neutralize` documents (\"only `neutralize()` may introduce a sentinel\"). It lives\n * here rather than at each caller because there were three callers and two of them (`parse()`\n * and `analyze(str)`) forgot it, so `render(parse(src))` diverged from `render(src)` on that\n * edge and broke the parse-once-reuse contract (#51).\n *\n * {@link parseSequence} is NOT sanitised, and must not be: it re-parses a variable's *value*,\n * where sentinels a host neutralized are legitimate and have to reach the safety-restore.\n *\n * `source` keeps the ORIGINAL, unsanitised text — the validator reads it to place diagnostics,\n * which must point at the bytes the author actually wrote.\n */\nexport function parseTemplate(src: string): ParsedAst {\n const { body, setDefs, defDefs } = extractDirectives(stripComments(stripSentinels(src)));\n return { astVersion: AST_VERSION, source: src, setDefs, defDefs, nodes: parseSequence(body) };\n}\n\n/** One directive occurrence, in source order, with the line it was written on. */\nexport interface DirectiveOccurrence {\n readonly kind: 'set' | 'def';\n readonly name: string;\n readonly value: string;\n readonly line: number;\n}\n\n/**\n * Global directive extraction (parity with `extract_directives`): pull every line-anchored\n * `#set`/`#def` out of the text — regardless of brace nesting — collecting name→value (name\n * lowercased), strip the lines, then collapse `\\n{3,}`→`\\n\\n`.\n *\n * `occurrences` preserves every directive line including duplicates that the two maps flatten\n * away: a validator cannot report a collision it can no longer see.\n */\nexport function extractDirectives(text: string): {\n body: string;\n setDefs: Record<string, string>;\n defDefs: Record<string, string>;\n occurrences: DirectiveOccurrence[];\n} {\n const setDefs: Record<string, string> = {};\n const defDefs: Record<string, string> = {};\n const occurrences: DirectiveOccurrence[] = [];\n\n // Match offsets ascend (replace scans left to right), so the line number resumes\n // from the previous match instead of recounting from the start of the text — a\n // fresh count per occurrence made a directive-heavy document quadratic.\n let cursorOffset = 0;\n let cursorLine = 1;\n const lineAt = (offset: number): number => {\n for (let i = cursorOffset; i < offset; i += 1) {\n if (text.charCodeAt(i) === 10) cursorLine += 1;\n }\n cursorOffset = offset;\n return cursorLine;\n };\n\n DIRECTIVE_RE.lastIndex = 0;\n const stripped = text.replace(\n DIRECTIVE_RE,\n (full: string, kind: string, rawName: string, value: string, offset: number): string => {\n const name = rawName.toLowerCase();\n occurrences.push({\n kind: kind as 'set' | 'def',\n name,\n value,\n line: lineAt(offset),\n });\n if (kind === 'def') defDefs[name] = value;\n else setDefs[name] = value;\n return '';\n },\n );\n\n return { body: stripped.replace(/\\n{3,}/gu, '\\n\\n'), setDefs, defDefs, occurrences };\n}\n\n/** Remove `/# … #/` block comments (non-greedy, spans newlines). */\nexport function stripComments(text: string): string {\n return text.replace(/\\/#[\\s\\S]*?#\\//g, '');\n}\n\n/** Parse a run of text into a node sequence (construct parsing only — no comment\n * strip / #set extraction; the renderer uses this to re-process variable values). */\nexport function parseSequence(text: string): Node[] {\n const nodes: Node[] = [];\n let literal = '';\n let i = 0;\n\n const flushLiteral = (): void => {\n if (literal !== '') {\n nodes.push({ type: 'literal', value: literal });\n literal = '';\n }\n };\n\n while (i < text.length) {\n const ch = text.charAt(i);\n\n if (ch === '{') {\n const end = findMatchingClose(text, i, '{', '}');\n if (end === -1) {\n literal += ch;\n i += 1;\n continue;\n }\n const content = text.slice(i + 1, end);\n flushLiteral();\n nodes.push(parseBraceConstruct(content));\n i = end + 1;\n continue;\n }\n\n if (ch === '[') {\n const end = findMatchingClose(text, i, '[', ']');\n if (end === -1) {\n literal += ch;\n i += 1;\n continue;\n }\n flushLiteral();\n nodes.push(parsePermutation(text.slice(i + 1, end)));\n i = end + 1;\n continue;\n }\n\n if (ch === '%') {\n const name = VARIABLE_RE.exec(text.slice(i))?.[1];\n if (name !== undefined) {\n flushLiteral();\n nodes.push({ type: 'variable', name });\n i += name.length + 2; // \"%\" + name + \"%\"\n continue;\n }\n }\n\n literal += ch;\n i += 1;\n }\n\n flushLiteral();\n return nodes;\n}\n\n/**\n * Decide what a `{…}` (content between the braces) is: a conditional (`?…`), a\n * plural (`plural …:` …), or — the default and the fallback for a malformed\n * conditional — an enumeration.\n */\nfunction parseBraceConstruct(content: string): Node {\n if (content.charAt(0) === '?') {\n const cond = tryParseConditional(content);\n if (cond) return cond;\n // Malformed conditional ⇒ fall back to enumeration (plugin parity).\n } else if (content.startsWith(PLURAL_PREFIX) && content.slice(PLURAL_PREFIX.length).includes(':')) {\n return parsePlural(content.slice(PLURAL_PREFIX.length));\n }\n return { type: 'enumeration', options: splitTopLevel(content).map((o) => parseSequence(o)) };\n}\n\n/**\n * A recognized `{?…}` as OFFSETS into the string it was found in — no branch text\n * copied out. The count-slot pass walks spans instead of substrings; slicing the\n * branch per level of nesting is quadratic on a deeply nested template, and that\n * template arrives from the public Worker.\n */\nexport interface ConditionalHead {\n readonly name: string;\n readonly inverted: boolean;\n /** Offset of the body (past `?name?`). */\n readonly bodyStart: number;\n /** Offset of the top-level `|`, or -1 when the branch stands alone. */\n readonly sepIndex: number;\n}\n\n/** A recognized `{?…}` with its branches materialized — what the parser needs. */\nexport interface ConditionalParts {\n readonly name: string;\n readonly inverted: boolean;\n readonly thenRaw: string;\n readonly elseRaw: string;\n}\n\n/**\n * Recognize `?VAR?then|else` / `?!VAR?then` in `text[contentStart, contentEnd)`\n * (the span between the braces), or null if malformed — the ONE place the\n * conditional grammar lives. Reports offsets only; {@link splitConditional} is\n * the wrapper that materializes the branches for the parser.\n *\n * The renderer needs the branches unparsed as well as parsed: the plural count\n * slot resolves conditionals textually, without resolving the enums a branch may\n * carry (spintax-js#67). Two readers, one recognizer — a second copy of these\n * rules would be a syntax-surface divergence waiting to happen (#55–#57).\n */\nexport function recognizeConditional(\n text: string,\n contentStart: number,\n contentEnd: number,\n): ConditionalHead | null {\n let p = contentStart + 1; // past the leading '?'\n let inverted = false;\n if (text.charAt(p) === '!') {\n inverted = true;\n p += 1;\n }\n\n CONDITIONAL_NAME_RE.lastIndex = p;\n const name = CONDITIONAL_NAME_RE.exec(text)?.[0];\n if (name === undefined || p + name.length > contentEnd) return null;\n p += name.length;\n\n if (text.charAt(p) !== '?') return null; // required '?' after the name\n p += 1;\n\n return { name, inverted, bodyStart: p, sepIndex: firstTopLevelPipe(text, p, contentEnd) };\n}\n\nexport function splitConditional(content: string): ConditionalParts | null {\n const head = recognizeConditional(content, 0, content.length);\n if (head === null) return null;\n\n const body = content.slice(head.bodyStart);\n const sep = head.sepIndex < 0 ? -1 : head.sepIndex - head.bodyStart;\n\n return {\n name: head.name,\n inverted: head.inverted,\n thenRaw: sep < 0 ? body : body.slice(0, sep),\n elseRaw: sep < 0 ? '' : body.slice(sep + 1),\n };\n}\n\n/** Parse `?VAR?then|else` / `?!VAR?then` (content starts with `?`), or null if malformed. */\nfunction tryParseConditional(content: string): Node | null {\n const parts = splitConditional(content);\n if (parts === null) return null;\n\n return {\n type: 'conditional',\n name: parts.name,\n inverted: parts.inverted,\n then: parseSequence(parts.thenRaw),\n else: parseSequence(parts.elseRaw),\n };\n}\n\n/** Parse `<count>: forms` (the part after the `plural ` prefix). */\nfunction parsePlural(afterPrefix: string): Node {\n const colon = afterPrefix.indexOf(':');\n // Count + raw forms are kept as strings; the renderer expands variables in them\n // FIRST (Stage 6d runs after var-expansion, before enum/perm), then splits/checks.\n return { type: 'plural', countRaw: afterPrefix.slice(0, colon), formsRaw: afterPrefix.slice(colon + 1) };\n}\n\n// ─── Permutation parsing (config + per-element separators) ────────────────────\n\nconst CONFIG_KEY_RE = /\\b(?:minsize|maxsize|sep|lastsep)\\s*=/i;\nconst MINSIZE_RE = /minsize\\s*=\\s*(\\d+)/i;\nconst MAXSIZE_RE = /maxsize\\s*=\\s*(\\d+)/i;\nconst SEP_RE = /(?<!last)sep\\s*=\\s*\"([^\"]*)\"/i; // negative lookbehind excludes \"lastsep\"\nconst LASTSEP_RE = /lastsep\\s*=\\s*\"([^\"]*)\"/i;\nconst HTML_TAG_RE = /^([a-zA-Z][a-zA-Z0-9-]*)(?:\\s+[^>]*)?\\/?$/;\nconst PER_ELEM_HTML_RE = /^[a-zA-Z][a-zA-Z0-9]*\\s/;\n\nfunction defaultPermConfig(): PermConfig {\n return { minsize: null, maxsize: null, sep: ' ', lastsep: null };\n}\n\n/** Parse a permutation body `[<config>a|b|c]` inner → config + options with per-element seps. */\nfunction parsePermutation(rawInner: string): Node {\n const { config, content } = extractPermutationConfig(rawInner);\n const options = extractPerElementSeparators(splitTopLevel(content));\n return { type: 'permutation', config, options };\n}\n\n/** Split a leading `<config>` off the body (config is extracted BEFORE the top-level split). */\nfunction extractPermutationConfig(content: string): { config: PermConfig; content: string } {\n const trimmed = phpLtrim(content);\n if (trimmed === '' || trimmed.charAt(0) !== '<') {\n return { config: defaultPermConfig(), content };\n }\n const end = findConfigEnd(trimmed);\n if (end === -1) return { config: defaultPermConfig(), content };\n\n const configStr = trimmed.slice(1, end);\n const remaining = trimmed.slice(end + 1);\n // A leading `<li>…</li>`-style tag is HTML, not config.\n if (looksLikeHtmlStartTag(configStr, remaining)) {\n return { config: defaultPermConfig(), content };\n }\n return { config: parseConfigString(configStr), content: remaining };\n}\n\n/** Index of the closing `>` of a `<…>` config, respecting quoted strings; -1 if none. */\nfunction findConfigEnd(text: string): number {\n let inQuote = false;\n for (let i = 1; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '\"') inQuote = !inQuote;\n if (ch === '>' && !inQuote) return i;\n }\n return -1;\n}\n\nfunction parseConfigString(str: string): PermConfig {\n if (!CONFIG_KEY_RE.test(str)) {\n // Single-separator form: the whole string is sep (and lastsep).\n return { minsize: null, maxsize: null, sep: str, lastsep: str };\n }\n return {\n minsize: intGroup(MINSIZE_RE.exec(str)),\n maxsize: intGroup(MAXSIZE_RE.exec(str)),\n sep: strGroup(SEP_RE.exec(str)) ?? ' ',\n lastsep: strGroup(LASTSEP_RE.exec(str)),\n };\n}\n\nfunction looksLikeHtmlStartTag(tagText: string, remaining: string): boolean {\n const trimmed = phpTrim(tagText);\n if (trimmed === '') return false;\n const m = HTML_TAG_RE.exec(trimmed);\n if (!m) return false;\n if (trimmed.endsWith('/')) return true; // self-closing\n const tagName = (m[1] ?? '').toLowerCase();\n return new RegExp(`</${escapeRegExp(tagName)}\\\\s*>`, 'iu').test(remaining);\n}\n\n/**\n * Turn raw split parts into elements, moving a trailing `<sep>` on part[i] to be\n * the per-element separator of the element from part[i+1]. Each element's text is\n * trimmed; empty elements are dropped (plugin `extract_per_element_separators`).\n */\nfunction extractPerElementSeparators(rawParts: string[]): PermOption[] {\n const options: PermOption[] = [];\n let pendingSep: string | null = null;\n\n rawParts.forEach((part, i) => {\n let text = part;\n let trailingSep: string | null = null;\n if (i < rawParts.length - 1) {\n const extracted = extractTrailingSep(part);\n if (extracted) {\n text = extracted.text;\n trailingSep = extracted.sep;\n }\n }\n const trimmed = phpTrim(text);\n if (trimmed !== '') {\n options.push({ nodes: parseSequence(trimmed), separator: pendingSep });\n }\n pendingSep = trailingSep;\n });\n\n return options;\n}\n\n/** Detect a trailing `< sep >` on a part (not an HTML tag). Returns {text, sep} or null. */\nfunction extractTrailingSep(part: string): { text: string; sep: string } | null {\n const trimmed = phpRtrim(part);\n const len = trimmed.length;\n if (len === 0 || trimmed.charAt(len - 1) !== '>') return null;\n\n let openPos = -1;\n for (let i = len - 2; i >= 0; i -= 1) {\n const ch = trimmed.charAt(i);\n if (ch === '<') {\n openPos = i;\n break;\n }\n if (ch === '>') return null; // nested/complex, bail\n }\n if (openPos === -1) return null;\n\n const inner = trimmed.slice(openPos + 1, len - 1);\n const innerTrimmed = phpTrim(inner);\n // HTML tag → not a separator: closing </x>, self-closing <x/>, or tag-with-attrs `<x …>`.\n if (innerTrimmed.startsWith('/') || innerTrimmed.endsWith('/') || PER_ELEM_HTML_RE.test(innerTrimmed)) {\n return null;\n }\n return { text: trimmed.slice(0, openPos), sep: inner };\n}\n\nfunction intGroup(m: RegExpExecArray | null): number | null {\n return m && m[1] !== undefined ? Number.parseInt(m[1], 10) : null;\n}\nfunction strGroup(m: RegExpExecArray | null): string | null {\n return m && m[1] !== undefined ? m[1] : null;\n}\nfunction escapeRegExp(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/gu, '\\\\$&');\n}\n\n// PHP trim strips only [ \\t\\n\\r\\0\\x0B] — NOT the full JS Unicode whitespace set —\n// so use these for byte-exact parity wherever the plugin trims (permutation\n// config / element text / separators, plural forms).\nconst PHP_LTRIM_RE = /^[ \\t\\n\\r\\0\\x0B]+/u;\nconst PHP_RTRIM_RE = /[ \\t\\n\\r\\0\\x0B]+$/u;\nfunction phpTrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '').replace(PHP_RTRIM_RE, '');\n}\nfunction phpLtrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '');\n}\nfunction phpRtrim(s: string): string {\n return s.replace(PHP_RTRIM_RE, '');\n}\n\n/**\n * Index of the `close` that matches the `open` at `openPos`, tracking depth of\n * this bracket pair only. Returns -1 if unmatched.\n */\nfunction findMatchingClose(text: string, openPos: number, open: string, close: string): number {\n let depth = 0;\n for (let i = openPos; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === open) {\n depth += 1;\n } else if (ch === close) {\n depth -= 1;\n if (depth === 0) return i;\n }\n }\n return -1;\n}\n\n/**\n * Split on top-level `|` — mirrors the plugin's `split_top_level`: brace and\n * bracket depths tracked INDEPENDENTLY and decremented UNCONDITIONALLY (may go\n * negative), split only when BOTH are exactly 0. So `a]|b` stays one option.\n */\nexport function splitTopLevel(inner: string): string[] {\n const parts: string[] = [];\n let brace = 0;\n let bracket = 0;\n let cur = '';\n for (const ch of inner) {\n if (ch === '{') brace += 1;\n else if (ch === '}') brace -= 1;\n else if (ch === '[') bracket += 1;\n else if (ch === ']') bracket -= 1;\n\n if (ch === '|' && brace === 0 && bracket === 0) {\n parts.push(cur);\n cur = '';\n } else {\n cur += ch;\n }\n }\n parts.push(cur);\n return parts;\n}\n\n/**\n * Index of the first top-level `|` in a conditional body, or -1. Uses a single\n * depth counter CLAMPED at 0 (matching the plugin's `parse_conditional` body\n * split, which differs from `split_top_level`'s signed dual counters).\n */\nfunction firstTopLevelPipe(body: string, from = 0, to = body.length): number {\n let depth = 0;\n for (let j = from; j < to; j += 1) {\n const ch = body.charAt(j);\n if (ch === '{' || ch === '[') {\n depth += 1;\n } else if (ch === '}' || ch === ']') {\n if (depth > 0) depth -= 1;\n } else if (ch === '|' && depth === 0) {\n return j;\n }\n }\n return -1;\n}\n","/**\n * Locale plural rules — ported from the plugin's `Plurals` (parity item §3.1).\n * Shared by the validator (arity check, PR-12) and the renderer (bucket pick, M2).\n */\n\nconst PLURAL_PREFIX = '{plural ';\n\nexport interface PluralBlock {\n readonly start: number;\n /** Exclusive end offset — one past the block's closing `}` (for diagnostics). */\n readonly end: number;\n readonly countSlot: string;\n readonly formsRaw: string;\n}\n\n/**\n * Raw brace-aware scan for `{plural …}` blocks — ported from the plugin's\n * `find_plural_blocks`. Used by the validator (and available to the renderer).\n * Scans the whole text, so it finds plurals nested inside `[…]` permutations too\n * (the AST leaves a permutation body unparsed until PR-11b). A block without a\n * `:` is not a plural (left to the enumeration path).\n */\nexport function findPluralBlocks(text: string): PluralBlock[] {\n const blocks: PluralBlock[] = [];\n let i = 0;\n while (i < text.length) {\n const start = text.indexOf(PLURAL_PREFIX, i);\n if (start === -1) break;\n\n let depth = 1;\n let j = start + PLURAL_PREFIX.length;\n while (j < text.length) {\n const ch = text.charAt(j);\n if (ch === '{') depth += 1;\n else if (ch === '}') {\n depth -= 1;\n if (depth === 0) break;\n }\n j += 1;\n }\n if (depth !== 0) {\n i = start + PLURAL_PREFIX.length; // unmatched opening — skip past prefix\n continue;\n }\n\n const inner = text.slice(start + PLURAL_PREFIX.length, j);\n const colon = inner.indexOf(':');\n if (colon === -1) {\n i = j + 1; // no colon ⇒ not a plural\n continue;\n }\n blocks.push({ start, end: j + 1, countSlot: inner.slice(0, colon), formsRaw: inner.slice(colon + 1) });\n i = j + 1;\n }\n return blocks;\n}\n\n/** Normalise a locale to its base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. */\nexport function normalizeBaseLang(locale: string): string {\n const first = locale.toLowerCase().split(/[-_]/, 1)[0];\n return first ?? '';\n}\n\n/**\n * Expected number of plural forms: 3 for the Slavic one/few/other family\n * (East Slavic ru/uk/be + BCS sr/hr/bs), else 2 (EN-style).\n *\n * BCS shares the East-Slavic integer rule exactly, so it reuses that bucket; CLDR\n * names the third slot \"other\" rather than \"many\", positionally the same.\n */\nexport function pluralArity(baseLang: string): number {\n switch (baseLang) {\n case 'ru':\n case 'uk':\n case 'be':\n case 'sr':\n case 'hr':\n case 'bs':\n return 3;\n default:\n return 2;\n }\n}\n\n/**\n * How many forms `render` resolves against when the host supplies no locale.\n *\n * Derived from the table rather than written as `2`, so the validator's\n * `plural.locale-missing` warning cannot come to disagree with what render actually\n * does — the disagreement between those two is the whole of issue #65.\n */\nexport const DEFAULT_PLURAL_ARITY = pluralArity('');\n\n/**\n * Pick the plural form for a count by the locale's grammar.\n * - Slavic 3-form (ru/uk/be + sr/hr/bs): one (1,21,31… not 11), few (2-4,22-24…\n * not 12-14), many (rest, incl. 0).\n * - EN-style: one (n=1), many (rest). Negative counts use abs().\n *\n * Counts are integers here (§3.1 erases a non-numeric slot), so the BCS/East-Slavic\n * split on fractions — CLDR gives BCS a fraction-digit rule — cannot be reached.\n */\nexport function pluralFor(baseLang: string, n: number, forms: readonly string[]): string {\n const abs = Math.abs(n);\n const mod10 = abs % 10;\n const mod100 = abs % 100;\n\n switch (baseLang) {\n case 'ru':\n case 'uk':\n case 'be':\n case 'sr':\n case 'hr':\n case 'bs':\n if (mod10 === 1 && mod100 !== 11) return forms[0] ?? '';\n if (mod10 >= 2 && mod10 <= 4 && (mod100 < 12 || mod100 > 14)) return forms[1] ?? '';\n return forms[2] ?? '';\n default:\n return (abs === 1 ? forms[0] : forms[1]) ?? '';\n }\n}\n","/**\n * Static validator — ported from the plugin's `Validator` (parity gate §3.1).\n * Produces {@link Diagnostic}[] with the canonical, stable codes documented in\n * `@spintax/conformance`'s README. \"Valid\" ⇔ no `severity:'error'`.\n *\n * Bracket balance is a raw char scan (the lenient AST doesn't represent\n * imbalance). Plural and #include checks walk the AST. Positions are best-effort\n * — not parity-gated (§3.1): only `code` (+ severity) is.\n *\n * Circular `#include` is NOT a verdict here — it is a render-time maxDepth guard\n * (the plugin's validator never resolves includes).\n */\nimport type { Diagnostic, ValidateOptions } from '../index';\nimport { DIRECTIVE_RE, extractDirectives, stripComments } from './parser';\nimport { DEFAULT_PLURAL_ARITY, findPluralBlocks, normalizeBaseLang, pluralArity } from './plurals';\n\nconst KNOWN_CONFIG_KEYS = new Set(['minsize', 'maxsize', 'sep', 'lastsep']);\n// The gap class is spelled out because no dialect's `\\s` is this set — PHP's under /u is\n// UCP-Unicode (measured, #55), not the ASCII this comment once claimed. Corpus-pinned.\nconst INCLUDE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\n\n/**\n * Pure raw-text validation — exactly like the plugin's `Validator` (which does\n * NOT build an AST). Scanning the raw text (not the lenient AST) is what lets\n * bracket imbalance and constructs nested inside `[…]` permutations be seen.\n */\nexport function validateTemplate(src: string, opts: ValidateOptions = {}): Diagnostic[] {\n const diagnostics: Diagnostic[] = [];\n const text = stripComments(src);\n const idx = buildLineIndex(text);\n\n checkBrackets(text, diagnostics);\n checkDirectives(text, diagnostics);\n checkPermutationConfigs(text, idx, diagnostics);\n checkPlurals(text, idx, opts.locale, opts.knownVariables, diagnostics);\n checkVariableReferences(text, idx, opts.knownVariables, diagnostics);\n if (opts.knownIncludes && opts.knownIncludes.length > 0) {\n checkIncludeTargets(text, idx, opts.knownIncludes, diagnostics);\n }\n\n return diagnostics;\n}\n\n/** Position (+ optional end and structured data) attached to a Diagnostic. */\ninterface Pos { line: number; column: number; endLine?: number; endColumn?: number; data?: Record<string, unknown> }\n\nfunction err(code: string, message: string, pos: Pos): Diagnostic {\n return { severity: 'error', code, message, ...pos };\n}\nfunction warn(code: string, message: string, pos: Pos): Diagnostic {\n return { severity: 'warning', code, message, ...pos };\n}\n\n/**\n * Line-start offsets of `text`, built once per validate() call. Every diagnostic\n * position is then a binary search instead of a scan from offset 0 — the scan made\n * a diagnostic-heavy document quadratic (each of N diagnostics re-walked the text).\n */\ninterface LineIndex { starts: number[]; length: number }\n\nfunction buildLineIndex(text: string): LineIndex {\n const starts = [0];\n for (let i = 0; i < text.length; i += 1) {\n if (text.charCodeAt(i) === 10) starts.push(i + 1);\n }\n return { starts, length: text.length };\n}\n\n/** 1-based (line, column) of a character offset — same clamp and column model as the old scan. */\nfunction offsetToLineCol(idx: LineIndex, offset: number): { line: number; column: number } {\n const end = Math.min(Math.max(offset, 0), idx.length);\n let lo = 0;\n let hi = idx.starts.length - 1;\n while (lo < hi) {\n const mid = (lo + hi + 1) >> 1;\n if ((idx.starts[mid] ?? 0) <= end) lo = mid;\n else hi = mid - 1;\n }\n return { line: lo + 1, column: end - (idx.starts[lo] ?? 0) + 1 };\n}\n\n/** A full [offset, offset+length) span as start + end positions. */\nfunction span(idx: LineIndex, offset: number, length: number): Pos {\n const s = offsetToLineCol(idx, offset);\n const e = offsetToLineCol(idx, offset + length);\n return { line: s.line, column: s.column, endLine: e.line, endColumn: e.column };\n}\n\n/** Balanced `{}`/`[]` with proper nesting (raw char scan, real line/col). */\nfunction checkBrackets(text: string, out: Diagnostic[]): void {\n const close: Record<string, string> = { '{': '}', '[': ']' };\n const stack: Array<{ char: string; expect: string; line: number; column: number }> = [];\n let line = 1;\n let column = 1;\n\n for (const ch of text) {\n if (ch === '\\n') {\n line += 1;\n column = 1;\n continue;\n }\n if (ch === '{' || ch === '[') {\n stack.push({ char: ch, expect: close[ch]!, line, column });\n } else if (ch === '}' || ch === ']') {\n const top = stack.pop();\n if (top === undefined) {\n out.push(err('bracket.unexpected-closing', `Unexpected closing '${ch}'.`, { line, column, endLine: line, endColumn: column + 1, data: { bracket: ch } }));\n } else if (top.expect !== ch) {\n out.push(err('bracket.mismatched', `'${top.char}' closed by '${ch}'.`, { line, column, endLine: line, endColumn: column + 1, data: { open: top.char, close: ch } }));\n }\n }\n column += 1;\n }\n\n for (const unclosed of stack) {\n out.push(err('bracket.unclosed', `Unclosed '${unclosed.char}'.`, { line: unclosed.line, column: unclosed.column, endLine: unclosed.line, endColumn: unclosed.column + 1, data: { bracket: unclosed.char } }));\n }\n}\n\n/**\n * Directive lines must match the shared grammar, each name may be defined once, and `#include`\n * may not appear in a `#def` value.\n *\n * The shape test uses `DIRECTIVE_RE` rather than a private copy. The old copy differed from the\n * parser's in two ways — `\\s` for whitespace and `(.+)` for the value — and the second was a live\n * defect: an empty value is legal and the parser accepts it, but this reported `#set %x% =` as\n * malformed unless a trailing space happened to be present.\n */\nfunction checkDirectives(text: string, out: Diagnostic[]): void {\n const lines = text.split('\\n');\n lines.forEach((lineText, idx) => {\n const trimmed = lineText.replace(/^[ \\t]+/, '');\n const kind = (['#set', '#def'] as const).find(\n (candidate) => trimmed.startsWith(`${candidate} `) || trimmed.startsWith(`${candidate}\\t`),\n );\n if (!kind) return;\n\n DIRECTIVE_RE.lastIndex = 0;\n if (!DIRECTIVE_RE.test(trimmed)) {\n const column = lineText.length - trimmed.length + 1; // first non-space char\n const line = idx + 1;\n const code = kind === '#def' ? 'def.malformed' : 'set.malformed';\n out.push(err(code, `Malformed ${kind}. Expected: ${kind} %name% = value`, { line, column, endLine: line, endColumn: lineText.length + 1 }));\n }\n });\n\n const { occurrences } = extractDirectives(text);\n const seen = new Map<string, number>();\n\n for (const occurrence of occurrences) {\n // A name defined twice is an error whichever directives are involved. The two maps flatten a\n // collision to last-wins before anyone can see it, which is why `occurrences` exists — and a\n // `#set`/`#def` pair sharing a name would be worse still, the two carrying opposite semantics.\n const first = seen.get(occurrence.name);\n if (first !== undefined) {\n out.push(err(\n 'definition.duplicate-name',\n `Variable '${occurrence.name}' is defined more than once (first on line ${first}). A name belongs to one directive, once.`,\n { line: occurrence.line, column: 1 },\n ));\n } else {\n seen.set(occurrence.name, occurrence.line);\n }\n\n // Includes resolve after a definition is frozen, so one cannot be rolled into a value — it\n // would survive as literal text. Inside a `#set` it is fine: the macro is substituted verbatim\n // and its `#include` reaches the include stage in the body.\n if (occurrence.kind === 'def' && /#include\\b/u.test(occurrence.value)) {\n out.push(err(\n 'def.include-in-value',\n `#include cannot appear in a #def value ('${occurrence.name}'): includes resolve after the value is frozen. Use #set, or put the #include in the body.`,\n { line: occurrence.line, column: 1 },\n ));\n }\n }\n}\n\n/** `[<config>]` prefixes: known keys only, minsize/maxsize must be digit runs. */\nfunction checkPermutationConfigs(text: string, idx: LineIndex, out: Diagnostic[]): void {\n for (const m of text.matchAll(/\\[<([^>]*?)>/gu)) {\n const configStr = m[1] ?? '';\n if (!/\\w+\\s*=/.test(configStr)) continue; // not a key=value config\n const configBase = (m.index ?? 0) + 2; // offset of configStr in text (past \"[<\")\n\n for (const km of configStr.matchAll(/(\\w+)\\s*=/gu)) {\n const key = (km[1] ?? '').toLowerCase();\n if (!KNOWN_CONFIG_KEYS.has(key)) {\n out.push(err('permutation.unknown-key', `Unknown permutation config key: '${km[1]}'.`,\n { ...span(idx, configBase + (km.index ?? 0), (km[1] ?? '').length), data: { key: km[1] } }));\n }\n }\n const min = /minsize\\s*=\\s*([^;>\\s]+)/i.exec(configStr);\n if (min && !/^\\d+$/.test(min[1] ?? '')) {\n out.push(err('permutation.minsize-not-integer', `minsize must be a positive integer, got '${min[1]}'.`,\n { ...span(idx, configBase + min.index, min[0].length), data: { value: min[1] } }));\n }\n const max = /maxsize\\s*=\\s*([^;>\\s]+)/i.exec(configStr);\n if (max && !/^\\d+$/.test(max[1] ?? '')) {\n out.push(err('permutation.maxsize-not-integer', `maxsize must be a positive integer, got '${max[1]}'.`,\n { ...span(idx, configBase + max.index, max[0].length), data: { value: max[1] } }));\n }\n }\n}\n\n/** `{plural …}`: no nested brackets in forms; form count matches locale arity. */\nfunction checkPlurals(\n text: string,\n idx: LineIndex,\n locale: string | undefined,\n knownVariables: readonly string[] | undefined,\n out: Diagnostic[],\n): void {\n // Guard on the NORMALIZED base (like the plugin): a non-empty locale that\n // normalizes to '' (e.g. \"_en\") skips the arity check.\n const base = locale && locale !== '' ? normalizeBaseLang(locale) : '';\n const arity = base !== '' ? pluralArity(base) : 0;\n\n const tainted = macroTaintedNames(text);\n const { setDefs: macros, defDefs: defs } = extractDirectives(text);\n // Names the host says it will supply: runtime context outranks a definition of the\n // same name, so one of these makes a form count unknowable however the template\n // defines it.\n const hostNames = new Set((knownVariables ?? []).map((n) => n.toLowerCase()));\n\n for (const block of findPluralBlocks(text)) {\n const at = span(idx, block.start, block.end - block.start);\n\n // A macro in the count slot: the count is still unresolved spintax when the plural is decided,\n // so the block resolves to nothing. `#def` is the fix — it freezes to a literal before the\n // body is walked — which is why this points at the directive, not at the plural block.\n for (const m of block.countSlot.matchAll(/%(\\w+)%/gu)) {\n const name = (m[1] ?? '').toLowerCase();\n if (!tainted.has(name)) continue;\n out.push(err(\n 'plural.count-macro',\n `{plural ...}: the count '${m[1]}' is a #set macro, so it is still unresolved spintax when the plural is decided and the block renders empty. Define it with #def instead.`,\n at,\n ));\n }\n\n if (/[{}[\\]]/.test(block.formsRaw)) {\n out.push(err('plural.nested-brackets', '{plural ...}: forms must not contain nested spintax brackets. Extract via #def first — a #set is substituted verbatim and would put the brackets straight back.', at));\n continue;\n }\n\n // The form list AS THE RENDERER WILL SEE IT. `render` expands variables before it\n // counts forms (internal/render.ts), so counting the raw pipes here judged a\n // different string than the one that gets rendered — a `#def` holding `few|many`\n // made a correct 3-form Russian template report plural.arity, and a 1-pipe list\n // that expands to 2 forms reported nothing (issue #66, found adopting #65 in the\n // Pascal port).\n const expanded = expandFormsForCounting(block.formsRaw, defs, macros, hostNames);\n\n // A `#set` whose value carries spintax lands in the form list VERBATIM and is still\n // unresolved when the plural is decided — the same fact plural.count-macro states\n // for the count slot, and exactly what this message already describes.\n if (expanded.directMacroSpintax) {\n out.push(err('plural.nested-brackets', '{plural ...}: forms must not contain nested spintax brackets. Extract via #def first — a #set is substituted verbatim and would put the brackets straight back.', at));\n continue;\n }\n\n // A reference the template does not define — a host variable, or a chain past the\n // budget — has no static form count. Judging it would repeat the mistake #65 fixed:\n // filing a verdict on a fact the caller never claimed.\n if (expanded.unresolved) continue;\n\n const count = expanded.forms;\n if (arity > 0) {\n if (count !== arity) {\n out.push(err('plural.arity', `{plural ...}: expected ${arity} forms, got ${count}.`,\n { ...at, data: { expected: arity, got: count } }));\n }\n } else if (count !== DEFAULT_PLURAL_ARITY) {\n // No locale ⇒ no arity VERDICT: the template may well be correct for the locale it\n // will be rendered with, and calling it invalid here would fail a good template for\n // a fact the caller never claimed. But `render` has no such luxury — it defaults to\n // 2 forms — so silence sends a 3-form block straight to the fullwidth-brace\n // fallback in finished text (issue #65: a pipeline shipped {plural …} to live\n // pages because validate stayed quiet). A warning says the one true thing: this\n // resolves only if a matching locale arrives at render time.\n // Two ways to arrive with no arity: nothing was passed, or what was passed does\n // not normalize to a language the engine knows (`_en`). Saying \"no locale was\n // supplied\" to a caller who supplied one sends them looking for the wrong bug.\n const unusable = locale !== undefined && locale !== '';\n out.push(warn(\n 'plural.locale-missing',\n unusable\n ? `{plural ...}: ${count} forms, and the locale '${locale}' does not normalize to a ` +\n `language the engine knows, so render falls back to ${DEFAULT_PLURAL_ARITY} forms and ` +\n `leaves this block unresolved — pass a base tag such as 'en' or 'ru'.`\n : `{plural ...}: ${count} forms, but no locale was supplied. render defaults to ` +\n `${DEFAULT_PLURAL_ARITY} forms and leaves this block unresolved — pass the locale you will render with.`,\n {\n ...at,\n data: {\n got: count,\n defaultArity: DEFAULT_PLURAL_ARITY,\n ...(unusable ? { locale } : {}),\n },\n },\n ));\n }\n }\n}\n\n/**\n * Spintax still unresolved when plural agreement runs: `[`, or `{` that does not open a\n * conditional.\n *\n * Stage order decides this, not bracket type. Conditionals resolve BEFORE plurals, so a `{?…}` in\n * a count value is already a literal when the count is read — flagging it would be a false\n * positive on a template that renders correctly. Enumerations and permutations resolve AFTER\n * plurals and are the real hazard. A nested `{plural …}` is NOT exempt either: it resolves in the\n * same pass as the outer block, not before it.\n *\n * Only `#set` names can be tainted; a `#def` is frozen to literal text before the walk begins.\n * Taint propagates through `#set` → `#set` references to a fixpoint, because the chain can be\n * arbitrarily long and carry no bracket at its final link.\n */\nconst UNRESOLVED_AT_PLURAL_TIME = /\\[|\\{(?!\\?)/u;\n\n/**\n * Any bracket at all — all four, and conditionals too.\n *\n * Two reasons, and both were review findings. Conditionals: one resolves before plurals,\n * so it is not \"unresolved at plural time\", but its branches can differ in top-level\n * pipes (`{?flag?a|b|c}` freezes as `a` or as `b|c`), and counting is about invariance\n * rather than stage order. Closing brackets: a `#set %x% = ]` balances against a `[`\n * elsewhere in the template, so the bracket checker stays quiet, and every renderer's\n * plural guard is `[{}[\\]]` — it rejects the form list on a stray closer exactly as on an\n * opener.\n *\n * Construct-free is a SUFFICIENT condition for the count to be invariant, deliberately\n * not a necessary one: `{a|b}` really does always freeze to one form. It is the property\n * this validator elects to prove, because the cases where a construct is invariant cannot\n * be told from the cases where it is not without evaluating it.\n */\nconst ANY_BRACKET = /[[\\]{}]/u;\n\n/**\n * Passes, not occurrences — each one substitutes EVERY reference, as the renderer's\n * expansion does. Counting occurrences instead made a form list with 51 references\n * exhaust the budget and go unjudged.\n *\n * It is deliberately NOT claimed to match a renderer's own limit (they differ: 50 here\n * and in Python, 51 in both PHP engines). It only has to terminate — a chain deeper than\n * this is suppressed rather than judged, which is the safe direction.\n */\nconst FORM_EXPANSION_PASSES = 51;\n/**\n * How far the form list may GROW under expansion, in characters.\n *\n * Passes alone do NOT bound the work: `#set %a% = %b% %b%` over `#set %b% = %a% %a%`\n * doubles the text every pass, so 51 of them is 2^51 — a 62-character template took\n * `validate()` out with an out-of-memory crash in every engine of the family.\n *\n * Growth, not total size, and the difference is a verdict: `{plural 2: one|<65 KB of\n * ordinary text>}` is plainly two forms and must keep earning `plural.arity` under `ru`.\n * A ceiling on total length called that unknowable and flipped it to valid — a real\n * regression, caught in review before it shipped. Expansion that ADDS this much is a\n * graph exploding; a long form list is just long.\n */\nconst FORM_EXPANSION_MAX_GROWTH = 64 * 1024;\n\n/**\n * How many forms the plural stage will actually receive — or an admission that it is not\n * knowable.\n *\n * Why this exists: `render` expands `%variables%` and only THEN splits the form list,\n * while this validator used to split the raw source, so any reference inside a form list\n * was judged on the wrong number in both directions (issue #66).\n *\n * The rule is deliberately narrow, and the narrowness IS the correction. A first version\n * tried to predict the roll — counting pipes at bracket depth 0, on the theory that a\n * construct always collapses to one form. It does not:\n *\n * #set %flag% =\n * #def %x% = {?flag?a|b|c} ← the false branch freezes as `b|c`: TWO forms\n * {plural 1: one|%x%} ← renders fine under ru; the guess said arity error\n *\n * So a value is counted only when its form count is the same WHATEVER the roll does —\n * that is, when it carries no spintax construct at all. Anything else, any name the host\n * may supply at render time, and any reference the template does not define, suppresses\n * the count-based verdicts. Silence on an unknowable input is the #65 principle; a\n * confident wrong answer is what it replaced.\n *\n * `directMacroSpintax` is the one prediction that survives, because it is not one: a\n * `#set` named DIRECTLY in the form slot is substituted verbatim and is still spintax\n * when the plural is decided — measured, and exactly what the nested-brackets message has\n * always described. Reached through a `#def` it is rolled first, so it is not reported.\n */\nfunction expandFormsForCounting(\n formsRaw: string,\n defs: Record<string, string>,\n macros: Record<string, string>,\n hostNames: ReadonlySet<string>,\n): { forms: number; unresolved: boolean; directMacroSpintax: boolean } {\n const unknown = (\n directMacroSpintax = false,\n ): { forms: number; unresolved: boolean; directMacroSpintax: boolean } => ({\n forms: 0,\n unresolved: true,\n directMacroSpintax,\n });\n\n // Which brackets reach the form slot VERBATIM: follow the `#set` chain out of the raw\n // slot, stopping at anything that changes the answer. \"Direct\" is a property of the\n // PATH, not of one hop — `#set %a% = %b%` with `#set %b% = {a|b}` never crosses a #def,\n // so the macro text arrives whole and the block renders as the fallback.\n const seenMacro = new Set<string>();\n const refsOf = (text: string): string[] =>\n [...text.matchAll(/%(\\w+)%/gu)].map((m) => (m[1] ?? '').toLowerCase());\n /**\n * Iterative, and the order is load-bearing: this is a pre-order depth-first walk in\n * source order, and the FIRST non-clean answer wins. A graph holding both an opaque\n * macro and a brackety one gives different diagnostics depending on which is met\n * first, so a cheaper order would be a different contract.\n *\n * Written recursively it cost one frame per link and threw on a long acyclic `#set`\n * chain — `RangeError` here at ~9000 links, `RecursionError` in the Python port at\n * ~1000, a 20 KB template — while the PHP engines returned a verdict. `validate()`\n * answering with an exception is neither a verdict nor parity. The `seenMacro` set\n * already bounds total work to the number of distinct macros, so no step budget is\n * needed on top.\n */\n const walkMacros = (source: string): 'brackets' | 'opaque' | 'clean' => {\n const stack: { refs: string[]; i: number }[] = [{ refs: refsOf(source), i: 0 }];\n\n while (stack.length > 0) {\n const frame = stack[stack.length - 1] as { refs: string[]; i: number };\n if (frame.i >= frame.refs.length) {\n stack.pop();\n continue;\n }\n const name = frame.refs[frame.i++] as string;\n // A #def rolls it, and a host value replaces it — either way the macro text does\n // not arrive verbatim, so this path says nothing.\n if (defs[name] !== undefined || hostNames.has(name)) continue;\n const macro = macros[name];\n if (macro === undefined || seenMacro.has(name)) continue;\n seenMacro.add(name);\n // A conditional is where the engines themselves disagree: both PHP renderers\n // resolve one that expansion introduces INSIDE a form list, TS and Python do not.\n // Until that is settled (filed separately), decline to judge rather than pick a\n // side — the retreat this whole fix is built on.\n if (/\\{\\?/u.test(macro)) return 'opaque';\n if (ANY_BRACKET.test(macro)) return 'brackets';\n stack.push({ refs: refsOf(macro), i: 0 });\n }\n\n return 'clean';\n };\n const verbatim = walkMacros(formsRaw);\n if (verbatim === 'brackets') return unknown(true);\n if (verbatim === 'opaque') return unknown();\n\n let text = formsRaw;\n const budget = formsRaw.length + FORM_EXPANSION_MAX_GROWTH;\n for (let pass = 0; pass < FORM_EXPANSION_PASSES; pass++) {\n let sawReference = false;\n let bailed = false;\n\n // EVERY reference per pass, as the renderer's expansion does. Replacing one at a time\n // spent the budget on a list that merely repeats a name 51 times.\n //\n // Built by hand rather than with `replace()` because the budget has to be enforced\n // DURING the pass: `replace()` materializes the whole next generation before anyone\n // can measure it, so a single pass over 60 KB of self-reference allocates ~900 MB and\n // the check downstream never runs.\n const parts: string[] = [];\n let total = 0;\n let cursor = 0;\n const re = /%(\\w+)%/gu;\n let m: RegExpExecArray | null;\n while ((m = re.exec(text)) !== null) {\n sawReference = true;\n const name = (m[1] ?? '').toLowerCase();\n // Runtime context outranks a definition of the same name, so a host-declared name\n // makes the count unknowable even where the template defines one locally.\n const value = hostNames.has(name) ? undefined : defs[name] ?? macros[name];\n // A construct in the value: what it rolls to may or may not carry a top-level pipe,\n // so no single count is true of every render.\n if (value === undefined || ANY_BRACKET.test(value)) {\n bailed = true;\n break;\n }\n parts.push(text.slice(cursor, m.index), value);\n total += m.index - cursor + value.length;\n cursor = m.index + m[0].length;\n if (total > budget) return unknown();\n }\n\n if (bailed) return unknown();\n parts.push(text.slice(cursor));\n total += text.length - cursor;\n if (total > budget) return unknown();\n text = parts.join('');\n\n if (!sawReference) {\n // No construct can be left here, so the plain split is what the renderer does too.\n return { forms: text.split('|').length, unresolved: false, directMacroSpintax: false };\n }\n }\n // A cycle, or a chain deeper than this bothers to follow.\n return unknown();\n}\n\nfunction macroTaintedNames(text: string): Set<string> {\n const macros = extractDirectives(text).setDefs;\n const tainted = new Set<string>();\n const queue: string[] = [];\n\n for (const [name, value] of Object.entries(macros)) {\n if (UNRESOLVED_AT_PLURAL_TIME.test(value)) {\n tainted.add(name);\n queue.push(name);\n }\n }\n\n // Same closure the old fixpoint sweep computed, via reverse edges — the sweep\n // re-parsed every value once per newly tainted name, O(n²) on a macro chain.\n const dependents = new Map<string, string[]>();\n for (const [name, value] of Object.entries(macros)) {\n for (const m of value.matchAll(/%(\\w+)%/gu)) {\n const ref = (m[1] ?? '').toLowerCase();\n const list = dependents.get(ref);\n if (list === undefined) dependents.set(ref, [name]);\n else list.push(name);\n }\n }\n while (queue.length > 0) {\n const source = queue.pop()!;\n for (const name of dependents.get(source) ?? []) {\n if (!tainted.has(name)) {\n tainted.add(name);\n queue.push(name);\n }\n }\n }\n\n return tainted;\n}\n\n/** Self-reference + circular definitions (errors) and undefined `%var%`/conditional refs (warnings). */\nfunction checkVariableReferences(text: string, idx: LineIndex, known: readonly string[] | undefined, out: Diagnostic[]): void {\n const knownSet = new Set((known ?? []).map((n) => n.toLowerCase()));\n // `[ \\t]` (single-line), uniform with the parser's extract_set_directives and\n // extract.ts — so a malformed cross-line `#set` isn't treated as a definition.\n const defs = new Map<string, string>();\n const defPos = new Map<string, Pos>(); // %name% token span in its #set line\n for (const m of text.matchAll(/^[ \\t]*#(?:set|def)[ \\t]+%(\\w+)%[ \\t]*=[ \\t]*(.*?)$/gmu)) {\n const name = (m[1] ?? '').toLowerCase();\n defs.set(name, m[2] ?? '');\n const nameOffset = (m.index ?? 0) + m[0].indexOf('%');\n defPos.set(name, span(idx, nameOffset, name.length + 2));\n }\n\n const somewhere: Pos = { line: 1, column: 1 };\n for (const [name, value] of defs) {\n if (value.toLowerCase().includes(`%${name}%`)) {\n out.push(err('variable.self-reference', `Variable '${name}' references itself.`, defPos.get(name) ?? somewhere));\n }\n }\n\n // Each value's references, parsed once — the walk used to re-run the regex at\n // every visit of every root.\n const refsOf = new Map<string, string[]>();\n for (const [name, value] of defs) {\n const refs: string[] = [];\n for (const m of value.matchAll(/%(\\w+)%/gu)) refs.push((m[1] ?? '').toLowerCase());\n refsOf.set(name, refs);\n }\n\n const reachesCycle = namesThatReachACycle(defs, refsOf);\n for (const name of defs.keys()) {\n detectCycle(name, defs, refsOf, reachesCycle, defPos.get(name) ?? somewhere, out);\n }\n\n // Blank #set lines to same-length whitespace so ref offsets still map to `text`\n // (a bare removal would shift every later column).\n const body = text.replace(/^[ \\t]*#(?:set|def)[ \\t]+%\\w+%[ \\t]*=[ \\t]*.*?$/gmu, (m) => m.replace(/[^\\n]/g, ' '));\n const seen = new Set<string>();\n const undefinedAt = (name: string, offset: number, length: number): void => {\n const key = name.toLowerCase();\n if (defs.has(key) || knownSet.has(key) || seen.has(key)) return;\n seen.add(key);\n out.push(warn('variable.undefined', `Variable '${name}' is not defined — may be a runtime variable.`,\n { ...span(idx, offset, length), data: { name } }));\n };\n for (const m of body.matchAll(/%(\\w+)%/gu)) undefinedAt(m[1] ?? '', m.index ?? 0, m[0].length);\n for (const m of body.matchAll(/\\{\\?!?([A-Za-z_]\\w*)\\?/gu)) {\n undefinedAt(m[1] ?? '', (m.index ?? 0) + m[0].indexOf(m[1] ?? ''), (m[1] ?? '').length);\n }\n}\n\n/**\n * Names from which a cycle of length ≥ 2 is reachable, over the graph name → defined\n * refs with self-edges excluded — exactly the edges the reporting walk can traverse\n * (it skips `ref === current`, and a pure self-loop is `variable.self-reference`).\n *\n * This is the prune that makes the walk affordable, and it is output-neutral by\n * construction: a report fires only when the walk meets a name already on its path,\n * which is a cycle the met name lies on — so a subtree in which no name reaches any\n * cycle cannot emit, and skipping it changes nothing. Without the prune every root\n * re-walked its whole subgraph (a 400-definition chain took hundreds of milliseconds,\n * and a converging diamond re-explored shared subtrees exponentially — a one-kilobyte\n * template validate() never returned from). One iterative colour walk, computed once.\n */\nfunction namesThatReachACycle(defs: Map<string, string>, refsOf: Map<string, string[]>): Set<string> {\n const GREY = 1;\n const BLACK = 2;\n const color = new Map<string, number>();\n const reaches = new Set<string>();\n\n interface Frame { name: string; refs: string[]; i: number }\n for (const root of defs.keys()) {\n if (color.has(root)) continue;\n const stack: Frame[] = [{ name: root, refs: refsOf.get(root) ?? [], i: 0 }];\n color.set(root, GREY);\n while (stack.length > 0) {\n const top = stack[stack.length - 1]!;\n if (top.i < top.refs.length) {\n const ref = top.refs[top.i]!;\n top.i += 1;\n if (ref === top.name || !defs.has(ref)) continue;\n const c = color.get(ref);\n if (c === GREY) reaches.add(top.name); // back edge — top sits on a cycle\n else if (c === BLACK) { if (reaches.has(ref)) reaches.add(top.name); }\n else {\n stack.push({ name: ref, refs: refsOf.get(ref) ?? [], i: 0 });\n color.set(ref, GREY);\n }\n } else {\n stack.pop();\n color.set(top.name, BLACK);\n if (stack.length > 0 && reaches.has(top.name)) reaches.add(stack[stack.length - 1]!.name);\n }\n }\n }\n return reaches;\n}\n\n/**\n * The reporting walk, exactly the recursive one it replaces: depth-first over a\n * value's references in order, one report per frame that meets a name already on\n * the path (the frame then abandons its remaining references; siblings continue\n * from the parent). Iterative so a definition chain as deep as the document cannot\n * overflow the call stack; the shared path array is pushed/popped instead of copied\n * per step, and membership is a Set — the array `includes` plus the per-step copy\n * made one 1600-definition cycle cost tens of seconds.\n */\nfunction detectCycle(\n root: string,\n defs: Map<string, string>,\n refsOf: Map<string, string[]>,\n reachesCycle: Set<string>,\n rootPos: Pos,\n out: Diagnostic[],\n): void {\n if (!reachesCycle.has(root)) return; // the root frame could only report ref === root, which it skips\n\n interface Frame { name: string; refs: string[]; i: number }\n const path: string[] = [root];\n const onPath = new Set<string>([root]);\n const stack: Frame[] = [{ name: root, refs: refsOf.get(root) ?? [], i: 0 }];\n\n const leave = (frame: Frame): void => {\n stack.pop();\n onPath.delete(frame.name);\n path.pop();\n };\n\n while (stack.length > 0) {\n const top = stack[stack.length - 1]!;\n if (top.i >= top.refs.length) {\n leave(top);\n continue;\n }\n const ref = top.refs[top.i]!;\n top.i += 1;\n if (ref === top.name) continue; // self-reference already reported\n if (onPath.has(ref)) {\n out.push(err('variable.circular-reference', `Circular variable reference: ${[...path, ref].join(' → ')}.`, rootPos));\n leave(top); // the recursive walk returned from the whole frame here\n continue;\n }\n if (defs.has(ref) && reachesCycle.has(ref)) {\n stack.push({ name: ref, refs: refsOf.get(ref) ?? [], i: 0 });\n onPath.add(ref);\n path.push(ref);\n }\n }\n}\n\n/** Unknown `#include` targets — only when a slug list is supplied. Raw `/m` scan. */\nfunction checkIncludeTargets(text: string, idx: LineIndex, known: readonly string[], out: Diagnostic[]): void {\n const set = new Set(known);\n INCLUDE_RE.lastIndex = 0;\n for (const m of text.matchAll(INCLUDE_RE)) {\n const ref = m[1] ?? '';\n if (!set.has(ref)) {\n const refOffset = (m.index ?? 0) + m[0].indexOf('\"') + 1; // inside the quotes\n out.push(err('include.unknown-target', `#include target '${ref}' does not match any known template.`,\n { ...span(idx, refOffset, ref.length), data: { target: ref } }));\n }\n }\n}\n","/**\n * Variable / #set / #include enumeration for `extract()` (spec §9.2).\n *\n * Raw-text scan (like the validator) rather than an AST walk, so it is complete:\n * it catches `%var%` inside a `{plural <count>: …}` count slot and inside a\n * `[…]` permutation body — both of which the AST leaves as raw strings. The\n * `#set` definition target (`#set %name% =` LHS) is a *definition*, not a\n * reference, so it is stripped before collecting `refs`.\n *\n * Variable names (`refs`, `sets`) are LOWER-CASED — the engine's variable\n * identity is case-insensitive, so cross-referencing sets against refs (the\n * two-phase-include / host-provisioning use) works. `includes` slugs are left\n * as authored (host-resolved, not case-folded). Arrays are de-duplicated;\n * order is insertion (the corpus compares order-normalized).\n *\n * NOTE (best-effort on malformed input): the conditional-name scan keys off the\n * `{?NAME?` prefix without requiring the brace to close, so an unclosed\n * `{?foo?…` yields a phantom `foo` ref. Acceptable for an extraction API.\n */\nimport { stripComments } from './parser';\n\nexport interface ExtractResult {\n refs: string[];\n sets: string[];\n defs: string[];\n includes: string[];\n}\n\n// Directives use [ \\t] (single-line), matching the parser's DIRECTIVE_RE — NOT \\s, which would\n// let a malformed multi-line directive be read as a definition.\nconst SET_DEF_RE = /^[ \\t]*#set[ \\t]+%(\\w+)%[ \\t]*=/gmu;\nconst DEF_DEF_RE = /^[ \\t]*#def[ \\t]+%(\\w+)%[ \\t]*=/gmu;\nconst DEFINITION_LHS_RE = /^[ \\t]*#(?:set|def)[ \\t]+%\\w+%[ \\t]*=/gmu;\n// The gap class is spelled out because no dialect's `\\s` is this set — PHP's under /u is\n// UCP-Unicode (measured, #55), not the ASCII this comment once claimed. Corpus-pinned.\nconst INCLUDE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\nconst VARIABLE_RE = /%(\\w+)%/gu;\nconst CONDITIONAL_REF_RE = /\\{\\?!?([A-Za-z_]\\w*)\\?/gu;\n\nexport function extractFromSource(src: string): ExtractResult {\n const text = stripComments(src);\n\n const sets = collect(text, SET_DEF_RE, true);\n const defs = collect(text, DEF_DEF_RE, true);\n const includes = collect(text, INCLUDE_RE, false);\n\n // Drop each `#set`/`#def … =` LHS (keep the value) so a definition target is not a ref. Missing\n // the `#def` half here would report every definition name as a phantom reference.\n const body = text.replace(DEFINITION_LHS_RE, '');\n const refs = new Set<string>();\n addAll(refs, body, VARIABLE_RE, true);\n addAll(refs, body, CONDITIONAL_REF_RE, true);\n\n return { refs: [...refs], sets, defs, includes };\n}\n\nfunction collect(text: string, re: RegExp, fold: boolean): string[] {\n const seen = new Set<string>();\n addAll(seen, text, re, fold);\n return [...seen];\n}\n\nfunction addAll(target: Set<string>, text: string, re: RegExp, fold: boolean): void {\n for (const m of text.matchAll(re)) {\n const value = m[1];\n if (value !== undefined && value !== '') target.add(fold ? value.toLowerCase() : value);\n }\n}\n","/**\n * Error hierarchy for @spintax/core (spec §9.3 — minimal, not a taxonomy).\n * `render()` throws these only on programmer error, never on template content.\n */\n\n/** Base class for programmer-error throws from render(). */\nexport class SpintaxError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SpintaxError';\n }\n}\n\n/** A host-injected includeResolver itself threw. */\nexport class IncludeResolverError extends SpintaxError {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = 'IncludeResolverError';\n if (options && 'cause' in options) {\n (this as { cause?: unknown }).cause = options.cause;\n }\n }\n}\n\n// NOTE: there is deliberately NO MaxDepthExceededError. Exceeding maxDepth\n// (circular / too-deep #include, runaway variable recursion) is LENIENT — the\n// guard resolves to '' rather than throwing, matching the plugin (which logs +\n// returns ''). render() throwing on a depth breach would break the lenient\n// contract, so no such error type is part of the public surface (§9.2/§9.3).\n\n/** An Ast produced by an incompatible engine version was passed back in. */\nexport class AstVersionError extends SpintaxError {\n constructor(message: string) {\n super(message);\n this.name = 'AstVersionError';\n }\n}\n\n/** Thrown by not-yet-implemented ops / node kinds until the engine lands. */\nexport class NotImplementedError extends SpintaxError {\n constructor(what: string) {\n super(`${what} is not implemented yet.`);\n this.name = 'NotImplementedError';\n }\n}\n","/**\n * Tree-walk renderer with the plugin's staged semantics layered on (parity with\n * Renderer::process_template). Not a naive walk — the deterministic stages are\n * reproduced in order:\n * - #set is a global pre-pass (parser) → setDefs; those enum values are\n * COLLAPSED ONCE here (buildVars), skipping values with `{?`/`{plural ` (they\n * reference vars and defer to the body) — plugin Stage 4b.\n * - variables resolve against the merged map (runtime context > #set); a value\n * that itself contains constructs is re-parsed and rendered (recursive, depth\n * capped) — this covers conditionals/plurals introduced by a variable value\n * (Stages 6b–6c), so a separate pre/post conditional pass isn't needed.\n * - conditionals test truthiness against the raw var map; plurals resolve the\n * count (vars already expanded) then pick the bucket, lenient fullwidth\n * fallback (Stage 6d, after vars).\n * - #include (post-tree string pass) and post-process are later PRs.\n *\n * RNG note: cross-engine RNG-sequence parity is a non-goal (§3.2). Enumerations\n * render outer-first and LAZILY (only the picked branch's nested RNG is used) vs\n * the plugin's eager innermost-out; corpus-safe because deterministic nested-enum\n * cases use order-independent sequences. Permutation matches the plugin's exact\n * pick→Fisher-Yates, so its rng-strategy cases are exact.\n */\nimport type { Node, ParsedAst, PermutationNode, PluralNode, ConditionalNode } from './ast';\nimport { IncludeResolverError } from './errors';\nimport { parseSequence, parseTemplate, recognizeConditional } from './parser';\nimport { normalizeBaseLang, pluralArity, pluralFor } from './plurals';\nimport type { Rng } from './rng';\n\nconst MAX_VARIABLE_DEPTH = 50;\n// ASCII whitespace only, spelled out — no dialect's `\\s` is this set. This comment used to\n// claim PHP's `\\s` under /u is ASCII; measured (#55), it is the opposite: /u turns on\n// PCRE2_UCP, so PHP matched NBSP and all of \\p{Z} here until it spelled the class out too.\n// The contract is this regex, pinned by the corpus (extract/include-*).\nconst INCLUDE_LINE_RE = /^[ \\t]*#include[ \\t\\n\\r\\f\\x0B]+\"([^\"]+)\"[ \\t\\n\\r\\f\\x0B]*$/gmu;\n\n/** Document-level render context (threads through nested #include resolution). */\n/**\n * A `{plural …}` block the renderer could not resolve, reported through\n * {@link RenderCtx.onPluralError}. Observation only — the render still degrades\n * exactly as it always has (§0.1 lenient contract); the host decides whether a\n * report is fatal. Mirrors the plugin's `on_error` callable.\n */\nexport interface PluralIssue {\n /**\n * `plural.nested-brackets` and `plural.arity` are the same codes `validate()`\n * emits. `plural.count` has no validate counterpart on purpose — an unresolved\n * count is a runtime-value fact, invisible to static analysis.\n */\n readonly code: 'plural.nested-brackets' | 'plural.arity' | 'plural.count';\n readonly message: string;\n /** The construct as the renderer saw it, AFTER variable expansion. */\n readonly construct: string;\n /** Normalized base language the arity was judged against. */\n readonly locale: string;\n /** Arity verdicts only. */\n readonly expected?: number;\n readonly got?: number;\n}\n\nexport interface RenderCtx {\n /** Runtime/host variable map — inherited by child #includes (NOT parent #set). */\n readonly runtimeContext: Readonly<Record<string, string>>;\n readonly rng: Rng;\n readonly locale: string;\n readonly resolver: ((ref: string) => string | null) | undefined;\n readonly maxDepth: number;\n /** #include ref chain for circular-reference detection. */\n readonly includeStack: readonly string[];\n /** Optional observer for unresolvable plural blocks; never affects output. */\n readonly onPluralError: ((issue: PluralIssue) => void) | undefined;\n}\n\n/**\n * Render a parsed template: build vars → roll `#def` → tree-walk → resolve `#includes`\n * (post-tree string pass, like the plugin's Stage 9 resolve_nested, AFTER\n * enum/perm). Post-process (Stage 10) is layered on by the public render().\n */\nexport function renderAst(ast: ParsedAst, ctx: RenderCtx): string {\n const base = buildVars(ast.setDefs, ctx.runtimeContext);\n const walkOpts = {\n rng: ctx.rng,\n locale: ctx.locale,\n depth: 0,\n onPluralError: ctx.onPluralError,\n };\n // The roll happens here and not inside buildVars: a definition is rendered against the FULL\n // context, globals and runtime included, so it must wait until that context exists.\n const vars =\n Object.keys(ast.defDefs).length > 0\n ? { ...base, ...rollDefinitions(ast.defDefs, base, ctx.runtimeContext, walkOpts) }\n : base;\n const text = renderNodes(ast.nodes, { ...walkOpts, vars });\n return ctx.resolver ? resolveIncludes(text, ctx) : text;\n}\n\n/**\n * Replace each `#include \"ref\"` (line-anchored) with the host-resolved child\n * template, rendered with a CHILD scope: inherits runtime context but NOT the\n * parent's #set locals (plugin `for_child_render`). Circular refs / runaway\n * depth resolve to '' (lenient); a resolver that throws surfaces as\n * IncludeResolverError (programmer error).\n *\n * NOTE: cycles are detected by the ref STRING (the engine has no template\n * identity beyond the host-supplied ref, §4.1), so two aliased refs for one\n * template aren't seen as a cycle and recurse until `maxDepth`. `maxDepth` also\n * caps deep ACYCLIC chains (silently → ''), a guard the plugin lacks.\n */\nfunction resolveIncludes(text: string, ctx: RenderCtx): string {\n INCLUDE_LINE_RE.lastIndex = 0;\n return text.replace(INCLUDE_LINE_RE, (_m, ref: string): string => {\n if (ctx.includeStack.includes(ref) || ctx.includeStack.length >= ctx.maxDepth) return '';\n let included: string | null;\n try {\n included = ctx.resolver!(ref);\n } catch (cause) {\n throw new IncludeResolverError(`includeResolver threw for \"${ref}\"`, { cause });\n }\n if (included === null) return '';\n return renderAst(parseTemplate(included), {\n ...ctx,\n runtimeContext: ctx.runtimeContext, // child inherits runtime, not parent #set\n includeStack: [...ctx.includeStack, ref],\n });\n });\n}\n\nexport interface RenderInternalOptions {\n /** Merged variable map, keys LOWER-CASED (runtime context wins over #set). */\n readonly vars: Readonly<Record<string, string>>;\n readonly rng: Rng;\n /** Plural-bucket locale (raw; normalized per lookup). Empty ⇒ default 2-form. */\n readonly locale: string;\n /** Variable re-processing depth (guards runaway/circular expansion). */\n readonly depth: number;\n /** Optional observer for unresolvable plural blocks; never affects output. */\n readonly onPluralError: ((issue: PluralIssue) => void) | undefined;\n}\n\n/**\n * Build the merged variable map: `#set` values go in RAW, then the runtime context overlays them\n * (and wins). Context keys are lowercased.\n *\n * A `#set` is a macro — its value is re-parsed and re-rendered at every `%var%` reference, so any\n * brackets it holds re-roll each time. Nothing is resolved here. (Until 0.3.0 this collapsed\n * enumeration-valued `#set`s once at set-time; that behaviour moved to `#def`.)\n */\nexport function buildVars(\n setDefs: Readonly<Record<string, string>>,\n context: Readonly<Record<string, string>>,\n): Record<string, string> {\n const vars: Record<string, string> = {};\n for (const [name, value] of Object.entries(setDefs)) {\n vars[name] = value;\n }\n for (const [name, value] of Object.entries(context)) {\n vars[name.toLowerCase()] = value;\n }\n return vars;\n}\n\n/**\n * Render each `#def` value ONCE and return the frozen results, to be merged over `vars`.\n *\n * A definition value is rendered as if it were a miniature body — the same tree walk the document\n * gets — and the result is held for every reference. This runs only after the merged context\n * exists, so a definition can read globals and runtime variables; a runtime variable of the same\n * name outranks it and the definition is then never rolled at all.\n *\n * Values are rendered in dependency order, and that order follows aliases: a `#def` can reach\n * another `#def` through a `#set`, which is expanded at reference time and therefore invisible in\n * the first definition's own text.\n */\nexport function rollDefinitions(\n defDefs: Readonly<Record<string, string>>,\n vars: Readonly<Record<string, string>>,\n context: Readonly<Record<string, string>>,\n opts: Omit<RenderInternalOptions, 'vars'>,\n): Record<string, string> {\n const outranked = new Set(Object.keys(context).map((key) => key.toLowerCase()));\n const rolled: Record<string, string> = {};\n\n // The alias map is every macro value a definition can see, minus the definitions that will\n // actually be rolled — a `#def` shadows a same-named global, and hopping through the shadowed\n // value computes the wrong graph. A definition the runtime outranks is NOT removed: it is never\n // rolled, so the runtime value is what really gets substituted and the graph must follow it.\n const aliases: Record<string, string> = {};\n for (const [name, value] of Object.entries(vars)) {\n if (name in defDefs && !outranked.has(name)) continue;\n aliases[name] = value;\n }\n\n for (const name of orderDefinitions(defDefs, aliases)) {\n if (outranked.has(name)) continue;\n const value = defDefs[name] ?? '';\n rolled[name] = renderNodes(parseSequence(value), { ...opts, vars: { ...vars, ...rolled } });\n }\n\n return rolled;\n}\n\n/** Definition names, dependencies first. A cycle cannot be ordered, so its members come last. */\nfunction orderDefinitions(\n defDefs: Readonly<Record<string, string>>,\n aliases: Readonly<Record<string, string>>,\n): string[] {\n const names = Object.keys(defDefs);\n const blocked = new Map<string, Set<string>>();\n\n for (const name of names) {\n const reached = referencedNames(defDefs[name] ?? '', aliases);\n blocked.set(name, new Set(names.filter((candidate) => reached.has(candidate))));\n }\n\n const ordered: string[] = [];\n let pending = names;\n\n while (pending.length > 0) {\n const ready = pending.filter((name) => {\n const deps = blocked.get(name);\n return !deps || ![...deps].some((dep) => dep !== name && pending.includes(dep));\n });\n if (ready.length === 0) return [...ordered, ...pending];\n ordered.push(...ready);\n pending = pending.filter((name) => !ready.includes(name));\n }\n\n return ordered;\n}\n\n/** Every variable name a value reaches, hopping through macro (alias) values to a fixpoint. */\nfunction referencedNames(value: string, aliases: Readonly<Record<string, string>>): Set<string> {\n const seen = new Set<string>();\n const queue = directReferences(value);\n\n while (queue.length > 0) {\n const name = queue.shift() as string;\n if (seen.has(name)) continue;\n seen.add(name);\n const alias = aliases[name];\n if (alias !== undefined) queue.push(...directReferences(alias));\n }\n\n return seen;\n}\n\n/** The `%var%` names written literally in a string, lowercased. */\nfunction directReferences(text: string): string[] {\n return [...text.matchAll(/%(\\w+)%/gu)].map((match) => (match[1] ?? '').toLowerCase());\n}\n\nexport function renderNodes(nodes: readonly Node[], opts: RenderInternalOptions): string {\n let out = '';\n for (const node of nodes) out += renderNode(node, opts);\n return out;\n}\n\nfunction renderNode(node: Node, opts: RenderInternalOptions): string {\n switch (node.type) {\n case 'literal':\n return node.value;\n case 'variable':\n return resolveVariable(node.name, opts);\n case 'enumeration':\n return renderEnumeration(node.options, opts);\n case 'permutation':\n return renderPermutation(node, opts);\n case 'conditional':\n return renderConditional(node, opts);\n case 'plural':\n return renderPlural(node, opts);\n }\n}\n\n/** `min === max` short-circuits WITHOUT consuming the RNG (plugin `random_int`). */\nfunction randomInt(rng: Rng, min: number, max: number): number {\n return min === max ? min : rng(min, max);\n}\n\n/**\n * Resolve a `%var%`. A value containing constructs is re-parsed and rendered\n * (recursive, depth-capped) so nested vars / conditionals / plurals introduced by\n * the value are resolved; a plain value is returned as-is; unresolved ⇒ verbatim.\n */\nfunction resolveVariable(name: string, opts: RenderInternalOptions): string {\n const value = opts.vars[name.toLowerCase()];\n if (value === undefined) return `%${name}%`;\n // At the cap, stop expanding (lenient: partial output, never throws — unlike the\n // plugin which throws→'' on runaway; §9.2 render never throws on content).\n if (opts.depth >= MAX_VARIABLE_DEPTH || !/[{[%]/u.test(value)) return value;\n // parseSequence, NOT parseTemplate: a value must not be re-comment-stripped or\n // re-#set-extracted (those are one-time body passes in the plugin).\n return renderNodes(parseSequence(value), { ...opts, depth: opts.depth + 1 });\n}\n\n/** Variable-expansion ONLY (plugin `expand_variables` fixpoint) — leaves enums/perms literal. */\nfunction expandVarsOnly(text: string, opts: RenderInternalOptions): string {\n let out = text;\n for (let i = 0; i < MAX_VARIABLE_DEPTH; i += 1) {\n let changed = false;\n out = out.replace(/%(\\w+)%/gu, (m, name: string): string => {\n const value = opts.vars[name.toLowerCase()];\n if (value === undefined) return m;\n changed = true;\n return value;\n });\n if (!changed) break;\n }\n return out;\n}\n\n/** Truthy = the raw var value is set and has a non-whitespace char (plugin is_truthy). */\nfunction conditionalTakesThen(name: string, inverted: boolean, opts: RenderInternalOptions): boolean {\n const value = opts.vars[name.toLowerCase()];\n const baseTruthy = value !== undefined && /\\S/u.test(value);\n return inverted ? !baseTruthy : baseTruthy;\n}\n\nfunction renderConditional(node: ConditionalNode, opts: RenderInternalOptions): string {\n const truthy = conditionalTakesThen(node.name, node.inverted, opts);\n return renderNodes(truthy ? node.then : node.else, opts);\n}\n\n/**\n * Resolve conditionals in the plural COUNT slot, textually — the branch is\n * substituted, never rendered (spintax-js#67).\n *\n * Why this exists: the plugin runs its conditional stage over the whole text\n * before plurals, so `#set %n% = {?flag?1|2}` reaches the count slot as a plain\n * number and the block renders. This engine parses the count slot into a raw\n * string and expanded VARIABLES only, so the conditional survived, failed the\n * numeric test, and the block was ERASED — `validate()` meanwhile returned no\n * diagnostic at all, and `plural.count-macro` documents conditionals as exempt\n * *because* they resolve before plurals. Valid input, silently deleted output.\n *\n * Textual, and only the taken branch's text, because the stage order still holds\n * around it: enums and permutations resolve AFTER plurals, so a branch yielding\n * `{a|b}` must reach the numeric test as `{a|b}` and erase the block, exactly as\n * the plugin does. Rendering the branch would spin it into `a` and invent a\n * count neither engine has.\n *\n * The FORM slot is deliberately not touched: there the engines genuinely\n * disagree and no side has been chosen yet (spintax-js#67).\n *\n * Iterative, over spans, for two reasons paid for in review: recursing into the\n * taken branch made `render()` throw `RangeError` at ~9000 levels of nesting —\n * §9.2 says render never throws on content, and the parsers were made iterative\n * for this exact reason — and re-scanning per `{?` was quadratic (see\n * {@link matchBraces}). Both are reachable from template text through the live\n * public Worker.\n */\nfunction resolveCountConditionals(text: string, opts: RenderInternalOptions): string {\n if (!text.includes('{?')) return text;\n\n const close = matchBraces(text);\n const out: string[] = [];\n // Spans of `text` still to emit, in order. A taken branch is a SPAN of the same\n // string, never a copy, and the untaken one is skipped — so every character is\n // visited at most once and the pass stays linear.\n const pending: [number, number][] = [[0, text.length]];\n\n while (pending.length > 0) {\n const segment = pending.pop() as [number, number];\n const segEnd = segment[1];\n let i = segment[0];\n\n while (i < segEnd) {\n const open = text.indexOf('{?', i);\n // `{?` found past this span belongs to the text around it, not to this span.\n if (open === -1 || open + 1 >= segEnd) {\n out.push(text.slice(i, segEnd));\n break;\n }\n\n // A close outside the span is no close at all: the branch it would reach\n // into is not ours to read.\n const shut = close[open] ?? -1;\n const head = shut === -1 || shut >= segEnd ? null : recognizeConditional(text, open + 1, shut);\n if (head === null) {\n // Unclosed, or `{?` that is not a conditional — a malformed one is an\n // enumeration to the parser, and enumerations are not this pass's business.\n out.push(text.slice(i, Math.min(open + 2, segEnd)));\n i = open + 2;\n continue;\n }\n\n out.push(text.slice(i, open));\n const branchEnd = head.sepIndex < 0 ? shut : head.sepIndex;\n const [from, to] = conditionalTakesThen(head.name, head.inverted, opts)\n ? [head.bodyStart, branchEnd]\n : [head.sepIndex < 0 ? shut : head.sepIndex + 1, shut];\n // Continuation first, branch second: the stack pops the branch back out\n // ahead of it, which is what keeps the output in source order.\n pending.push([shut + 1, segEnd]);\n pending.push([from, to]);\n break;\n }\n }\n\n return out.join('');\n}\n\n/**\n * Match `{` to `}` across the whole string in ONE pass — index of the closing\n * brace for every opening one, or -1.\n *\n * Equivalent to calling `findMatchingClose` per `{`, and that is the point: the\n * per-brace call rescans to the end of the string every time it fails to match,\n * so an unbalanced count slot (legal — only the whole `{plural …}` block has to\n * balance, and the slot is cut at the first `:`) made this pass quadratic. A\n * 78 KB slot took 3 seconds, and the public Worker renders untrusted templates.\n */\nfunction matchBraces(text: string): Int32Array {\n const close = new Int32Array(text.length).fill(-1);\n const opens: number[] = [];\n\n for (let i = 0; i < text.length; i += 1) {\n const ch = text.charAt(i);\n if (ch === '{') {\n opens.push(i);\n } else if (ch === '}') {\n const open = opens.pop();\n if (open !== undefined) close[open] = i;\n }\n }\n\n return close;\n}\n\n/**\n * Plural agreement (Stage 6d — after variable-expansion, before enum/perm). The\n * count/forms are expanded with VARIABLES ONLY, so the checks (nested-bracket,\n * numeric erase, arity) see the same state the plugin does — enums/perms still\n * literal. Order: bracket check → numeric erase → arity → bucket pick. The two\n * error paths emit the (var-expanded) construct verbatim with fullwidth braces.\n */\nfunction renderPlural(node: PluralNode, opts: RenderInternalOptions): string {\n const countRaw = resolveCountConditionals(expandVarsOnly(node.countRaw, opts), opts);\n const formsRaw = expandVarsOnly(node.formsRaw, opts);\n const base = normalizeBaseLang(opts.locale);\n const report = (issue: PluralIssue): void => opts.onPluralError?.(issue);\n\n if (/[{}[\\]]/u.test(formsRaw)) {\n report({\n code: 'plural.nested-brackets',\n message:\n 'Plural form slot contains nested spintax brackets; extract via #def first — a #set is '\n + 'substituted verbatim and would put the brackets straight back.',\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n });\n return fullwidthVerbatim(countRaw, formsRaw);\n }\n\n const count = phpTrim(countRaw);\n if (!/^-?\\d+$/u.test(count)) {\n // Erasing leaves no trace in the output, so this report is the ONLY way a\n // host can tell an intentionally-empty sentence from an unsubstituted %Var%.\n report({\n code: 'plural.count',\n message: `Plural count slot is empty or non-numeric (${JSON.stringify(count)}); block erased.`,\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n });\n return '';\n }\n\n const forms = formsRaw.split('|').map((f) => phpTrim(f));\n if (forms.length !== pluralArity(base)) {\n report({\n code: 'plural.arity',\n message: `Plural has ${forms.length} form(s); locale \"${base}\" takes ${pluralArity(base)}.`,\n construct: rawConstruct(countRaw, formsRaw),\n locale: base,\n expected: pluralArity(base),\n got: forms.length,\n });\n return fullwidthVerbatim(countRaw, formsRaw);\n }\n\n // The picked form re-enters the pipeline (its enums/perms resolve after plurals).\n const picked = pluralFor(base, Number.parseInt(count, 10), forms);\n return renderNodes(parseSequence(picked), opts);\n}\n\n/** The construct as the renderer saw it — ASCII braces, for reports and logs. */\nfunction rawConstruct(countRaw: string, formsRaw: string): string {\n return `{plural ${countRaw}:${formsRaw}}`;\n}\n\n/** Emit the plural construct verbatim with fullwidth braces so later passes leave it alone. */\nfunction fullwidthVerbatim(countRaw: string, formsRaw: string): string {\n return rawConstruct(countRaw, formsRaw).replace(/\\{/gu, '{').replace(/\\}/gu, '}');\n}\n\n/** Pick one option (outer-first) and render it. */\nfunction renderEnumeration(options: readonly (readonly Node[])[], opts: RenderInternalOptions): string {\n if (options.length === 0) return '';\n const picked = options[randomInt(opts.rng, 0, options.length - 1)];\n return picked ? renderNodes(picked, opts) : '';\n}\n\ninterface Element {\n text: string;\n sep: string | null;\n}\n\nfunction renderPermutation(node: PermutationNode, opts: RenderInternalOptions): string {\n const elements: Element[] = node.options.map((o) => ({\n text: renderNodes(o.nodes, opts),\n sep: o.separator,\n }));\n const total = elements.length;\n if (total === 0) return '';\n\n const { config } = node;\n const hasMin = config.minsize !== null;\n const hasMax = config.maxsize !== null;\n let min: number;\n let max: number;\n if (hasMin && hasMax) {\n min = config.minsize as number;\n max = config.maxsize as number;\n } else if (hasMin) {\n min = config.minsize as number;\n max = total;\n } else if (hasMax) {\n min = 1;\n max = config.maxsize as number;\n } else {\n min = total;\n max = total;\n }\n min = Math.max(1, Math.min(min, total));\n max = Math.max(min, Math.min(max, total));\n\n const pick = randomInt(opts.rng, min, max);\n shuffle(elements, opts.rng);\n return joinWithSeparators(elements.slice(0, pick), config.sep, config.lastsep ?? config.sep);\n}\n\n/** Fisher-Yates, matching the plugin: i = n-1 … 1, j = randomInt(0, i), swap. */\nfunction shuffle(arr: Element[], rng: Rng): void {\n for (let i = arr.length - 1; i > 0; i -= 1) {\n const j = randomInt(rng, 0, i);\n const tmp = arr[i] as Element;\n arr[i] = arr[j] as Element;\n arr[j] = tmp;\n }\n}\n\nfunction joinWithSeparators(elements: readonly Element[], globalSep: string, globalLastsep: string): string {\n const count = elements.length;\n if (count === 0) return '';\n if (count === 1) return (elements[0] as Element).text;\n\n let out = (elements[0] as Element).text;\n for (let i = 1; i < count; i += 1) {\n const el = elements[i] as Element;\n const sep = el.sep ?? (i === count - 1 ? globalLastsep : globalSep);\n out += padSeparator(sep) + el.text;\n }\n return out;\n}\n\n/** Purely-alphabetic separators get space-padded; others pass through (plugin). */\nfunction padSeparator(sep: string): string {\n const trimmed = phpTrim(sep);\n if (trimmed === '') return sep;\n if (/^\\p{L}+$/u.test(trimmed)) return ` ${trimmed} `;\n return sep;\n}\n\nconst PHP_LTRIM_RE = /^[ \\t\\n\\r\\0\\x0B]+/u;\nconst PHP_RTRIM_RE = /[ \\t\\n\\r\\0\\x0B]+$/u;\nfunction phpTrim(s: string): string {\n return s.replace(PHP_LTRIM_RE, '').replace(PHP_RTRIM_RE, '');\n}\n","/**\n * Cosmetic post-process — faithful port of the plugin's `Parser::post_process`\n * (parity-target §5). Order matters: URLs / emails / domains / decimals /\n * abbreviations are shielded to `\\x00…\\x00` placeholders FIRST so the\n * spacing/capitalization passes don't corrupt them, then restored + trimmed.\n *\n * This is the COSMETIC stage (gated by `postProcess`). The mandatory neutralize\n * safety-restore (§6) is separate (M2e) and always runs.\n */\n\n// Single-token abbreviations (case-insensitive) that would otherwise look like a\n// sentence end. Multi-dot forms (т.д.) are handled by the 5a regex.\nconst SINGLE_ABBREVS = [\n // Russian editorial / address / unit shorthands.\n 'соц', 'эл', 'см', 'ср', 'ст', 'ул', 'пр', 'пер', 'г', 'р', 'руб', 'коп',\n 'тыс', 'млн', 'млрд', 'трлн', 'доп', 'напр', 'прим', 'изд', 'обл', 'респ',\n 'стр', 'табл', 'рис', 'мин', 'макс', 'тел', 'факс',\n // English titles / business suffixes / editorial.\n 'etc', 'vs', 'Mr', 'Mrs', 'Ms', 'Dr', 'Prof', 'Sr', 'Jr', 'Inc', 'Ltd', 'Co',\n 'Corp', 'No', 'St', 'Ave', 'Blvd',\n];\n\n// ASCII whitespace only — PHP `\\s`/`\\b` under /u (no PCRE_UCP) are ASCII, while\n// JS `\\s` is Unicode. Using `\\s` would diverge around NBSP / thin spaces, so every\n// whitespace class below is the explicit ASCII set. (`\\b` in JS is already ASCII.)\nconst WS = ' \\\\t\\\\r\\\\n\\\\f\\\\x0B';\nconst S = `[${WS}]`;\n\nconst DOMAIN_PART =\n '(?:(?:(?:xn--)?[\\\\p{L}\\\\p{N}]+(?:-[\\\\p{L}\\\\p{N}]+)*)\\\\.)+(?:xn--[a-z0-9\\\\-]{2,59}|[\\\\p{L}][\\\\p{L}\\\\p{N}-]{1,62})';\n/**\n * URIs — `https?`/`ftp` (with a `//` authority) and `mailto:`/`tel:` (without one) — shielded\n * in ONE pass, deliberately.\n *\n * They used to be two passes, URLs then `mailto:`/`tel:`. A URI body runs to the first\n * delimiter, so the two match sets overlap whenever one URI contains the other's scheme, and\n * with two passes the second one runs into a placeholder the first already minted:\n * `mailto:sales@x.com?body=see%20https://shop.x.com/cart` shielded the URL first, then stored\n * a `mailto:` value with URL_0's key inside it. Restore was past that key by the time the value\n * landed, so the engine emitted a raw U+0000 — illegal in XML, U+FFFD to an HTML parser,\n * rejected by Postgres `text`, and a live key again as soon as an edit detaches it from the\n * prefix that was shielding it (spintax-js#53).\n *\n * Neither pass order fixes that, because whichever runs second is the one that gets split:\n * ordering `mailto:` first instead only moves the damage onto a URL whose path carries a\n * `mailto:`, where the leading half then loses its trailing dot to the punctuation pass\n * (`https://x.io/a.mailto:…` → `https://x.io/a. mailto:…`). A single alternation has no second\n * pass to damage: the leftmost match wins and takes the whole token, whichever scheme it is.\n *\n * `\\x00` stays out of the body class regardless. Nothing is shielded yet when this pass runs,\n * so on ordinary input it never bites; it is there for a caller-supplied U+0000, which would\n * otherwise let a URI match run through the delimiters of a placeholder minted after it.\n */\nconst URI_BODY = `[^\\\\x00${WS}<>\"')\\\\]]`;\nconst URI_RE = new RegExp(`(?:(?:https?|ftp):\\\\/\\\\/|(?:mailto|tel):)${URI_BODY}+`, 'giu');\n// Which placeholder prefix a match gets. Kept distinct (URL vs URI) even though one pass mints\n// both: the prefixes are what the other engines' fixtures and #52's restore regex speak.\nconst MAILTEL_PREFIX_RE = /^(?:mailto|tel):/iu;\nconst EMAIL_RE = new RegExp(`[a-z0-9._%+\\\\-]+@${DOMAIN_PART}\\\\b`, 'giu');\nconst DOMAIN_RE = new RegExp(`\\\\b${DOMAIN_PART}\\\\b`, 'giu');\nconst DECIMAL_RE = /\\b\\d+\\.\\d+\\b/gu;\nconst MULTI_ABBR_RE = new RegExp(`\\\\b(?:\\\\p{L}{1,2}\\\\.${S}*){2,}`, 'gu');\nconst SINGLE_ABBR_RE = new RegExp(`(?<![\\\\p{L}\\\\p{N}])(?:${SINGLE_ABBREVS.join('|')})\\\\.(?=${S}|$|<)`, 'giu');\nconst TRAILING_PUNCT_RE = /([.,;:!]+)$/u;\n\n/**\n * SENTENCE OPENERS — the inverted marks that OPEN a Spanish question/exclamation.\n *\n * Every other European language only ever *closes* with punctuation, which is why the spacing and\n * capitalization passes below were written as if a sentence always begins with a letter. In Spanish\n * it does not: `¿cómo estás?` begins with `¿`, and the capitalizer — which upper-cases the first\n * *character* after a boundary — hits a mark that has no uppercase form and silently leaves the\n * real first letter lowercase.\n *\n * Named explicitly, and deliberately NOT widened to quotes/brackets/«»: those both open and close,\n * and capitalizing after them would mangle list markers (\"Elige. (a) primero\" → \"(A) primero\").\n * This constant encodes the language semantics of Spanish punctuation, not a general \"skip anything\n * that isn't a letter\" rule.\n */\nconst SENTENCE_OPENERS = '¿¡';\n/**\n * The LEAD — everything that can sit between a sentence boundary and the first letter: HTML tags,\n * sentence openers and whitespace, in any order and any number.\n *\n * A single optional opener is not enough. `¡¿Qué haces?!` — RAE's form for a sentence that is both\n * a question and an exclamation — opens with TWO marks, and the opened word is routinely wrapped in\n * markup (`<p>¿<a href=\"/ayuda\">Necesitas ayuda</a>?</p>`), which puts a tag AFTER the opener.\n * Whatever the lead fails to cover silently keeps a lowercase first letter.\n */\nconst LEAD = `(?:<[^>]+>|[${SENTENCE_OPENERS}]|${S})*`;\n\n// Spacing + capitalization (all ASCII-whitespace).\nconst SPACE_BEFORE_PUNCT_RE = new RegExp(`${S}+([,;:!?.])`, 'gu');\nconst SPACE_AFTER_COMMA_RE = new RegExp(`([,;:])(?!\\\\d)(?!${S}|$|<)`, 'gu');\n// A run of sentence punctuation is ONE sentence end, not several: \"...\" and \"?!\" have to survive\n// intact, so the space goes after the whole run. `(?![.!?])` is what completes the run — a greedy\n// `+` on its own still backtracks INTO it to satisfy the lookaheads, turning \"Wow!!!\" into\n// \"Wow!! !\". (JS has no possessive quantifiers, and PHP must match this shape exactly.)\nconst SPACE_AFTER_SENTENCE_RE = new RegExp(`([.!?]+)(?![.!?])(?!\\\\d)(?!${S}|$|<)`, 'gu');\n// An opener binds to the word it opens: \"¿ qué tal ?\" → \"¿qué tal?\". MUST run before the\n// capitalization passes, so they see the real first letter instead of a space.\nconst SPACE_AFTER_OPENER_RE = new RegExp(`([${SENTENCE_OPENERS}])${S}+`, 'gu');\nconst CAP_FIRST_RE = new RegExp(`^(${LEAD})(\\\\p{Ll})`, 'u');\nconst CAP_AFTER_SENTENCE_RE = new RegExp(`([.!?…])(${LEAD})(\\\\p{Ll})`, 'gu');\nconst CAP_AFTER_BLOCK_RE = new RegExp(\n `(<\\\\/?(?:p|h[1-6]|li|blockquote|div|td|th)[^>]*>${LEAD})(\\\\p{Ll})`,\n 'giu',\n);\nconst CAP_AFTER_BREAK_RE = new RegExp(`(\\\\n${LEAD})(\\\\p{Ll})`, 'gu');\n\nconst up = (ch: string): string => ch.toUpperCase();\n\n// The shield's placeholder prefixes, in one place: RESTORE_RE below is built from this\n// list, so a new shield pass cannot mint a key shape the single-pass restore fails to\n// recognise. Keep the two in step by construction, not by memory.\nconst SHIELD_PREFIXES = ['URL', 'URI', 'EMAIL', 'DOM', 'NUM', 'ABBR'] as const;\ntype ShieldPrefix = (typeof SHIELD_PREFIXES)[number];\nconst RESTORE_RE = new RegExp(`\\\\x00(?:${SHIELD_PREFIXES.join('|')})_\\\\d+\\\\x00`, 'gu');\n\n/**\n * Restore the shielded values (step 12).\n *\n * The reference form is one `split(key).join(value)` per key — a full scan of the text\n * per placeholder, so O(text × placeholders). Every URL, URI, email, domain, decimal and\n * abbreviation is shielded, so on shield-heavy output the placeholder count grows with\n * the text and this stage comes to dominate the render: 39 s on a 950 KB render, against\n * 0.07 s with `postProcess: false` (spintax-js#52).\n *\n * A single left-to-right pass is NOT the same function, because the loop is a repeated\n * SUBSTRING substitution and the pass is a token substitution. `split/join` rewrites every\n * occurrence of a key, not only the one the shield placed. Three shapes make them differ:\n * the caller's own text spells a key the shield goes on to mint; an unpaired `\\x00` from\n * the input pairs with a real placeholder's delimiter; and — needing no `\\x00` from the\n * caller at all — two adjacent placeholders sandwich caller text that spells a key, so one\n * token's CLOSING delimiter, that text, and the next token's OPENING delimiter form a\n * third occurrence of a key that really was minted. Delimiters are not owned by the token\n * that placed them.\n *\n * The guard therefore removes the `\\x00`-borne disagreements; it does not make the two\n * functions equal, and an earlier version of this comment claimed a proof that does not\n * hold (spintax-js#54). Measured over a 456 976-input differential sweep whose fragments\n * include bare key names: 13 266 inputs distinguish the two restores, 12 of them carrying\n * no `\\x00`. On every one of those 12 it is the LOOP that is wrong — it emits a raw U+0000\n * from `\\x00`-free input, wrecking two real tokens to serve a forged one — and the single\n * pass returns the text intact. So the fast path is not merely faster on the shape that\n * survives the guard; it is the answer we want there, and the guard's whole remaining\n * effect is the 13 254 `\\x00`-carrying inputs where the loop's reading is the defensible\n * one. Real text carries no `\\x00`, so the fast path is what actually runs.\n *\n * Neither path rescans a value it inserted, which is what makes them agree even if a stored\n * value ever came to contain another key. On `\\x00`-free input none can: URI_BODY excludes\n * `\\x00` and every other shield class is letters/digits/dots, so no match can span a\n * placeholder (spintax-js#53). The property is worth stating because it is the one an\n * ordering change could quietly take away.\n */\nfunction restore(text: string, input: string, placeholders: Map<string, string>): string {\n if (!input.includes('\\x00')) {\n return text.replace(RESTORE_RE, (key) => placeholders.get(key) ?? key);\n }\n let out = text;\n for (const [key, value] of placeholders) {\n out = out.split(key).join(value);\n }\n return out;\n}\n\nexport function postProcess(input: string): string {\n const placeholders = new Map<string, string>();\n let counter = 0;\n\n const store = (value: string, prefix: ShieldPrefix): string => {\n const key = `\\x00${prefix}_${counter}\\x00`;\n placeholders.set(key, value);\n counter += 1;\n return key;\n };\n const storeWithTrailingPunct = (value: string, prefix: ShieldPrefix): string => {\n const m = TRAILING_PUNCT_RE.exec(value);\n if (m) {\n const suffix = m[1] ?? '';\n const body = value.slice(0, value.length - suffix.length);\n return body === '' ? suffix : store(body, prefix) + suffix;\n }\n return store(value, prefix);\n };\n\n let text = input;\n\n // 1-5: shield. URIs go first and in one pass, so an overlapping pair is never split\n // (spintax-js#53), and always before EMAIL/DOMAIN, so the whole `mailto:` survives\n // instead of the address being carved out from under its prefix (spintax-js#41).\n text = text.replace(URI_RE, (m) =>\n storeWithTrailingPunct(m, MAILTEL_PREFIX_RE.test(m) ? 'URI' : 'URL'),\n );\n text = text.replace(EMAIL_RE, (m) => store(m, 'EMAIL'));\n text = text.replace(DOMAIN_RE, (m) => store(m, 'DOM'));\n text = text.replace(DECIMAL_RE, (m) => store(m, 'NUM'));\n text = text.replace(MULTI_ABBR_RE, (m) => store(m, 'ABBR'));\n text = text.replace(SINGLE_ABBR_RE, (m) => store(m, 'ABBR'));\n\n // 6: collapse duplicate spaces/tabs.\n text = text.replace(/[ \\t]{2,}/gu, ' ');\n\n // 7: punctuation spacing. Remove whitespace before punctuation, then add a\n // space after ,;: and after a RUN of .!? unless followed by a digit / space / end / tag.\n text = text.replace(SPACE_BEFORE_PUNCT_RE, '$1');\n text = text.replace(SPACE_AFTER_COMMA_RE, '$1 ');\n text = text.replace(SPACE_AFTER_SENTENCE_RE, '$1 ');\n // 7a: a Spanish opener binds to the word it opens. Before capitalization, deliberately.\n text = text.replace(SPACE_AFTER_OPENER_RE, '$1');\n\n // 8: capitalize the first letter (skipping leading HTML tags and sentence openers).\n text = text.replace(CAP_FIRST_RE, (_m, lead: string, ch: string) => lead + up(ch));\n // 9: capitalize after sentence punctuation (through HTML tags).\n text = text.replace(CAP_AFTER_SENTENCE_RE, (_m, p: string, gap: string, ch: string) => p + gap + up(ch));\n // 10: capitalize after block-level HTML tags.\n text = text.replace(CAP_AFTER_BLOCK_RE, (_m, tag: string, ch: string) => tag + up(ch));\n // 11: capitalize after line breaks.\n text = text.replace(CAP_AFTER_BREAK_RE, (_m, br: string, ch: string) => br + up(ch));\n\n // 12: restore placeholders, then trim.\n return restore(text, input, placeholders).trim();\n}\n","/**\n * The full render pipeline with an INJECTED rng — the seam shared by the public\n * render() (which seeds the rng from RenderOptions.seed) and the corpus harness\n * (which injects a fixture's `rng` strategy). Keeping the rng a parameter is what\n * lets the deterministic parity fixtures assert exact output.\n *\n * Order: strip stray sentinels → build vars, roll #def, tree-walk (+ #include) →\n * cosmetic post-process (if on) → mandatory neutralize safety-restore (always).\n */\nimport { renderAst, type PluralIssue, type RenderCtx } from './render';\nimport { postProcess } from './postprocess';\nimport { safetyRestore } from './neutralize';\nimport { parseTemplate } from './parser';\nimport { isParsedAst, type Ast, type ParsedAst } from './ast';\nimport { AstVersionError } from './errors';\nimport type { Rng } from './rng';\n\n/** Default for {@link PipelineOptions.maxDepth} (#include + parse-nesting guard). */\nexport const DEFAULT_MAX_DEPTH = 20;\n\nexport interface PipelineOptions {\n context?: Record<string, string>;\n locale?: string;\n includeResolver?: (ref: string) => string | null;\n postProcess?: boolean;\n maxDepth?: number;\n onPluralError?: (issue: PluralIssue) => void;\n}\n\nexport function renderWith(input: string | Ast, rng: Rng, opts: PipelineOptions = {}): string {\n const ctx: RenderCtx = {\n runtimeContext: opts.context ?? {},\n rng,\n locale: opts.locale ?? '',\n resolver: opts.includeResolver,\n maxDepth: opts.maxDepth ?? DEFAULT_MAX_DEPTH,\n includeStack: [],\n onPluralError: opts.onPluralError,\n };\n // parseTemplate sanitises author markup itself now (see its docblock), so the sentinel strip\n // that used to live here — and only here, missing parse() and analyze() — is gone.\n const ast = resolveAst(input);\n let out = renderAst(ast, ctx);\n // Cosmetic post-process defaults ON (§0.1); false skips it. It runs on the still-\n // shielded form (neutralize sentinels are inert here).\n if (opts.postProcess !== false) out = postProcess(out);\n // Mandatory neutralize safety-restore (§6) — ALWAYS runs, even with postProcess:false.\n return safetyRestore(out);\n}\n\n/** Resolve a `string | Ast` input to a parsed AST (parses a string fresh). */\nfunction resolveAst(input: string | Ast): ParsedAst {\n if (typeof input === 'string') return parseTemplate(input);\n if (isParsedAst(input)) return input;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n","/**\n * RNG seam. Signature `(min, max) => int` inclusive — mirrors the plugin's\n * injectable `$random_fn`. The engine short-circuits `min === max` (see\n * `randomInt` in render.ts), so this is only invoked when a real choice exists.\n */\nexport type Rng = (min: number, max: number) => number;\n\n/**\n * Build an RNG from a `seed` (deterministic PRNG — reproducible within THIS\n * engine; cross-engine sequence parity is a non-goal §3.2) or, when omitted,\n * from `Math.random` (universal on Workers / Node / browser).\n */\nexport function makeRng(seed: number | string | undefined): Rng {\n const next =\n seed === undefined\n ? Math.random\n : mulberry32(typeof seed === 'number' ? seed >>> 0 : hashString(seed));\n return (min, max) => min + Math.floor(next() * (max - min + 1));\n}\n\n/** mulberry32 — tiny, fast, well-distributed 32-bit PRNG. */\nfunction mulberry32(seed: number): () => number {\n let a = seed >>> 0;\n return () => {\n a = (a + 0x6d2b79f5) | 0;\n let t = Math.imul(a ^ (a >>> 15), 1 | a);\n t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t;\n return ((t ^ (t >>> 14)) >>> 0) / 4294967296;\n };\n}\n\n/** FNV-1a hash of a string seed → 32-bit uint. */\nfunction hashString(s: string): number {\n let h = 2166136261;\n for (let i = 0; i < s.length; i += 1) {\n h ^= s.charCodeAt(i);\n h = Math.imul(h, 16777619);\n }\n return h >>> 0;\n}\n","/**\n * @spintax/core — framework-agnostic Spintax engine (parse / render / validate /\n * extract / analyze / neutralize). Public API contract per spec §9.2 / §9.3.\n *\n * STATUS: M3. The full §9.2 surface — parse / render / validate / extract /\n * analyze / neutralize — is implemented.\n */\n\nimport { parseTemplate } from './internal/parser';\nimport { validateTemplate } from './internal/validator';\nimport { extractFromSource } from './internal/extract';\nimport { renderWith } from './internal/pipeline';\nimport { neutralize as neutralizeValue } from './internal/neutralize';\nimport { makeRng } from './internal/rng';\nimport { AstVersionError } from './internal/errors';\nimport { isParsedAst, walk, type Ast, type ParsedAst } from './internal/ast';\nimport type { PluralIssue } from './internal/render';\nimport {\n normalizeBaseLang as normalizeBaseLangInternal,\n pluralArity as pluralArityForBase,\n} from './internal/plurals';\n\n// ─── Public types (§9.2) ─────────────────────────────────────────────────────\n\n/**\n * Opaque, versioned parse result. NOT a public data contract in v1 — consumers\n * pass it back to render/validate/extract/analyze, they do not introspect it.\n * An in-memory perf handle, not a serialization format (do not persist across\n * engine versions).\n */\nexport type { Ast };\n\n/** Reported through {@link RenderOptions.onPluralError}; never thrown. */\nexport type { PluralIssue };\n\nexport interface RenderOptions {\n /** Variable map (T1, author-controlled by default — §6). */\n context?: Record<string, string>;\n /** Deterministic RNG seed; omit ⇒ nondeterministic. */\n seed?: number | string;\n /** Plural-bucket locale (§3.1); omit ⇒ default EN-style 2-form. */\n locale?: string;\n /** Host-injected, SYNCHRONOUS #include resolver (§4.1); omit ⇒ #include disabled. */\n includeResolver?: (ref: string) => string | null;\n /** Default TRUE (§0.1). false skips cosmetic post-process only; the mandatory neutralize safety-restore still runs (§6). */\n postProcess?: boolean;\n /** #include + parse-nesting guard; defaults to {@link DEFAULT_MAX_DEPTH}. */\n maxDepth?: number;\n /**\n * Observer for `{plural …}` blocks the renderer could not resolve — the port of\n * the plugin's `on_error` callable. Observation ONLY: output degrades exactly as\n * it does without it (§0.1 lenient contract — `render()` never throws on template\n * content), and the host decides whether a report is fatal.\n *\n * Worth wiring when a render is PERSISTED rather than shown: an unresolved count\n * erases its block, which is indistinguishable in the output from copy that was\n * meant to be empty.\n */\n onPluralError?: (issue: PluralIssue) => void;\n}\n\nexport interface ValidateOptions {\n /** Plural-bucket locale for arity verdicts (§3.1); omit ⇒ default 2-form. */\n locale?: string;\n /** Slug/id allow-list; enables \"unknown #include target\" verdicts. */\n knownIncludes?: readonly string[];\n /**\n * Variable names the host will supply at render (globals / context keys).\n * Suppresses the `variable.undefined` WARNING for them — verdict is unaffected\n * (an undefined var is never an error). Case-insensitive.\n */\n knownVariables?: readonly string[];\n}\n\nexport interface Diagnostic {\n severity: 'error' | 'warning';\n /** Stable machine code — parity-gated (wording/position are not). */\n code: string;\n message: string;\n /** 1-based. */\n line: number;\n /** 1-based. */\n column: number;\n endLine?: number;\n endColumn?: number;\n /** Structured specifics keyed off `code`, e.g. { expected: 3, got: 2 }. */\n data?: Record<string, unknown>;\n}\n\nexport interface ExtractResult {\n refs: string[];\n /** Names defined by `#set` — macros, re-picked at every reference. */\n sets: string[];\n /** Names defined by `#def` — rolled once per render and held. */\n defs: string[];\n includes: string[];\n}\n\nexport interface Analysis extends ExtractResult {\n diagnostics: Diagnostic[];\n /** Best-effort construct counts — NOT a variant-cardinality promise (§9.3). */\n constructs: Record<string, number>;\n}\n\n/** Default value for {@link RenderOptions.maxDepth}. */\nexport { DEFAULT_MAX_DEPTH } from './internal/pipeline';\n\n// ─── Locale helpers ──────────────────────────────────────────────────────────\n//\n// Exported so a consumer that must AGREE with the engine about plurals can ask\n// it, instead of keeping a copy of the table. A copy is not hypothetical: this\n// repo's own authoring prompt kept one, and it drifted twice — once on content\n// (a new locale added in one place) and once on shape (`locale.slice(0, 2)`\n// instead of this normalization, which disagrees on any 3-letter tag).\n//\n// `findPluralBlocks` is deliberately NOT exported alongside these: it returns\n// byte offsets into the source, i.e. parser internals, and publishing it would\n// freeze that shape and invite consumers to build on the parse layer — the same\n// reason `Ast` is opaque (see its doc above).\n\n/**\n * A locale's base language tag: `pt-BR`→`pt`, `uk_UA`→`uk`, `RU`→`ru`. Absent or\n * empty gives `''`.\n *\n * Knows nothing of ISO-639-3, so a 3-letter tag is returned whole (`srp`→`srp`)\n * and is NOT recognized as its 2-letter language.\n */\nexport function normalizeBaseLang(locale?: string | null): string {\n return normalizeBaseLangInternal(locale ?? '');\n}\n\n/**\n * How many `{plural …}` forms this locale takes — 3 for the Slavic one/few/other\n * family (ru/uk/be + sr/hr/bs), 2 for everything else.\n *\n * Takes a RAW locale and normalizes internally, unlike the internal helper of the\n * same name: a public function that silently answered 2 for `sr-Latn` would be a\n * trap. Accepts an absent locale, and unknown tags fall back to 2 rather than\n * throwing (§3.1), so the same optional value `RenderOptions.locale` carries can be\n * passed straight through.\n *\n * NOTE the asymmetry with {@link validate}: an absent or empty locale makes the\n * validator skip the arity check ENTIRELY (structural verdicts only), whereas this\n * answers the 2-form default that {@link render} would then apply. Ask this what\n * render will do; do not read it as \"what validate will enforce\".\n */\nexport function pluralArity(locale?: string | null): number {\n return pluralArityForBase(normalizeBaseLang(locale));\n}\n\n// ─── Errors (§9.3 — minimal, not a taxonomy) ─────────────────────────────────\n\nexport { SpintaxError, IncludeResolverError, AstVersionError, NotImplementedError } from './internal/errors';\n\n// ─── Public API surface (§9.2) ───────────────────────────────────────────────\n\nexport function parse(src: string): Ast {\n return parseTemplate(src);\n}\n\nexport function render(input: string | Ast, opts: RenderOptions = {}): string {\n // Public entry: seed the rng, then run the shared pipeline (internal/pipeline).\n return renderWith(input, makeRng(opts.seed), opts);\n}\n\nexport function validate(input: string | Ast, opts: ValidateOptions = {}): Diagnostic[] {\n return validateTemplate(resolveSource(input), opts);\n}\n\n/** Resolve a `string | Ast` input to its source text (for the raw-text checks). */\nfunction resolveSource(input: string | Ast): string {\n if (typeof input === 'string') return input;\n if (isParsedAst(input)) return input.source;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n\nexport function extract(input: string | Ast): ExtractResult {\n return extractFromSource(resolveSource(input));\n}\n\nexport function analyze(input: string | Ast, opts: ValidateOptions = {}): Analysis {\n const ast = resolveAst(input);\n const extracted = extractFromSource(ast.source);\n return {\n ...extracted,\n diagnostics: validateTemplate(ast.source, opts),\n constructs: countConstructs(ast, extracted.includes.length),\n };\n}\n\n/** Resolve a `string | Ast` input to a parsed AST (parses a string fresh). */\nfunction resolveAst(input: string | Ast): ParsedAst {\n if (typeof input === 'string') return parseTemplate(input);\n if (isParsedAst(input)) return input;\n throw new AstVersionError('Ast was not produced by this engine version.');\n}\n\n/**\n * Best-effort construct census (§9.3) — counts author-visible constructs, NOT a\n * variant-cardinality promise. `set`/`include` are directive counts; the rest are\n * AST node types (nested nodes included; literals excluded).\n */\nfunction countConstructs(ast: ParsedAst, includeCount: number): Record<string, number> {\n const counts: Record<string, number> = {\n enumeration: 0,\n permutation: 0,\n variable: 0,\n conditional: 0,\n plural: 0,\n };\n walk(ast.nodes, (n) => {\n if (n.type in counts) counts[n.type] = (counts[n.type] ?? 0) + 1;\n });\n counts.set = Object.keys(ast.setDefs).length;\n counts.include = includeCount;\n return counts;\n}\n\nexport function neutralize(value: string): string {\n return neutralizeValue(value);\n}\n"]}
|