@rohal12/spindle-lsp 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +30 -4
- package/dist/bin.js.map +2 -2
- package/package.json +1 -1
package/dist/bin.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/core/workspace/document-store.ts", "../src/core/parsing/passage-parser.ts", "../src/core/workspace/passage-index.ts", "../src/core/workspace/macro-registry.ts", "../src/core/workspace/variable-tracker.ts", "../src/core/workspace/widget-registry.ts", "../src/core/parsing/macro-parser.ts", "../src/macro-supplements.json", "../src/core/workspace/workspace-model.ts", "../src/core/diagnostic-codes.ts", "../src/core/parsing/argument-lexer.ts", "../src/core/parsing/parameter-validator.ts", "../src/core/parsing/link-parser.ts", "../src/plugins/diagnostics.ts", "../src/core/workspace/config-loader.ts", "../src/cli/reporters/pretty.ts", "../src/cli/reporters/json.ts", "../src/cli/reporters/sarif.ts", "../src/cli/check.ts", "../src/plugins/format.ts", "../src/cli/format.ts", "../src/core/plugin/plugin-loader.ts", "../src/server/capabilities.ts", "../src/plugins/completions.ts", "../src/plugins/hover.ts", "../src/plugins/signature.ts", "../src/plugins/definition.ts", "../src/plugins/references.ts", "../src/plugins/rename.ts", "../src/plugins/code-lens.ts", "../src/plugins/inlay-hints.ts", "../src/plugins/semantic-tokens.ts", "../src/plugins/code-actions.ts", "../src/plugins/document-symbol.ts", "../src/plugins/workspace-symbol.ts", "../src/plugins/folding-range.ts", "../src/plugins/document-link.ts", "../src/plugins/index.ts", "../src/server/server.ts", "../src/bin.ts"],
|
|
4
|
-
"sourcesContent": ["import { EventEmitter } from 'node:events';\nimport { readFileSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\n\ninterface DocumentEntry {\n text: string;\n version: number;\n}\n\n/**\n * In-memory store for open document contents.\n * Emits events when documents are opened, changed, or closed.\n */\nexport class DocumentStore extends EventEmitter {\n private docs = new Map<string, DocumentEntry>();\n\n /** Open a document (or replace if already open). */\n open(uri: string, text: string, version?: number): void {\n this.docs.set(uri, { text, version: version ?? 0 });\n this.emit('documentOpened', uri);\n }\n\n /** Update an already-open document's text. */\n update(uri: string, text: string, version?: number): void {\n const existing = this.docs.get(uri);\n const newVersion = version ?? (existing ? existing.version + 1 : 0);\n this.docs.set(uri, { text, version: newVersion });\n this.emit('documentChanged', uri);\n }\n\n /** Close a document and remove it from the store. */\n close(uri: string): void {\n this.docs.delete(uri);\n this.emit('documentClosed', uri);\n }\n\n /** Get the text of a document, or undefined if not open. */\n getText(uri: string): string | undefined {\n return this.docs.get(uri)?.text;\n }\n\n /** Get the version of a document (0 if unknown). */\n getVersion(uri: string): number {\n return this.docs.get(uri)?.version ?? 0;\n }\n\n /** Get all open document URIs. */\n getUris(): string[] {\n return Array.from(this.docs.keys());\n }\n\n /** Check whether a document is currently open. */\n has(uri: string): boolean {\n return this.docs.has(uri);\n }\n\n /** Load files from disk (CLI mode). Converts paths to file:// URIs. */\n loadFromDisk(paths: string[]): void {\n for (const filePath of paths) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = pathToFileURL(filePath).href;\n this.open(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n }\n}\n", "import type { Range } from '../types.js';\n\nexport interface ParsedPassageHeader {\n name: string;\n tags: string[];\n meta: Record<string, unknown> | undefined;\n headerRange: Range;\n nameRange: Range;\n}\n\n/**\n * Regex for matching passage headers.\n * Captures: (1) `:: ` prefix, (2) passage name, (3) optional `[tags]`, (4) optional `{meta}`\n *\n * Derived from the reference in twee3-language-tools/src/parse-text.ts:\n * /(^::\\s*)(.*?)(\\[.*?\\]\\s*)?(\\{.*?\\}\\s*)?\\r?$/\n */\nconst passageHeaderRegex = /^(::\\s+)(.*?)(\\[.*?\\]\\s*)?(\\{.*?\\}\\s*)?\\r?$/;\n\nconst SPECIAL_PASSAGES = new Set([\n 'StoryVariables',\n 'StoryInit',\n 'StoryData',\n 'StoryTitle',\n 'StoryBanner',\n 'StoryCaption',\n 'StoryMenu',\n 'StoryInterface',\n 'StoryAuthor',\n]);\n\n/**\n * Parse a single line as a passage header.\n * Returns null if the line is not a valid passage header.\n */\nexport function parsePassageHeader(line: string, lineNumber: number): ParsedPassageHeader | null {\n // Run regex against escaped version (neutralize backslash sequences for matching)\n const escaped = line.replace(/\\\\./g, 'ec');\n const match = passageHeaderRegex.exec(escaped);\n if (!match) return null;\n\n const prefix = match[1] ?? ''; // \":: \"\n const rawName = match[2] ?? ''; // everything between prefix and tags/meta\n const rawTags = match[3] ?? ''; // \"[tag1 tag2] \" or \"\"\n const rawMeta = match[4] ?? ''; // '{\"key\":\"val\"} ' or \"\"\n\n // Extract the actual name from the original line (not escaped)\n const nameStart = prefix.length;\n const nameEnd = nameStart + rawName.length;\n const name = line.substring(nameStart, nameEnd).trim();\n\n if (!name) return null;\n\n // Reject names with unescaped meta characters\n const escapedName = name.replace(/\\\\./g, 'ec');\n if (/[\\[\\]\\{\\}]/.test(escapedName)) return null;\n\n // Parse tags\n const tagsStr = rawTags.trim();\n let tags: string[] = [];\n if (tagsStr) {\n const inner = tagsStr.substring(1, tagsStr.length - 1).trim();\n // Reject unescaped meta characters inside tags\n if (/[\\[\\]\\{\\}]/.test(inner.replace(/\\\\./g, 'ec'))) return null;\n tags = inner ? inner.split(/\\s+/) : [];\n }\n\n // Parse meta JSON\n let meta: Record<string, unknown> | undefined;\n const metaStr = rawMeta.trim();\n if (metaStr) {\n try {\n meta = JSON.parse(line.substring(nameStart + rawName.length + rawTags.length, nameStart + rawName.length + rawTags.length + rawMeta.length).trim());\n } catch {\n // Invalid JSON \u2014 treat the entire line as not a valid passage header\n return null;\n }\n }\n\n const headerRange: Range = {\n start: { line: lineNumber, character: 0 },\n end: { line: lineNumber, character: line.length },\n };\n\n // nameRange: position of the trimmed name within the line\n // The name starts right after the prefix, but the prefix may include extra whitespace.\n // We need to find where the actual name text starts (after \":: \" which is the prefix).\n const nameCharStart = prefix.length;\n const nameCharEnd = nameCharStart + name.length;\n\n const nameRange: Range = {\n start: { line: lineNumber, character: nameCharStart },\n end: { line: lineNumber, character: nameCharEnd },\n };\n\n return {\n name: name.replace(/\\\\(.)/g, '$1'), // unescape\n tags,\n meta,\n headerRange,\n nameRange,\n };\n}\n\n/**\n * Check whether a passage name is one of the special/system passages.\n */\nexport function isSpecialPassage(name: string): boolean {\n return SPECIAL_PASSAGES.has(name);\n}\n", "import type { Passage, Range } from '../types.js';\nimport { parsePassageHeader } from '../parsing/passage-parser.js';\n\n/**\n * Maintains an index of all passages across all open documents.\n * Supports lookup by name, URI, line number, and detects duplicates.\n */\nexport class PassageIndex {\n /** Per-URI list of passages. */\n private byUri = new Map<string, Passage[]>();\n\n /**\n * Parse all passage headers in the given document text and\n * store them, replacing any previous entries for this URI.\n */\n rebuild(uri: string, text: string): void {\n // Remove old entries for this URI\n this.byUri.delete(uri);\n\n const lines = text.split('\\n');\n const passages: Passage[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const header = parsePassageHeader(lines[i], i);\n if (!header) continue;\n\n // Compute the end of the passage content:\n // it extends until the next passage header or end of file.\n // For now, headerEnd is just the header line range.\n const passage: Passage = {\n name: header.name,\n range: {\n start: { line: i, character: 0 },\n end: { line: i, character: lines[i].length }, // will be extended below\n },\n headerEnd: header.headerRange,\n uri,\n tags: header.tags.length > 0 ? header.tags : undefined,\n meta: header.meta,\n };\n passages.push(passage);\n }\n\n // Extend each passage range to cover content until the next header\n for (let i = 0; i < passages.length; i++) {\n const nextStart = i + 1 < passages.length\n ? passages[i + 1].range.start.line - 1\n : lines.length - 1;\n passages[i].range = {\n start: passages[i].range.start,\n end: { line: nextStart, character: lines[nextStart]?.length ?? 0 },\n };\n }\n\n if (passages.length > 0) {\n this.byUri.set(uri, passages);\n }\n }\n\n /** Remove all passages for a URI. */\n remove(uri: string): void {\n this.byUri.delete(uri);\n }\n\n /** Get a passage by name. Returns the first match found. */\n getPassage(name: string): Passage | undefined {\n for (const passages of this.byUri.values()) {\n for (const p of passages) {\n if (p.name === name) return p;\n }\n }\n return undefined;\n }\n\n /** Get the passage containing a specific line in a document. */\n getPassageAt(uri: string, line: number): Passage | undefined {\n const passages = this.byUri.get(uri);\n if (!passages) return undefined;\n\n // Find the passage whose range contains this line\n for (let i = passages.length - 1; i >= 0; i--) {\n if (passages[i].range.start.line <= line) {\n return passages[i];\n }\n }\n return undefined;\n }\n\n /** Get all passages in a specific document. */\n getPassagesInDocument(uri: string): Passage[] {\n return this.byUri.get(uri) ?? [];\n }\n\n /** Get all passages across all documents. */\n getAllPassages(): Passage[] {\n const result: Passage[] = [];\n for (const passages of this.byUri.values()) {\n result.push(...passages);\n }\n return result;\n }\n\n /** Get the StoryVariables passage, if any. */\n getStoryVariables(): Passage | undefined {\n return this.getPassage('StoryVariables');\n }\n\n /** Get the StoryInit passage, if any. */\n getStoryInit(): Passage | undefined {\n return this.getPassage('StoryInit');\n }\n\n /**\n * Find passage names that appear more than once across all documents.\n * Returns a map from name to the list of duplicate Passage objects.\n */\n getDuplicates(): Map<string, Passage[]> {\n const byName = new Map<string, Passage[]>();\n for (const passages of this.byUri.values()) {\n for (const p of passages) {\n const existing = byName.get(p.name);\n if (existing) {\n existing.push(p);\n } else {\n byName.set(p.name, [p]);\n }\n }\n }\n\n const duplicates = new Map<string, Passage[]>();\n for (const [name, passages] of byName) {\n if (passages.length > 1) {\n duplicates.set(name, passages);\n }\n }\n return duplicates;\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, parse as parsePath } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MacroInfo, ChildConstraint } from '../types.js';\n\n/**\n * Supplement entry as found in macro-supplements.json or user config.\n * Uses `container` (boolean) which maps to `block` on MacroInfo.\n */\ninterface SupplementEntry {\n name?: string;\n description?: string;\n parameters?: string[];\n container?: boolean;\n children?: ChildConstraint[];\n parents?: string[];\n skipArgs?: boolean;\n}\n\n/** Shape of entries in @rohal12/spindle's macro-registry.json */\ninterface BuiltinMacroEntry {\n name: string;\n block: boolean;\n subMacros: string[];\n storeVar?: boolean;\n interpolate?: boolean;\n merged?: boolean;\n source: string;\n}\n\n/**\n * Registry of all known macros, merging data from three tiers:\n * 1. Builtins \u2014 from @rohal12/spindle/tooling getMacroRegistry()\n * 2. Supplements \u2014 macro-supplements.json (descriptions, parameters, children)\n * 3. User config \u2014 workspace-level overrides\n *\n * All lookups are case-insensitive.\n */\nexport class MacroRegistry {\n private macros = new Map<string, MacroInfo>();\n\n /**\n * Load built-in macro metadata from @rohal12/spindle's macro-registry.json.\n * This is the base layer that provides name, block, subMacros, flags, source.\n */\n /** Warnings collected during loadBuiltins for logging. */\n readonly warnings: string[] = [];\n\n loadBuiltins(): void {\n let builtinMacros: BuiltinMacroEntry[] = [];\n\n try {\n // Resolve the macro-registry.json from @rohal12/spindle package.\n // Walk up from this file's directory to find node_modules.\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const registryPath = this.resolveRegistryPath(thisDir);\n if (registryPath) {\n const raw = readFileSync(registryPath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) {\n this.warnings.push(\n `macro-registry.json: expected array, got ${typeof parsed}. Continuing with supplements only.`,\n );\n } else {\n builtinMacros = parsed;\n }\n }\n } catch (err: unknown) {\n // Package not available or malformed \u2014 log and continue with supplements only\n const message = err instanceof Error ? err.message : String(err);\n this.warnings.push(\n `Failed to load builtin macros: ${message}. Continuing with supplements only.`,\n );\n }\n\n for (const m of builtinMacros) {\n try {\n const key = m.name.toLowerCase();\n this.macros.set(key, {\n name: m.name,\n block: m.block,\n subMacros: m.subMacros ?? [],\n storeVar: m.storeVar,\n interpolate: m.interpolate,\n merged: m.merged,\n source: m.source === 'builtin' ? 'builtin' : 'user',\n });\n } catch {\n // Skip malformed entries\n this.warnings.push(`Skipped malformed builtin macro entry: ${JSON.stringify(m)}`);\n }\n }\n }\n\n /**\n * Overlay supplement data onto the registry.\n * Supplements provide descriptions, parameters, children, parents, skipArgs.\n * The `container` field maps to `block` on MacroInfo.\n */\n loadSupplements(supplements: Record<string, SupplementEntry>): void {\n this.mergeEntries(supplements);\n }\n\n /**\n * Overlay user config onto the registry.\n * Same format as supplements; applied last so it wins.\n */\n loadConfig(config: Record<string, SupplementEntry>): void {\n this.mergeEntries(config);\n }\n\n /** Add or replace a single macro entry. */\n addMacro(info: Partial<MacroInfo> & { name: string }): void {\n const key = info.name.toLowerCase();\n const existing = this.macros.get(key);\n this.macros.set(key, {\n name: info.name,\n block: info.block ?? existing?.block ?? false,\n subMacros: info.subMacros ?? existing?.subMacros ?? [],\n source: info.source ?? existing?.source ?? 'user',\n storeVar: info.storeVar ?? existing?.storeVar,\n interpolate: info.interpolate ?? existing?.interpolate,\n merged: info.merged ?? existing?.merged,\n description: info.description ?? existing?.description,\n parameters: info.parameters ?? existing?.parameters,\n children: info.children ?? existing?.children,\n parents: info.parents ?? existing?.parents,\n skipArgs: info.skipArgs ?? existing?.skipArgs,\n });\n }\n\n /** Get a macro by name (case-insensitive). */\n getMacro(name: string): MacroInfo | undefined {\n return this.macros.get(name.toLowerCase());\n }\n\n /** Check if a macro is a block (container) macro. */\n isBlock(name: string): boolean {\n return this.macros.get(name.toLowerCase())?.block ?? false;\n }\n\n /** Check if a macro is a sub-macro (has parents). */\n isSubMacro(name: string): boolean {\n const info = this.macros.get(name.toLowerCase());\n return (info?.parents != null && info.parents.length > 0);\n }\n\n /** Get all registered macros. */\n getAllMacros(): MacroInfo[] {\n return Array.from(this.macros.values());\n }\n\n /**\n * Walk up directory tree from `startDir` to find the\n * @rohal12/spindle/dist/pkg/macro-registry.json file.\n */\n private resolveRegistryPath(startDir: string): string | null {\n const target = join('node_modules', '@rohal12', 'spindle', 'dist', 'pkg', 'macro-registry.json');\n let dir = startDir;\n const { root } = parsePath(dir);\n while (dir !== root) {\n const candidate = join(dir, target);\n if (existsSync(candidate)) {\n return candidate;\n }\n dir = dirname(dir);\n }\n return null;\n }\n\n /** Merge a set of supplement/config entries into the registry. */\n private mergeEntries(entries: Record<string, SupplementEntry>): void {\n for (const [rawKey, entry] of Object.entries(entries)) {\n const key = rawKey.toLowerCase();\n const existing = this.macros.get(key);\n\n if (existing) {\n // Overlay fields \u2014 supplement fields win when present\n if (entry.description !== undefined) existing.description = entry.description;\n if (entry.parameters !== undefined) existing.parameters = entry.parameters;\n if (entry.children !== undefined) existing.children = entry.children;\n if (entry.parents !== undefined) existing.parents = entry.parents;\n if (entry.skipArgs !== undefined) existing.skipArgs = entry.skipArgs;\n if (entry.container !== undefined) existing.block = entry.container;\n } else {\n // Create a new entry from the supplement\n this.macros.set(key, {\n name: entry.name ?? rawKey,\n block: entry.container ?? false,\n subMacros: [],\n source: 'user',\n description: entry.description,\n parameters: entry.parameters,\n children: entry.children,\n parents: entry.parents,\n skipArgs: entry.skipArgs,\n });\n }\n }\n }\n}\n", "import type { DeclaredVariable, MacroNode, Range } from '../types.js';\nimport { parsePassageHeader } from '../parsing/passage-parser.js';\n\n/** Regex to match $variable references including dot notation. */\nconst varRefRegex = /\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n\n/** Passages excluded from variable scanning. */\nconst EXCLUDED_PASSAGES = new Set([\n 'StoryVariables', 'StoryInit', 'StoryData', 'StoryScript', 'StoryInterface',\n]);\n\n/** Patterns that should be stripped before scanning for variable references. */\nconst CLEAN_PATTERNS = [\n /<!--[\\s\\S]*?-->/g, // HTML comments\n /<script(?:\\s+[^>]*)?>[\\s\\S]*?<\\/script>/gi, // script tags\n /<style>[\\s\\S]*?<\\/style>/gi, // style tags\n /`(?:\\\\.|[^`\\\\])*`/g, // backtick strings\n /\"(?:\\\\.|[^\"\\\\])*\"/g, // double-quoted strings\n /'(?:\\\\.|[^'\\\\])*'/g, // single-quoted strings\n];\n\ninterface VariableUsage {\n uri: string;\n baseName: string;\n fullName: string;\n range: Range;\n}\n\n/**\n * Tracks declared variables (from StoryVariables) and variable usages across documents.\n */\nexport class VariableTracker {\n private declared = new Map<string, DeclaredVariable>();\n private _hasStoryVariables = false;\n\n /** Per-URI list of variable usages. */\n private usagesByUri = new Map<string, VariableUsage[]>();\n\n /**\n * Parse the StoryVariables passage content for declarations.\n * Each line like `$name = value` becomes a declaration.\n */\n parseStoryVariables(content: string): void {\n this.declared.clear();\n this._hasStoryVariables = true;\n\n const lines = content.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('<!--')) continue;\n\n const match = /^\\$([A-Za-z_$][\\w$]*)\\s*=\\s*(.*)$/.exec(trimmed);\n if (!match) continue;\n\n const name = match[1];\n const expr = match[2].trim();\n const decl: DeclaredVariable = { name, sigil: '$' };\n\n // Extract top-level object fields for dot-notation validation\n if (expr.startsWith('{')) {\n const fieldRegex = /(\\w+)\\s*:/g;\n let fieldMatch;\n const fields: string[] = [];\n while ((fieldMatch = fieldRegex.exec(expr)) !== null) {\n fields.push(fieldMatch[1]);\n }\n if (fields.length > 0) {\n decl.fields = fields;\n }\n }\n\n this.declared.set(name, decl);\n }\n }\n\n /**\n * Scan a document for variable usages.\n * Identifies passages in the document and scans non-special ones.\n */\n scanDocument(uri: string, text: string, _macros: MacroNode[]): void {\n // Clear previous usages for this URI\n this.usagesByUri.delete(uri);\n\n const lines = text.split('\\n');\n const usages: VariableUsage[] = [];\n\n // Find all passage boundaries in the document\n const passageBoundaries: Array<{ name: string; startLine: number }> = [];\n for (let i = 0; i < lines.length; i++) {\n const header = parsePassageHeader(lines[i], i);\n if (header) {\n passageBoundaries.push({ name: header.name, startLine: i });\n }\n }\n\n // Scan each passage's content\n for (let pi = 0; pi < passageBoundaries.length; pi++) {\n const passage = passageBoundaries[pi];\n if (EXCLUDED_PASSAGES.has(passage.name)) continue;\n\n const contentStartLine = passage.startLine + 1;\n const contentEndLine = pi + 1 < passageBoundaries.length\n ? passageBoundaries[pi + 1].startLine\n : lines.length;\n\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n const content = contentLines.join('\\n');\n\n // Clean the content to avoid scanning inside strings/comments\n let cleaned = content;\n for (const pattern of CLEAN_PATTERNS) {\n cleaned = cleaned.replace(pattern, (m) => ' '.repeat(m.length));\n }\n\n // Build line offsets for this content block\n const lineOffsets: number[] = [0];\n for (let i = 0; i < cleaned.length; i++) {\n if (cleaned[i] === '\\n') lineOffsets.push(i + 1);\n }\n\n // Find variable references\n const re = new RegExp(varRefRegex.source, 'g');\n let match;\n while ((match = re.exec(cleaned)) !== null) {\n const fullName = match[1];\n const baseName = fullName.split('.')[0];\n const charOffset = match.index;\n\n // Convert offset to line/character within content block\n let localLine = 0;\n for (let i = 0; i < lineOffsets.length; i++) {\n if (lineOffsets[i] > charOffset) break;\n localLine = i;\n }\n const character = charOffset - lineOffsets[localLine];\n const absoluteLine = contentStartLine + localLine;\n\n const range: Range = {\n start: { line: absoluteLine, character },\n end: { line: absoluteLine, character: character + match[0].length },\n };\n\n usages.push({ uri, baseName, fullName, range });\n }\n }\n\n if (usages.length > 0) {\n this.usagesByUri.set(uri, usages);\n }\n }\n\n /** Get all declared variables. */\n getDeclared(): Map<string, DeclaredVariable> {\n return this.declared;\n }\n\n /** Get all usages of a variable by base name. */\n getUsages(name: string): Array<{ uri: string; range: Range }> {\n const results: Array<{ uri: string; range: Range }> = [];\n for (const usages of this.usagesByUri.values()) {\n for (const u of usages) {\n if (u.baseName === name) {\n results.push({ uri: u.uri, range: u.range });\n }\n }\n }\n return results;\n }\n\n /** Get undeclared variable usages in a specific document. */\n getUndeclared(uri: string): Array<{ name: string; range: Range }> {\n const usages = this.usagesByUri.get(uri);\n if (!usages) return [];\n\n const results: Array<{ name: string; range: Range }> = [];\n const seen = new Set<string>();\n\n for (const u of usages) {\n if (!this.declared.has(u.baseName) && !seen.has(u.baseName)) {\n seen.add(u.baseName);\n results.push({ name: u.baseName, range: u.range });\n }\n }\n return results;\n }\n\n /** Whether a StoryVariables passage has been parsed. */\n hasStoryVariables(): boolean {\n return this._hasStoryVariables;\n }\n}\n", "import type { Passage, WidgetDef, Range } from '../types.js';\n\n/** Regex matching {widget \"name\" @param1 @param2} definitions. */\nconst widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"((?:\\s+@[A-Za-z_$][\\w$]*)*)\\s*\\}/gi;\n\n/** Regex extracting individual @param names from the parameter string. */\nconst paramRegex = /@([A-Za-z_$][\\w$]*)/g;\n\n/**\n * Registry of user-defined widgets.\n * Scans passages tagged [widget] for {widget \"name\" @params} definitions.\n */\nexport class WidgetRegistry {\n private widgets = new Map<string, WidgetDef>();\n\n /**\n * Scan all passages for widget definitions.\n * Only passages tagged `widget` are examined.\n *\n * @param passages - All known passages.\n * @param getContent - Function to retrieve document text by URI.\n */\n scan(passages: Passage[], getContent: (uri: string) => string | undefined): void {\n this.widgets.clear();\n\n for (const passage of passages) {\n if (!passage.tags?.includes('widget')) continue;\n\n const text = getContent(passage.uri);\n if (!text) continue;\n\n // Get the passage content (lines after the header)\n const lines = text.split('\\n');\n const contentStartLine = passage.range.start.line + 1;\n // Find the end of this passage (next header or EOF)\n let contentEndLine = lines.length;\n for (let i = contentStartLine; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEndLine = i;\n break;\n }\n }\n\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n\n for (let i = 0; i < contentLines.length; i++) {\n const line = contentLines[i];\n widgetDefRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = widgetDefRegex.exec(line)) !== null) {\n const widgetName = match[1];\n const paramString = match[2] || '';\n const params: string[] = [];\n let paramMatch: RegExpExecArray | null;\n paramRegex.lastIndex = 0;\n while ((paramMatch = paramRegex.exec(paramString)) !== null) {\n params.push(paramMatch[1]);\n }\n\n const lineNum = contentStartLine + i;\n const charStart = match.index;\n const charEnd = charStart + match[0].length;\n\n const range: Range = {\n start: { line: lineNum, character: charStart },\n end: { line: lineNum, character: charEnd },\n };\n\n this.widgets.set(widgetName, {\n name: widgetName,\n params,\n uri: passage.uri,\n range,\n });\n }\n }\n }\n }\n\n /** Get a widget definition by name. */\n getWidget(name: string): WidgetDef | undefined {\n return this.widgets.get(name);\n }\n\n /** Get all registered widget definitions. */\n getAllWidgets(): WidgetDef[] {\n return Array.from(this.widgets.values());\n }\n}\n", "import type { MacroNode, Range } from '../types.js';\n\n/**\n * Regex for variable interpolation: {$var}, {_var}, {@var}\n * These must be neutralized before macro parsing to avoid false matches.\n */\nconst variableInterpolationRegex = /(?<!\\\\)\\{([$_@][A-Za-z_$][\\w$.]*)\\}/g;\n\n/**\n * Spindle macro regex.\n * Groups:\n * 1 = closing slash (/) \u2014 present for closing macros\n * 2 = CSS prefix (e.g. \".red#alert \")\n * 3 = macro name\n * 4 = raw arguments\n */\nconst macroRegex = /(?<!\\\\)\\{(\\/)?(?:((?:[#.][a-zA-Z][\\w-]*\\s*)*)([A-Za-z][\\w-]*))(?:\\s+((?:(?:`(?:\\\\.|[^`\\\\])*?`)|(?:\"(?:\\\\.|[^\"\\\\])*?\")|(?:'(?:\\\\.|[^'\\\\])*?')|(?:\\[(?:[<>]?[Ii][Mm][Gg])?\\[[^\\r\\n]*?\\]\\]+)|[^}]|(?:}))*?))?\\}/gmi;\n\n/**\n * Build an array of line-start offsets from text.\n * lineStarts[i] is the character offset where line i begins.\n */\nfunction buildLineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) {\n if (text[i] === '\\n') {\n starts.push(i + 1);\n }\n }\n return starts;\n}\n\n/**\n * Convert a character offset to a line/character Position\n * using precomputed line-start offsets.\n */\nfunction offsetToPosition(offset: number, lineStarts: number[]): { line: number; character: number } {\n // Binary search for the line containing this offset\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const mid = (low + high + 1) >> 1;\n if (lineStarts[mid] <= offset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return { line: low, character: offset - lineStarts[low] };\n}\n\n/**\n * Parse all macros from the given text.\n *\n * Variable interpolation patterns ({$var}, {_var}, {@var}) are replaced with\n * same-length placeholder text before regex matching, preserving character offsets.\n */\nexport function parseMacros(text: string): MacroNode[] {\n // Replace variable interpolation with same-length spaces to preserve offsets\n const cleaned = text.replace(variableInterpolationRegex, (match) => {\n return ' '.repeat(match.length);\n });\n\n const lineStarts = buildLineStarts(text);\n const macros: MacroNode[] = [];\n let id = 0;\n\n // Reset regex state (global regex)\n macroRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = macroRegex.exec(cleaned)) !== null) {\n const closeSlash = match[1];\n const cssPrefix = (match[2] || '').trim();\n const macroName = match[3];\n const rawArgs = match[4];\n\n const open = closeSlash !== '/';\n\n const matchStart = match.index;\n const matchEnd = matchStart + match[0].length;\n\n const startPos = offsetToPosition(matchStart, lineStarts);\n const endPos = offsetToPosition(matchEnd, lineStarts);\n\n const range: Range = {\n start: startPos,\n end: endPos,\n };\n\n macros.push({\n id,\n pair: -1,\n name: macroName,\n open,\n range,\n cssPrefix: cssPrefix || undefined,\n rawArgs: rawArgs || undefined,\n });\n\n id++;\n }\n\n return macros;\n}\n\n/**\n * Pair opening and closing macros using a name-keyed stack algorithm.\n *\n * For each opening macro where isBlock(name) returns true, push onto a\n * per-name stack. For each closing macro, pop the matching opening macro\n * and set both their pair fields to each other's id.\n *\n * Unmatched macros keep pair = -1.\n */\nexport function pairMacros(macros: MacroNode[], isBlock: (name: string) => boolean): void {\n const stacks: Record<string, number[]> = {};\n\n for (const macro of macros) {\n const name = macro.name.toLowerCase();\n\n if (!isBlock(macro.name)) continue;\n\n if (macro.open) {\n if (!stacks[name]) stacks[name] = [];\n stacks[name].push(macro.id);\n } else {\n // Closing macro \u2014 pop the matching opening macro\n const stack = stacks[name];\n if (stack && stack.length > 0) {\n const openId = stack.pop()!;\n macros[openId].pair = macro.id;\n macro.pair = openId;\n }\n }\n }\n}\n", "{\n \"if\": {\n \"name\": \"if\",\n \"children\": [\n { \"name\": \"else\", \"max\": 1 },\n { \"name\": \"elseif\" }\n ],\n \"container\": true,\n \"description\": \"Conditionally displays its contents based on the given expression.\\n\\nUsage:\\n\\n```\\n{if condition}\\n ...\\n{elseif condition}\\n ...\\n{else}\\n ...\\n{/if}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"elseif\": {\n \"name\": \"elseif\",\n \"parents\": [\"if\"],\n \"description\": \"Used within `{if}` to provide an additional conditional branch.\\n\\nUsage: `{elseif condition}`\",\n \"parameters\": [\"...text\"]\n },\n \"else\": {\n \"name\": \"else\",\n \"parents\": [\"if\"],\n \"description\": \"Used within `{if}` to provide a fallback branch.\\n\\nUsage: `{else}`\",\n \"parameters\": []\n },\n \"for\": {\n \"name\": \"for\",\n \"children\": [\n { \"name\": \"next\" },\n { \"name\": \"stop\" }\n ],\n \"container\": true,\n \"description\": \"Loop block. Usage: `{for @item of $list}...{/for}` or `{for @item, @index of $list}...{/for}`\",\n \"skipArgs\": true\n },\n \"next\": {\n \"name\": \"next\",\n \"parents\": [\"for\"],\n \"description\": \"Continues to the next iteration of a `{for}` loop.\\n\\nUsage: `{next}`\",\n \"parameters\": []\n },\n \"stop\": {\n \"name\": \"stop\",\n \"parents\": [\"for\", \"repeat\"],\n \"description\": \"Breaks out of a `{for}` or `{repeat}` loop.\\n\\nUsage: `{stop}`\",\n \"parameters\": []\n },\n \"switch\": {\n \"name\": \"switch\",\n \"children\": [\n { \"name\": \"case\", \"min\": 1 },\n { \"name\": \"default\", \"max\": 1 }\n ],\n \"container\": true,\n \"description\": \"Evaluates an expression and executes the matching `{case}` branch.\\n\\nUsage:\\n\\n```\\n{switch expression}\\n {case value1}\\n ...\\n {case value2}\\n ...\\n {default}\\n ...\\n{/switch}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"case\": {\n \"name\": \"case\",\n \"parents\": [\"switch\"],\n \"description\": \"Defines a branch within a `{switch}` macro.\\n\\nUsage: `{case value}`\",\n \"parameters\": [\"...text\"]\n },\n \"default\": {\n \"name\": \"default\",\n \"parents\": [\"switch\"],\n \"description\": \"Defines the default branch within a `{switch}` macro.\\n\\nUsage: `{default}`\",\n \"parameters\": []\n },\n \"set\": {\n \"name\": \"set\",\n \"description\": \"Sets variables based on the given expression.\\n\\nUsage: `{set $var to value}`\\n\\nSupports `$var` (story), `_var` (temporary), and `@var` (local) variables.\",\n \"parameters\": [\"...text\"]\n },\n \"unset\": {\n \"name\": \"unset\",\n \"description\": \"Unsets one or more variables.\\n\\nUsage: `{unset $var}`\",\n \"parameters\": [\"...text\"]\n },\n \"computed\": {\n \"name\": \"computed\",\n \"description\": \"Evaluates an expression and outputs the result.\\n\\nUsage: `{computed expression}`\",\n \"parameters\": [\"...text\"]\n },\n \"print\": {\n \"name\": \"print\",\n \"description\": \"Outputs the result of the given expression.\\n\\nUsage: `{print expression}`\",\n \"parameters\": [\"...text\"]\n },\n \"do\": {\n \"name\": \"do\",\n \"container\": true,\n \"description\": \"Displays its contents. Can be updated dynamically.\\n\\nUsage:\\n\\n```\\n{do}\\n ...\\n{/do}\\n```\",\n \"parameters\": []\n },\n \"link\": {\n \"name\": \"link\",\n \"container\": true,\n \"description\": \"Creates a link that executes its contents when clicked.\\n\\nUsage:\\n\\n```\\n{link \\\"text\\\" \\\"passage\\\"}\\n ...\\n{/link}\\n```\",\n \"parameters\": [\"text |+ text\", \"\"]\n },\n \"button\": {\n \"name\": \"button\",\n \"container\": true,\n \"description\": \"Creates a button that executes its contents when clicked.\\n\\nUsage:\\n\\n```\\n{button \\\"text\\\" \\\"passage\\\"}\\n ...\\n{/button}\\n```\",\n \"parameters\": [\"text |+ text\", \"\"]\n },\n \"timed\": {\n \"name\": \"timed\",\n \"children\": [\n { \"name\": \"next\" }\n ],\n \"container\": true,\n \"description\": \"Displays its contents after a specified delay.\\n\\nUsage:\\n\\n```\\n{timed delay}\\n ...\\n {next delay}\\n ...\\n{/timed}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"repeat\": {\n \"name\": \"repeat\",\n \"children\": [\n { \"name\": \"stop\" }\n ],\n \"container\": true,\n \"description\": \"Repeatedly displays its contents at the specified interval.\\n\\nUsage:\\n\\n```\\n{repeat delay}\\n ...\\n{/repeat}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"type\": {\n \"name\": \"type\",\n \"container\": true,\n \"description\": \"Outputs its contents one character at a time, mimicking a typewriter effect.\\n\\nUsage:\\n\\n```\\n{type speed}\\n ...\\n{/type}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"listbox\": {\n \"name\": \"listbox\",\n \"children\": [\n { \"name\": \"option\", \"min\": 1 }\n ],\n \"container\": true,\n \"description\": \"Creates a dropdown listbox.\\n\\nUsage:\\n\\n```\\n{listbox \\\"$receiver\\\"}\\n {option \\\"label1\\\"}\\n {option \\\"label2\\\"}\\n{/listbox}\\n```\",\n \"parameters\": [\"receiver\"]\n },\n \"cycle\": {\n \"name\": \"cycle\",\n \"children\": [\n { \"name\": \"option\", \"min\": 1 }\n ],\n \"container\": true,\n \"description\": \"Creates a cycling link.\\n\\nUsage:\\n\\n```\\n{cycle \\\"$receiver\\\"}\\n {option \\\"label1\\\"}\\n {option \\\"label2\\\"}\\n{/cycle}\\n```\",\n \"parameters\": [\"receiver\"]\n },\n \"option\": {\n \"name\": \"option\",\n \"parents\": [\"listbox\", \"cycle\"],\n \"description\": \"Defines an option within a `{listbox}` or `{cycle}` macro.\\n\\nUsage: `{option label}`\",\n \"parameters\": [\"|+ text &+ text\", \"text\"]\n },\n \"widget\": {\n \"name\": \"widget\",\n \"container\": true,\n \"description\": \"Defines a custom widget (macro).\\n\\nUsage:\\n\\n```\\n{widget \\\"name\\\"}\\n ...\\n{/widget}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"meter\": {\n \"name\": \"meter\",\n \"description\": \"Displays a progress meter.\\n\\nUsage: `{meter $var min max}`\",\n \"parameters\": [\"...text\"]\n },\n \"goto\": {\n \"name\": \"goto\",\n \"description\": \"Navigates to the specified passage.\\n\\nUsage: `{goto \\\"passage\\\"}`\",\n \"parameters\": [\"text\"]\n },\n \"back\": {\n \"name\": \"back\",\n \"description\": \"Creates a link or navigates to the previous passage in history.\\n\\nUsage: `{back}`\",\n \"parameters\": []\n },\n \"forward\": {\n \"name\": \"forward\",\n \"description\": \"Creates a link or navigates to the next passage in history.\\n\\nUsage: `{forward}`\",\n \"parameters\": []\n },\n \"restart\": {\n \"name\": \"restart\",\n \"description\": \"Restarts the story.\\n\\nUsage: `{restart}`\",\n \"parameters\": []\n },\n \"include\": {\n \"name\": \"include\",\n \"description\": \"Outputs the contents of the specified passage.\\n\\nUsage: `{include \\\"passage\\\"}`\",\n \"parameters\": [\"text\"]\n },\n \"passage\": {\n \"name\": \"passage\",\n \"description\": \"Outputs the name of the current passage.\\n\\nUsage: `{passage}`\",\n \"parameters\": []\n },\n \"textbox\": {\n \"name\": \"textbox\",\n \"description\": \"Creates a text input box.\\n\\nUsage: `{textbox \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"numberbox\": {\n \"name\": \"numberbox\",\n \"description\": \"Creates a number input box.\\n\\nUsage: `{numberbox \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"textarea\": {\n \"name\": \"textarea\",\n \"description\": \"Creates a multi-line text input area.\\n\\nUsage: `{textarea \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"checkbox\": {\n \"name\": \"checkbox\",\n \"description\": \"Creates a checkbox input.\\n\\nUsage: `{checkbox \\\"$receiver\\\" uncheckedValue checkedValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"radiobutton\": {\n \"name\": \"radiobutton\",\n \"description\": \"Creates a radio button input.\\n\\nUsage: `{radiobutton \\\"$receiver\\\" value}`\",\n \"parameters\": [\"receiver &+ text &+ text\"]\n },\n \"quicksave\": {\n \"name\": \"quicksave\",\n \"description\": \"Performs a quick save of the current story state.\\n\\nUsage: `{quicksave}`\",\n \"parameters\": []\n },\n \"quickload\": {\n \"name\": \"quickload\",\n \"description\": \"Loads the most recent quick save.\\n\\nUsage: `{quickload}`\",\n \"parameters\": []\n },\n \"saves\": {\n \"name\": \"saves\",\n \"description\": \"Opens the saves dialog.\\n\\nUsage: `{saves}`\",\n \"parameters\": []\n },\n \"settings\": {\n \"name\": \"settings\",\n \"description\": \"Opens the settings dialog.\\n\\nUsage: `{settings}`\",\n \"parameters\": []\n },\n \"story-title\": {\n \"name\": \"story-title\",\n \"description\": \"Outputs the story title.\\n\\nUsage: `{story-title}`\",\n \"parameters\": []\n },\n \"dialog\": {\n \"name\": \"dialog\",\n \"container\": true,\n \"description\": \"Opens a dialog with its contents.\\n\\nUsage:\\n\\n```\\n{dialog \\\"title\\\"}\\n ...\\n{/dialog}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"nobr\": {\n \"name\": \"nobr\",\n \"container\": true,\n \"description\": \"Removes line breaks from its contents.\\n\\nUsage:\\n\\n```\\n{nobr}\\n ...\\n{/nobr}\\n```\",\n \"parameters\": []\n },\n \"span\": {\n \"name\": \"span\",\n \"container\": true,\n \"description\": \"Wraps its contents in a `<span>` element.\\n\\nUsage:\\n\\n```\\n{span}\\n ...\\n{/span}\\n```\",\n \"parameters\": []\n },\n \"save-manager\": {\n \"name\": \"save-manager\",\n \"description\": \"Renders the save/load UI.\\n\\nUsage: `{save-manager}`\",\n \"parameters\": []\n },\n \"settings-controls\": {\n \"name\": \"settings-controls\",\n \"description\": \"Renders the settings controls UI.\\n\\nUsage: `{settings-controls}`\",\n \"parameters\": []\n },\n \"watch\": {\n \"name\": \"watch\",\n \"description\": \"Watches a variable for changes and triggers a re-render.\\n\\nUsage: `{watch $var}`\",\n \"parameters\": [\"...text\"]\n },\n \"unwatch\": {\n \"name\": \"unwatch\",\n \"description\": \"Stops watching a variable.\\n\\nUsage: `{unwatch $var}`\",\n \"parameters\": [\"...text\"]\n }\n}\n", "import { EventEmitter } from 'node:events';\nimport { DocumentStore } from './document-store.js';\nimport { PassageIndex } from './passage-index.js';\nimport { MacroRegistry } from './macro-registry.js';\nimport { VariableTracker } from './variable-tracker.js';\nimport { WidgetRegistry } from './widget-registry.js';\nimport { parseMacros } from '../parsing/macro-parser.js';\nimport supplements from '../../macro-supplements.json' with { type: 'json' };\n\nexport interface WorkspaceModelConfig {\n disabledPlugins?: string[];\n}\n\n/**\n * Orchestrates all workspace-level data structures.\n *\n * Event cascade on document change:\n * document change \u2192 passage rebuild \u2192 widget/variable rescan \u2192 emit 'modelReady'\n *\n * Changes are debounced at 200ms for rapid edits.\n */\nexport class WorkspaceModel extends EventEmitter {\n readonly documents: DocumentStore;\n readonly passages: PassageIndex;\n readonly macros: MacroRegistry;\n readonly variables: VariableTracker;\n readonly widgets: WidgetRegistry;\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly DEBOUNCE_MS = 200;\n\n /** Bound listeners for cleanup in dispose(). */\n private onDocumentChanged: (uri: string) => void;\n private onDocumentOpened: (uri: string) => void;\n private onDocumentClosed: (uri: string) => void;\n\n constructor(config?: WorkspaceModelConfig) {\n super();\n this.documents = new DocumentStore();\n this.passages = new PassageIndex();\n this.macros = new MacroRegistry();\n this.variables = new VariableTracker();\n this.widgets = new WidgetRegistry();\n\n // Bind event handlers\n this.onDocumentChanged = (uri: string) => this.handleDocumentChange(uri);\n this.onDocumentOpened = (uri: string) => this.handleDocumentChange(uri);\n this.onDocumentClosed = (uri: string) => this.handleDocumentClose(uri);\n\n // Wire up the event cascade\n this.documents.on('documentChanged', this.onDocumentChanged);\n this.documents.on('documentOpened', this.onDocumentOpened);\n this.documents.on('documentClosed', this.onDocumentClosed);\n }\n\n /**\n * Initialize the workspace in CLI/batch mode.\n * Loads all file contents, builds indices, and emits 'modelReady'.\n */\n initialize(fileContents: Map<string, string>): void {\n // Load macros first (builtins + supplements)\n this.macros.loadBuiltins();\n this.macros.loadSupplements(supplements as Record<string, any>);\n\n // Load all documents (this triggers documentOpened for each, which\n // will rebuild passages, but we do a bulk rebuild below anyway)\n // Temporarily detach listeners to avoid per-document cascading\n this.documents.removeListener('documentOpened', this.onDocumentOpened);\n this.documents.removeListener('documentChanged', this.onDocumentChanged);\n\n for (const [uri, text] of fileContents) {\n this.documents.open(uri, text);\n }\n\n // Reattach listeners\n this.documents.on('documentOpened', this.onDocumentOpened);\n this.documents.on('documentChanged', this.onDocumentChanged);\n\n // Bulk rebuild\n this.rebuildAll();\n\n // Schedule modelReady emission\n this.scheduleModelReady();\n }\n\n /** Clean up listeners and timers. */\n dispose(): void {\n this.documents.removeListener('documentChanged', this.onDocumentChanged);\n this.documents.removeListener('documentOpened', this.onDocumentOpened);\n this.documents.removeListener('documentClosed', this.onDocumentClosed);\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n this.removeAllListeners();\n }\n\n /** Handle a document change: rebuild passages for that document, then cascade. */\n private handleDocumentChange(uri: string): void {\n const text = this.documents.getText(uri);\n if (text !== undefined) {\n this.passages.rebuild(uri, text);\n }\n this.cascade();\n this.emit('documentChanged', uri);\n this.emit('passagesUpdated', uri);\n this.scheduleModelReady();\n }\n\n /** Handle a document close: remove its passages and cascade. */\n private handleDocumentClose(uri: string): void {\n this.passages.remove(uri);\n this.cascade();\n this.emit('documentClosed', uri);\n this.emit('passagesUpdated', uri);\n this.scheduleModelReady();\n }\n\n /** Rebuild all indices from scratch. */\n private rebuildAll(): void {\n for (const uri of this.documents.getUris()) {\n const text = this.documents.getText(uri);\n if (text !== undefined) {\n this.passages.rebuild(uri, text);\n }\n }\n this.cascade();\n }\n\n /**\n * Cascade: rescan variables and widgets based on current passages.\n * Called after any passage index update.\n */\n private cascade(): void {\n // Rescan StoryVariables\n const storyVars = this.passages.getStoryVariables();\n if (storyVars) {\n const text = this.documents.getText(storyVars.uri);\n if (text) {\n const lines = text.split('\\n');\n const contentStart = storyVars.headerEnd.end.line + 1;\n // Find end of this passage\n let contentEnd = lines.length;\n for (let i = contentStart; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEnd = i;\n break;\n }\n }\n const content = lines.slice(contentStart, contentEnd).join('\\n');\n this.variables.parseStoryVariables(content);\n }\n }\n\n // Rescan variable usages across all documents\n for (const uri of this.documents.getUris()) {\n const text = this.documents.getText(uri);\n if (text) {\n const macros = parseMacros(text);\n this.variables.scanDocument(uri, text, macros);\n }\n }\n\n // Rescan widgets\n const allPassages = this.passages.getAllPassages();\n this.widgets.scan(allPassages, (uri) => this.documents.getText(uri));\n }\n\n /** Debounce modelReady emission. */\n private scheduleModelReady(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.emit('modelReady');\n }, this.DEBOUNCE_MS);\n }\n}\n", "export const DiagnosticCode = {\n UndefinedMacro: 'SP100',\n MalformedContainer: 'SP101',\n IllegalClosingTag: 'SP104',\n InvalidChildren: 'SP107',\n ExpectedNoArguments: 'SP108',\n ParameterTypeError: 'SP109',\n ParameterWarning: 'SP110',\n TooManyArguments: 'SP111',\n ArgumentParsingWarning: 'SP112',\n ChildMaxExceeded: 'SP114',\n ChildMinNotMet: 'SP115',\n UndeclaredVariable: 'SP200',\n UndeclaredField: 'SP201',\n NoStoryVariables: 'SP202',\n BrokenPassageLink: 'SP300',\n WidgetArgCountMismatch: 'SP301',\n DeadEndPassage: 'SP400',\n UnreachablePassage: 'SP401',\n} as const;\n\nexport type DiagnosticCodeValue = (typeof DiagnosticCode)[keyof typeof DiagnosticCode];\n\ntype Severity = 'error' | 'warning' | 'info' | 'hint';\n\nconst severityMap: Record<DiagnosticCodeValue, Severity> = {\n SP100: 'warning',\n SP101: 'error',\n SP104: 'error',\n SP107: 'error',\n SP108: 'error',\n SP109: 'error',\n SP110: 'warning',\n SP111: 'error',\n SP112: 'warning',\n SP114: 'error',\n SP115: 'error',\n SP200: 'warning',\n SP201: 'warning',\n SP202: 'info',\n SP300: 'warning',\n SP301: 'warning',\n SP400: 'hint',\n SP401: 'hint',\n};\n\nexport function getSeverity(code: DiagnosticCodeValue): Severity {\n return severityMap[code];\n}\n", "/**\n * Argument lexer for Spindle macro arguments.\n *\n * Tokenizes the raw argument string from a macro invocation into typed Arg tokens.\n * Ported from twee3-language-tools/src/spindle-0/arguments.ts with simplifications:\n * - No dependency on vscode.Range (uses plain start/end offsets)\n * - Unified Boolean type (instead of separate True/False)\n * - Dot-path extraction for variables ($player.health -> path=[\"player\",\"health\"])\n */\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport enum ArgType {\n String,\n Number,\n Boolean,\n Null,\n Variable,\n Link,\n Image,\n Expression,\n Bareword,\n NaN,\n Undefined,\n}\n\nexport interface Arg {\n type: ArgType;\n text: string;\n start: number;\n end: number;\n /** Variable sigil: $, _, or @ */\n sigil?: '$' | '_' | '@';\n /** Dot-access path segments, e.g. $player.health -> [\"player\", \"health\"] */\n path?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Lex a raw argument string into an array of typed Arg tokens.\n */\nexport function lexArguments(source: string): Arg[] {\n const lexer = new Lexer(source, lexSpace);\n const rawItems = lexer.run();\n\n const args: Arg[] = [];\n for (const item of rawItems) {\n if (item.type === RawItem.Error) {\n // Stop on first error \u2014 mirrors the reference implementation\n break;\n }\n args.push(classifyToken(item));\n }\n return args;\n}\n\n/**\n * Count the number of arguments in a raw argument string.\n */\nexport function countArguments(source: string): number {\n return lexArguments(source).length;\n}\n\n// ---------------------------------------------------------------------------\n// Token classification\n// ---------------------------------------------------------------------------\n\nconst varTestRegexp = /^[$_@][$A-Z_a-z][$0-9A-Z_.a-z]*/;\n\nfunction classifyToken(item: LexerItem<RawItem>): Arg {\n const text = item.text;\n const base = { text, start: item.start, end: item.position };\n\n switch (item.type) {\n case RawItem.String:\n return { ...base, type: ArgType.String };\n\n case RawItem.Expression:\n return { ...base, type: ArgType.Expression };\n\n case RawItem.SquareBracket: {\n // Determine if it's a link or image based on the opening characters.\n // Images start with [img[, [<img[, [>img[ (case-insensitive)\n // Links start with [[\n const inner = text.slice(1); // skip first [\n if (/^[<>]?[Ii][Mm][Gg]\\[/.test(inner)) {\n return { ...base, type: ArgType.Image };\n }\n return { ...base, type: ArgType.Link };\n }\n\n case RawItem.Bareword: {\n // Variable?\n if (varTestRegexp.test(text)) {\n const sigil = text[0] as '$' | '_' | '@';\n const pathParts = text.slice(1).split('.');\n return {\n ...base,\n type: ArgType.Variable,\n sigil,\n path: pathParts,\n };\n }\n\n // Keywords\n if (text === 'null') return { ...base, type: ArgType.Null };\n if (text === 'undefined') return { ...base, type: ArgType.Undefined };\n if (text === 'true') return { ...base, type: ArgType.Boolean };\n if (text === 'false') return { ...base, type: ArgType.Boolean };\n if (text === 'NaN') return { ...base, type: ArgType.NaN };\n\n // Number? (including negative numbers like -5, floats like 3.14)\n const asNum = Number(text);\n if (!Number.isNaN(asNum)) {\n return { ...base, type: ArgType.Number };\n }\n\n // Fallback: bareword\n return { ...base, type: ArgType.Bareword };\n }\n\n default:\n return { ...base, type: ArgType.Bareword };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generic lexer engine (ported from reference)\n// ---------------------------------------------------------------------------\n\ntype LexerState<T> = (lexer: Lexer<T>) => LexerState<T> | null;\n\ninterface LexerItem<T> {\n type: T;\n text: string;\n start: number;\n position: number;\n message?: string;\n}\n\nconst EOF = -1 as const;\ntype EOFT = -1;\n\nclass Lexer<T> {\n readonly source: string;\n state: LexerState<T> | null;\n start = 0;\n pos = 0;\n depth = 0;\n items: LexerItem<T>[] = [];\n\n constructor(source: string, initial: LexerState<T>) {\n this.source = source;\n this.state = initial;\n }\n\n run(): LexerItem<T>[] {\n while (this.state !== null) {\n this.state = this.state(this);\n }\n return this.items;\n }\n\n next(): EOFT | string {\n const ch = this.peek();\n this.pos++;\n return ch;\n }\n\n peek(): EOFT | string {\n if (this.pos >= this.source.length) return EOF;\n return this.source[this.pos];\n }\n\n backup(num = 1) {\n this.pos -= num;\n }\n\n forward(num = 1) {\n this.pos += num;\n }\n\n ignore() {\n this.start = this.pos;\n }\n\n accept(valid: string): boolean {\n const ch = this.next();\n if (ch === EOF) return false;\n if (valid.includes(ch as string)) return true;\n this.backup();\n return false;\n }\n\n acceptRun(valid: string) {\n for (;;) {\n const ch = this.next();\n if (ch === EOF) return;\n if (!valid.includes(ch as string)) {\n break;\n }\n }\n this.backup();\n }\n\n emit(type: T) {\n this.items.push({\n type,\n text: this.source.slice(this.start, this.pos),\n start: this.start,\n position: this.pos,\n });\n this.start = this.pos;\n }\n\n error(type: T, message: string): null {\n this.items.push({\n type,\n message,\n text: this.source.slice(this.start, this.pos),\n start: this.start,\n position: this.pos,\n });\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Macro-argument lexer states\n// ---------------------------------------------------------------------------\n\nenum RawItem {\n Error,\n Bareword,\n Expression,\n String,\n SquareBracket,\n}\n\nconst notSpaceRegex = /\\S/;\nconst spaceRegex = /\\s/;\n\nfunction slurpQuote(lexer: Lexer<RawItem>, endQuote: string): EOFT | number {\n for (;;) {\n const next = lexer.next();\n if (next === '\\\\') {\n const ch = lexer.next();\n if (ch !== EOF && ch !== '\\n') continue;\n } else if (next === EOF) {\n return EOF;\n } else if (next === '\\n' && endQuote !== '`') {\n return EOF;\n } else if (next === endQuote) {\n break;\n }\n }\n return lexer.pos;\n}\n\nfunction lexSpace(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const offset = lexer.source.slice(lexer.pos).search(notSpaceRegex);\n\n if (offset === -1) return null;\n if (offset !== 0) {\n lexer.pos += offset;\n lexer.ignore();\n }\n\n // Skip commas as argument separators\n if (lexer.peek() === ',') {\n lexer.next();\n lexer.ignore();\n return lexSpace;\n }\n\n switch (lexer.next()) {\n case '`':\n return lexExpression;\n case '\"':\n return lexDoubleQuote;\n case \"'\":\n return lexSingleQuote;\n case '[':\n return lexSquareBracket;\n default:\n return lexBareword;\n }\n}\n\nfunction lexExpression(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, '`') === EOF) {\n return lexer.error(RawItem.Error, 'unterminated backquote expression');\n }\n lexer.emit(RawItem.Expression);\n return lexSpace;\n}\n\nfunction lexDoubleQuote(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, '\"') === EOF) {\n return lexer.error(RawItem.Error, 'unterminated double quoted string');\n }\n lexer.emit(RawItem.String);\n return lexSpace;\n}\n\nfunction lexSingleQuote(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, \"'\") === EOF) {\n return lexer.error(RawItem.Error, 'unterminated single quoted string');\n }\n lexer.emit(RawItem.String);\n return lexSpace;\n}\n\nfunction lexSquareBracket(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const imgMeta = '<>IiMmGg';\n let what: string;\n\n if (lexer.accept(imgMeta)) {\n what = 'image';\n lexer.acceptRun(imgMeta);\n } else {\n what = 'link';\n }\n\n if (!lexer.accept('[')) {\n return lexer.error(RawItem.Error, `malformed ${what} markup`);\n }\n\n lexer.depth = 2;\n\n for (;;) {\n switch (lexer.next()) {\n case '\\\\': {\n const ch = lexer.next();\n if (ch !== EOF && ch !== '\\n') break;\n }\n /* falls through */\n case EOF:\n case '\\n':\n return lexer.error(RawItem.Error, `unterminated ${what} markup`);\n case '[':\n ++lexer.depth;\n break;\n case ']':\n --lexer.depth;\n if (lexer.depth < 0) {\n return lexer.error(RawItem.Error, \"unexpected right square bracket ']'\");\n }\n if (lexer.depth === 1) {\n if (lexer.next() === ']') {\n --lexer.depth;\n // break out of the for loop\n lexer.emit(RawItem.SquareBracket);\n return lexSpace;\n }\n lexer.backup();\n }\n break;\n }\n }\n}\n\nfunction lexBareword(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const offset = lexer.source.slice(lexer.pos).search(spaceRegex);\n if (offset === -1) {\n // Rest of string is bareword; check for comma at end\n let end = lexer.source.length;\n // Trim trailing commas from bareword\n while (end > lexer.pos && lexer.source[end - 1] === ',') {\n end--;\n }\n lexer.pos = end;\n lexer.emit(RawItem.Bareword);\n // If there was a comma, continue lexing\n if (end < lexer.source.length) {\n lexer.pos = end + 1; // skip the comma\n lexer.ignore();\n return lexSpace;\n }\n return null;\n }\n\n // Check if comma comes before space\n const commaOffset = lexer.source.slice(lexer.pos).indexOf(',');\n if (commaOffset !== -1 && commaOffset < offset) {\n lexer.pos += commaOffset;\n lexer.emit(RawItem.Bareword);\n lexer.pos++; // skip comma\n lexer.ignore();\n return lexSpace;\n }\n\n lexer.pos += offset;\n lexer.emit(RawItem.Bareword);\n return lexSpace;\n}\n", "/**\n * Variant-based parameter validation for Spindle macros.\n *\n * Ported from twee3-language-tools/src/spindle-0/parameters.ts with simplifications:\n * - No dependency on vscode types\n * - Uses the simplified ArgType enum from argument-lexer.ts\n * - Pratt-parser format string parser preserved for correct operator precedence\n *\n * Format syntax:\n * type \u2014 single required parameter (e.g. \"text\", \"number\", \"var\")\n * ...type \u2014 variadic (zero or more)\n * type |+ type \u2014 optional next (left required, right optional)\n * type &+ type \u2014 required chain (both required)\n * type | type \u2014 or (either left or right)\n * 'literal' \u2014 literal value match\n * (group) \u2014 grouping\n */\n\nimport { ArgType, type Arg } from './argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n variantIndex: number | null;\n errors: ArgumentError[];\n warnings: ArgumentWarning[];\n}\n\nexport interface ArgumentError {\n message: string;\n argIndex: number;\n}\n\nexport interface ArgumentWarning {\n message: string;\n argIndex: number;\n}\n\nexport interface StateInfo {\n passages: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Parameter type system\n// ---------------------------------------------------------------------------\n\ninterface ParameterType {\n name: string[];\n validate(arg: Arg, args: Arg[], index: number, state?: StateInfo): TypeError | TypeWarning | null;\n}\n\nclass TypeError {\n constructor(public message: string) {}\n}\n\nclass TypeWarning {\n constructor(public message: string) {}\n}\n\n/**\n * \"Always\" arguments \u2014 variables and expressions pass any type check because\n * we cannot determine their runtime value statically.\n */\nfunction isAlwaysArg(arg: Arg): boolean {\n return arg.type === ArgType.Variable || arg.type === ArgType.Expression;\n}\n\n// Type definitions\nconst parameterTypes: ParameterType[] = [\n {\n name: ['bool', 'boolean'],\n validate(arg) {\n return arg.type === ArgType.Boolean ? null : new TypeError('Argument is not a boolean');\n },\n },\n {\n name: ['null'],\n validate(arg) {\n return arg.type === ArgType.Null ? null : new TypeError(\"Argument is not 'null'\");\n },\n },\n {\n name: ['undefined'],\n validate(arg) {\n return arg.type === ArgType.Undefined ? null : new TypeError(\"Argument is not 'undefined'\");\n },\n },\n {\n name: ['number'],\n validate(arg) {\n return arg.type === ArgType.Number ? null : new TypeError('Argument is not a number');\n },\n },\n {\n name: ['NaN'],\n validate(arg) {\n return arg.type === ArgType.NaN ? null : new TypeError(\"Argument is not 'NaN'\");\n },\n },\n {\n name: ['link'],\n validate(arg) {\n return arg.type === ArgType.Link ? null : new TypeError('Argument is not a link');\n },\n },\n {\n name: ['image'],\n validate(arg) {\n return arg.type === ArgType.Image ? null : new TypeError('Argument is not an image');\n },\n },\n {\n name: ['bareword'],\n validate(arg) {\n return arg.type === ArgType.Bareword ? null : new TypeError('Argument is not a bareword');\n },\n },\n {\n name: ['string'],\n validate(arg) {\n return arg.type === ArgType.String ? null : new TypeError('Argument is not a quoted string');\n },\n },\n {\n name: ['text'],\n validate(arg) {\n const t = arg.type;\n if (\n t === ArgType.Bareword ||\n t === ArgType.String ||\n t === ArgType.Boolean ||\n t === ArgType.Null ||\n t === ArgType.NaN ||\n t === ArgType.Number\n ) {\n return null;\n }\n return new TypeError('Argument is not text');\n },\n },\n {\n name: ['var'],\n validate(arg) {\n return arg.type === ArgType.Variable ? null : new TypeError('Argument is not a variable');\n },\n },\n {\n name: ['passage'],\n validate(arg, _args, _index, state) {\n // Extract passage name from the argument\n let passageName: string | undefined;\n if (arg.type === ArgType.String) {\n // Strip quotes\n passageName = arg.text.slice(1, -1);\n } else if (arg.type === ArgType.Bareword) {\n passageName = arg.text;\n } else if (arg.type === ArgType.Number) {\n passageName = arg.text;\n } else if (arg.type === ArgType.NaN) {\n passageName = 'NaN';\n }\n\n if (passageName !== undefined) {\n passageName = passageName.replace(/\\\\/g, '');\n if (state && state.passages.length > 0) {\n if (!state.passages.includes(passageName)) {\n return new TypeWarning(`Nonexistent passage: \"${passageName}\"`);\n }\n }\n return null;\n }\n\n return new TypeError('Argument is not an acceptable passage');\n },\n },\n];\n\nfunction findParameterType(name: string): ParameterType | null {\n for (const pt of parameterTypes) {\n if (pt.name.includes(name)) return pt;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Format tree types\n// ---------------------------------------------------------------------------\n\nenum FormatKind {\n Type,\n Literal,\n Group,\n AndNext,\n MaybeNext,\n Or,\n Repeat,\n}\n\ntype Format =\n | FormatType\n | FormatLiteral\n | FormatAndNext\n | FormatMaybeNext\n | FormatOr\n | FormatRepeat;\n\ninterface FormatType {\n kind: FormatKind.Type;\n type: ParameterType;\n}\ninterface FormatLiteral {\n kind: FormatKind.Literal;\n value: string;\n}\ninterface FormatAndNext {\n kind: FormatKind.AndNext;\n left: Format;\n right: Format;\n}\ninterface FormatMaybeNext {\n kind: FormatKind.MaybeNext;\n left?: Format;\n right: Format;\n}\ninterface FormatOr {\n kind: FormatKind.Or;\n left: Format;\n right: Format;\n}\ninterface FormatRepeat {\n kind: FormatKind.Repeat;\n right: Format;\n}\n\n// Lex tokens (superset of Format for groups)\ntype FormatLex =\n | FormatType\n | FormatLiteral\n | { kind: FormatKind.Group; open: boolean }\n | { kind: FormatKind.AndNext }\n | { kind: FormatKind.MaybeNext }\n | { kind: FormatKind.Or }\n | { kind: FormatKind.Repeat };\n\n// ---------------------------------------------------------------------------\n// Format string lexer\n// ---------------------------------------------------------------------------\n\nconst LEX_LIMIT = 1000;\nconst wsRe = /\\s/;\nconst identStartRe = /[a-zA-Z]/;\nconst identStopRe = /[|&+\\-\\s)(]/;\nconst quoteRe = /['\"]/;\nconst digitRe = /[0-9]/;\n\nfunction lexFormat(formatString: string): FormatLex[] {\n let pos = 0;\n const lexed: FormatLex[] = [];\n let iter = 0;\n\n for (;;) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex iteration limit exceeded');\n if (pos >= formatString.length) break;\n\n const ch = formatString[pos];\n\n if (wsRe.test(ch)) {\n pos++;\n } else if (ch === '&') {\n pos++;\n const next = formatString[pos];\n if (next === '+') {\n pos++;\n lexed.push({ kind: FormatKind.AndNext });\n } else {\n throw new Error(`Lex: Expected '+' after '&', found '${next ?? 'EOF'}'`);\n }\n } else if (ch === '|') {\n pos++;\n const next = formatString[pos];\n if (next === '+') {\n pos++;\n lexed.push({ kind: FormatKind.MaybeNext });\n } else if (next === undefined) {\n throw new Error(\"Lex: Expected content after '|'\");\n } else if (wsRe.test(next)) {\n pos++;\n lexed.push({ kind: FormatKind.Or });\n } else if (identStartRe.test(next) || quoteRe.test(next)) {\n lexed.push({ kind: FormatKind.Or });\n } else {\n throw new Error(`Lex: Invalid character after '|': '${next}'`);\n }\n } else if (quoteRe.test(ch)) {\n const openQuote = ch;\n const start = pos;\n pos++;\n while (pos < formatString.length && formatString[pos] !== openQuote) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex string iteration limit exceeded');\n pos++;\n }\n if (pos >= formatString.length) throw new Error('Lex: Unterminated string literal');\n const value = formatString.slice(start + 1, pos);\n pos++; // skip closing quote\n lexed.push({ kind: FormatKind.Literal, value });\n } else if (ch === '(' || ch === ')') {\n pos++;\n lexed.push({ kind: FormatKind.Group, open: ch === '(' });\n } else if (identStartRe.test(ch)) {\n const start = pos;\n pos++;\n while (pos < formatString.length) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex identifier iteration limit exceeded');\n const c = formatString[pos];\n if (identStopRe.test(c) || c === undefined) break;\n if (identStartRe.test(c)) {\n pos++;\n } else if (digitRe.test(c)) {\n throw new Error(`Lex: Digit '${c}' not allowed in parameter type name`);\n } else {\n throw new Error(`Lex: Invalid character '${c}' in parameter type name`);\n }\n }\n const ident = formatString.slice(start, pos);\n const pt = findParameterType(ident);\n if (pt === null) throw new Error(`Lex: Unknown parameter type '${ident}'`);\n lexed.push({ kind: FormatKind.Type, type: pt });\n } else if (ch === '.' && formatString[pos + 1] === '.' && formatString[pos + 2] === '.') {\n pos += 3;\n lexed.push({ kind: FormatKind.Repeat });\n } else {\n throw new Error(`Lex: Unexpected character '${ch}'`);\n }\n }\n\n return lexed;\n}\n\n// ---------------------------------------------------------------------------\n// Format string parser (Pratt parser)\n// ---------------------------------------------------------------------------\n\nconst PARSE_LIMIT = 2000;\n\nfunction parseFormat(formatString: string): Format | null {\n const tokens = lexFormat(formatString);\n if (tokens.length === 0) return null;\n\n let index = 0;\n let iter = 0;\n\n function infixBp(kind: FormatKind): [number, number] | null {\n switch (kind) {\n case FormatKind.Or: return [9, 10];\n case FormatKind.AndNext: return [4, 5];\n case FormatKind.MaybeNext: return [2, 3];\n default: return null;\n }\n }\n\n function prefixBp(kind: FormatKind): number {\n switch (kind) {\n case FormatKind.MaybeNext: return 3;\n case FormatKind.Repeat: return 8;\n default: throw new Error(`Parse: Unexpected prefix operator kind ${kind}`);\n }\n }\n\n function isPrefixOp(t: FormatLex): boolean {\n return t.kind === FormatKind.MaybeNext || t.kind === FormatKind.Repeat;\n }\n\n function isValue(t: FormatLex): t is FormatType | FormatLiteral {\n return t.kind === FormatKind.Type || t.kind === FormatKind.Literal;\n }\n\n function exprBp(minBp: number): Format {\n if (++iter > PARSE_LIMIT) throw new Error('Format parse iteration limit exceeded');\n const cur = tokens[index];\n if (!cur) throw new Error('Parse: Unexpected end of format string');\n index++;\n\n let lhs: Format;\n\n if (isPrefixOp(cur)) {\n const rBp = prefixBp(cur.kind);\n const rhs = exprBp(rBp);\n lhs = { kind: cur.kind, right: rhs } as Format;\n } else if (cur.kind === FormatKind.Group) {\n const g = cur as { kind: FormatKind.Group; open: boolean };\n if (!g.open) throw new Error('Parse: Unexpected closing parenthesis');\n lhs = exprBp(0);\n const closing = tokens[index];\n if (!closing || closing.kind !== FormatKind.Group || (closing as { open: boolean }).open) {\n throw new Error('Parse: Expected closing parenthesis');\n }\n index++;\n } else if (isValue(cur)) {\n lhs = cur;\n } else {\n throw new Error('Parse: Expected value or prefix operator');\n }\n\n for (;;) {\n if (++iter > PARSE_LIMIT) throw new Error('Format parse operator iteration limit exceeded');\n const op = tokens[index];\n if (!op) break;\n const bp = infixBp(op.kind);\n if (bp === null) break;\n const [lBp, rBp] = bp;\n if (lBp < minBp) break;\n index++;\n const rhs = exprBp(rBp);\n lhs = { kind: op.kind, left: lhs, right: rhs } as Format;\n }\n\n return lhs;\n }\n\n return exprBp(0);\n}\n\n// ---------------------------------------------------------------------------\n// Format tree utilities\n// ---------------------------------------------------------------------------\n\nfunction formatArgCountRange(format: Format): { min: number; max: number } {\n switch (format.kind) {\n case FormatKind.Type:\n case FormatKind.Literal:\n return { min: 1, max: 1 };\n case FormatKind.AndNext: {\n const l = formatArgCountRange(format.left);\n const r = formatArgCountRange(format.right);\n return { min: l.min + r.min, max: l.max + r.max };\n }\n case FormatKind.MaybeNext: {\n const l = format.left ? formatArgCountRange(format.left) : { min: 0, max: 0 };\n const r = formatArgCountRange(format.right);\n return { min: l.min, max: l.max + r.max };\n }\n case FormatKind.Or: {\n const l = formatArgCountRange(format.left);\n const r = formatArgCountRange(format.right);\n return { min: Math.min(l.min, r.min), max: Math.max(l.max, r.max) };\n }\n case FormatKind.Repeat:\n return { min: 0, max: Infinity };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validator (tree-crawl)\n// ---------------------------------------------------------------------------\n\nenum CrawlStatus {\n NotFound,\n Failure,\n Success,\n}\n\ninterface CrawlResult {\n status: CrawlStatus;\n rank: number;\n argIndex: number;\n errors: ArgumentError[];\n warnings: ArgumentWarning[];\n}\n\nfunction makeError(status: CrawlStatus, message: string, argIndex: number, rank = 0): CrawlResult {\n return {\n status,\n rank,\n argIndex,\n errors: [{ message, argIndex }],\n warnings: [],\n };\n}\n\nfunction makeSuccess(argIndex: number, rank: number, warnings: ArgumentWarning[] = []): CrawlResult {\n return { status: CrawlStatus.Success, rank, argIndex, errors: [], warnings };\n}\n\nfunction isFail(s: CrawlStatus): boolean {\n return s === CrawlStatus.Failure || s === CrawlStatus.NotFound;\n}\n\nconst VALIDATE_LIMIT = 2000;\nconst CORRECT_TYPE_RANK = 1;\nconst CORRECT_RANK = 2;\n\nfunction crawlValidate(\n format: Format,\n args: Arg[],\n startIndex: number,\n state?: StateInfo,\n): CrawlResult {\n let iter = 0;\n\n function crawl(fmt: Format, argIdx: number): CrawlResult {\n if (++iter > VALIDATE_LIMIT) {\n throw new Error(`Validation iteration limit exceeded at argument ${argIdx}`);\n }\n\n switch (fmt.kind) {\n case FormatKind.MaybeNext: {\n let rank = 0;\n let warnings: ArgumentWarning[] = [];\n let idx = argIdx;\n\n if (fmt.left) {\n const left = crawl(fmt.left, idx);\n if (isFail(left.status)) return left;\n rank += left.rank;\n idx = left.argIndex;\n warnings = left.warnings;\n }\n\n const right = crawl(fmt.right, idx);\n if (right.status === CrawlStatus.NotFound) {\n return makeSuccess(idx, rank, warnings);\n }\n if (isFail(right.status)) {\n right.status = CrawlStatus.Failure;\n return right;\n }\n\n return makeSuccess(right.argIndex, rank + right.rank, warnings.concat(right.warnings));\n }\n\n case FormatKind.AndNext: {\n const left = crawl(fmt.left, argIdx);\n if (isFail(left.status)) return left;\n\n const right = crawl(fmt.right, left.argIndex);\n if (isFail(right.status)) return right;\n\n return makeSuccess(\n right.argIndex,\n left.rank + right.rank,\n left.warnings.concat(right.warnings),\n );\n }\n\n case FormatKind.Or: {\n const left = crawl(fmt.left, argIdx);\n if (!isFail(left.status)) return left;\n\n const right = crawl(fmt.right, argIdx);\n if (!isFail(right.status)) return right;\n\n // Both failed \u2014 return left's error\n return left;\n }\n\n case FormatKind.Repeat: {\n let rank = 0;\n let warnings: ArgumentWarning[] = [];\n let idx = argIdx;\n\n for (;;) {\n const r = crawl(fmt.right, idx);\n if (isFail(r.status)) break;\n idx = r.argIndex;\n rank += r.rank;\n warnings = warnings.concat(r.warnings);\n }\n\n return makeSuccess(idx, rank, warnings);\n }\n\n case FormatKind.Literal: {\n const arg = args[argIdx];\n if (arg === undefined) {\n return makeError(CrawlStatus.NotFound, `Expected literal '${fmt.value}' but no argument found`, argIdx);\n }\n if (isAlwaysArg(arg)) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n // Check literal match\n const argText = arg.type === ArgType.String ? arg.text.slice(1, -1) : arg.text;\n if (argText === fmt.value) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n // Special keyword matches\n if (\n (fmt.value === 'null' && arg.type === ArgType.Null) ||\n (fmt.value === 'undefined' && arg.type === ArgType.Undefined) ||\n (fmt.value === 'true' && arg.type === ArgType.Boolean && arg.text === 'true') ||\n (fmt.value === 'false' && arg.type === ArgType.Boolean && arg.text === 'false') ||\n (fmt.value === 'NaN' && arg.type === ArgType.NaN)\n ) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n return makeError(CrawlStatus.Failure, `Expected literal '${fmt.value}'`, argIdx, CORRECT_TYPE_RANK);\n }\n\n case FormatKind.Type: {\n const arg = args[argIdx];\n const typeDef = fmt.type;\n\n if (arg === undefined) {\n return makeError(\n CrawlStatus.NotFound,\n `Expected type '${typeDef.name[0]}' but no argument found`,\n argIdx,\n );\n }\n\n if (isAlwaysArg(arg)) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n const result = typeDef.validate(arg, args, argIdx, state);\n if (result instanceof TypeError) {\n return {\n status: CrawlStatus.Failure,\n rank: 0,\n argIndex: argIdx,\n errors: [{ message: result.message, argIndex: argIdx }],\n warnings: [],\n };\n }\n if (result instanceof TypeWarning) {\n return makeSuccess(argIdx + 1, CORRECT_RANK, [\n { message: result.message, argIndex: argIdx },\n ]);\n }\n\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n }\n }\n\n return crawl(format, startIndex);\n}\n\n// ---------------------------------------------------------------------------\n// Parameters class (public API)\n// ---------------------------------------------------------------------------\n\ninterface ParsedVariant {\n formatString: string;\n format: Format | null;\n}\n\nexport class Parameters {\n private variants: ParsedVariant[];\n\n constructor(variants: string[]) {\n this.variants = variants.map((s) => ({\n formatString: s,\n format: parseFormat(s),\n }));\n }\n\n /**\n * Validate an array of Arg tokens against these parameter variants.\n * Selects the best-matching variant by rank.\n */\n validate(args: Arg[], stateInfo?: StateInfo): ValidationResult {\n // Handle case where no variants exist\n if (this.variants.length === 0) {\n if (args.length === 0) {\n return { variantIndex: null, errors: [], warnings: [] };\n }\n return {\n variantIndex: null,\n errors: [{ message: 'Expected no arguments', argIndex: 0 }],\n warnings: [],\n };\n }\n\n let bestIndex: number | null = null;\n let bestRank = -Infinity;\n let bestErrors: ArgumentError[] = [];\n let bestWarnings: ArgumentWarning[] = [];\n let bestIsClean = false; // tracks whether the best has zero errors\n\n for (let i = 0; i < this.variants.length; i++) {\n const variant = this.variants[i];\n\n if (variant.format === null) {\n // Empty variant: accepts zero arguments\n if (args.length === 0) {\n // Perfect match \u2014 no errors\n if (!bestIsClean || 0 > bestRank) {\n bestIndex = i;\n bestRank = 0;\n bestErrors = [];\n bestWarnings = [];\n bestIsClean = true;\n }\n } else {\n // Args provided but variant expects none\n if (!bestIsClean && bestIndex === null) {\n bestIndex = i;\n bestRank = -1;\n bestErrors = [{ message: 'Expected no arguments', argIndex: 0 }];\n bestWarnings = [];\n }\n }\n continue;\n }\n\n const result = crawlValidate(variant.format, args, 0, stateInfo);\n\n // Check for unconsumed arguments\n let errors = result.errors;\n if (result.errors.length === 0 && result.argIndex < args.length) {\n errors = [\n {\n message: `Too many arguments: expected ${result.argIndex}, got ${args.length}`,\n argIndex: result.argIndex,\n },\n ];\n }\n\n const rank = result.rank;\n const isClean = errors.length === 0;\n\n if (isClean && (!bestIsClean || rank > bestRank)) {\n // Clean result beats any errored result, or a better clean result\n bestIndex = i;\n bestRank = rank;\n bestErrors = [];\n bestWarnings = result.warnings;\n bestIsClean = true;\n } else if (!isClean && !bestIsClean && rank > bestRank) {\n // Both errored \u2014 pick the higher-ranked error\n bestIndex = i;\n bestRank = rank;\n bestErrors = errors;\n bestWarnings = result.warnings;\n } else if (bestIndex === null) {\n // First variant tried \u2014 store as default\n bestIndex = i;\n bestRank = rank;\n bestErrors = errors;\n bestWarnings = result.warnings;\n bestIsClean = isClean;\n }\n }\n\n return {\n variantIndex: bestIndex,\n errors: bestErrors,\n warnings: bestWarnings,\n };\n }\n\n /**\n * Compute the min/max argument count across all variants.\n */\n argCountRange(): { min: number; max: number } {\n let min = Infinity;\n let max = 0;\n\n for (const variant of this.variants) {\n if (variant.format === null) {\n min = 0;\n } else {\n const range = formatArgCountRange(variant.format);\n min = Math.min(min, range.min);\n max = Math.max(max, range.max);\n }\n }\n\n if (min === Infinity) min = 0;\n return { min, max };\n }\n\n /**\n * Whether all variants are empty (accept no arguments).\n */\n isEmpty(): boolean {\n if (this.variants.length === 0) return true;\n return !this.variants.some((v) => v.format !== null);\n }\n}\n", "import type { Range } from '../types.js';\n\nexport interface PassageRef {\n name: string;\n range: Range;\n source: 'link' | 'macro';\n}\n\n/**\n * Regex for [[display|target]] and [[target]] link syntax.\n * Group 1: optional display text followed by pipe\n * Group 2: passage name (target)\n */\nconst linkRegex = /\\[\\[([^\\]]*?\\|)?([^\\]]+?)\\]\\]/g;\n\n/**\n * Build an array of line-start offsets from text.\n * lineStarts[i] is the character offset where line i begins.\n */\nfunction buildLineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) {\n if (text[i] === '\\n') {\n starts.push(i + 1);\n }\n }\n return starts;\n}\n\n/**\n * Convert a character offset to a line/character Position\n * using precomputed line-start offsets.\n */\nfunction offsetToPosition(offset: number, lineStarts: number[]): { line: number; character: number } {\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const mid = (low + high + 1) >> 1;\n if (lineStarts[mid] <= offset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return { line: low, character: offset - lineStarts[low] };\n}\n\n/**\n * Parse all passage references from bracket links in the given text.\n *\n * Supports:\n * [[PassageName]]\n * [[Display Text|Target]]\n *\n * @param text - the text to parse\n * @param lineOffset - optional line offset added to all line numbers (default 0)\n */\nexport function parseLinks(text: string, lineOffset: number = 0): PassageRef[] {\n const lineStarts = buildLineStarts(text);\n const refs: PassageRef[] = [];\n\n linkRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const passageName = match[2].trim();\n if (!passageName) continue;\n\n // Calculate position of the passage name within the match\n const nameStartInMatch = match[0].indexOf(passageName);\n const nameStart = match.index + nameStartInMatch;\n const nameEnd = nameStart + passageName.length;\n\n const startPos = offsetToPosition(nameStart, lineStarts);\n const endPos = offsetToPosition(nameEnd, lineStarts);\n\n const range: Range = {\n start: { line: startPos.line + lineOffset, character: startPos.character },\n end: { line: endPos.line + lineOffset, character: endPos.character },\n };\n\n refs.push({\n name: passageName,\n range,\n source: 'link',\n });\n }\n\n return refs;\n}\n", "import type { Diagnostic, MacroNode } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { DiagnosticCode, getSeverity } from '../core/diagnostic-codes.js';\nimport type { DiagnosticCodeValue } from '../core/diagnostic-codes.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\nimport { Parameters } from '../core/parsing/parameter-validator.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core diagnostic function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute all diagnostics for a single document within the workspace context.\n *\n * Checks:\n * - Macro validation (SP100, SP101, SP104, SP107, SP114, SP115)\n * - Argument/parameter validation (SP108, SP109, SP110, SP111, SP112)\n * - Variable validation (SP200, SP202)\n * - Link/widget validation (SP300, SP301)\n */\nexport function computeDiagnostics(uri: string, workspace: WorkspaceModel): Diagnostic[] {\n try {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const diagnostics: Diagnostic[] = [];\n\n // Parse macros for the whole document\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n // Collect all passage names across workspace for link validation\n const allPassages = workspace.passages.getAllPassages();\n const passageNames = new Set(allPassages.map(p => p.name));\n\n // Each validation step is wrapped individually so that a failure\n // in one category still allows the others to produce diagnostics.\n\n try {\n validateMacros(macros, workspace, diagnostics);\n } catch {\n // Macro validation failed \u2014 continue with other checks\n }\n\n try {\n validateArguments(macros, workspace, passageNames, diagnostics);\n } catch {\n // Argument validation failed \u2014 continue\n }\n\n try {\n validateVariables(uri, workspace, diagnostics);\n } catch {\n // Variable validation failed \u2014 continue\n }\n\n try {\n validateLinks(text, passages, passageNames, diagnostics);\n } catch {\n // Link validation failed \u2014 continue\n }\n\n try {\n validateWidgetInvocations(macros, workspace, diagnostics);\n } catch {\n // Widget validation failed \u2014 continue\n }\n\n return diagnostics;\n } catch {\n // Catastrophic failure \u2014 return empty diagnostics rather than crashing\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Macro validation (SP100, SP101, SP104, SP107, SP114, SP115)\n// ---------------------------------------------------------------------------\n\nfunction validateMacros(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n for (let curIndex = 0; curIndex < macros.length; curIndex++) {\n const macro = macros[curIndex];\n const info = workspace.macros.getMacro(macro.name);\n\n if (info) {\n // Known macro\n if (info.block) {\n // SP101: unmatched container\n if (macro.open && macro.pair === -1) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.MalformedContainer,\n `Malformed container: no matching {/${macro.name}}`,\n ));\n } else if (!macro.open && macro.pair === -1) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.MalformedContainer,\n `Malformed container: no matching {${macro.name}}`,\n ));\n }\n\n // SP114/SP115: children constraints\n if (info.children && info.children.length > 0 && macro.open && macro.pair !== -1) {\n validateChildren(macros, curIndex, macro, info.children, workspace, diagnostics);\n }\n } else {\n // SP104: closing tag on non-container\n if (!macro.open) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.IllegalClosingTag,\n `Illegal closing tag: {${macro.name}} is not a container`,\n ));\n }\n }\n\n // SP107: parents constraint\n if (info.parents && info.parents.length > 0 && macro.open) {\n if (!isInsideParent(macros, curIndex, info.parents, workspace)) {\n const parentList = info.parents.join(', ');\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.InvalidChildren,\n `Invalid: {${macro.name}} can only be inside {${parentList}}`,\n ));\n }\n }\n } else {\n // Check if it's a user-defined widget before flagging SP100\n const widget = workspace.widgets.getWidget(macro.name);\n if (!widget && macro.open) {\n // SP100: unrecognized macro\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.UndefinedMacro,\n `Unrecognized macro: {${macro.name}}`,\n ));\n }\n }\n }\n}\n\n/**\n * Check whether the macro at `index` is inside one of the allowed parent containers.\n */\nfunction isInsideParent(\n macros: MacroNode[],\n index: number,\n parents: string[],\n workspace: WorkspaceModel,\n): boolean {\n const parentSet = new Set(parents.map(p => p.toLowerCase()));\n\n // Walk backwards to find an enclosing container\n for (let i = index - 1; i >= 0; i--) {\n const candidate = macros[i];\n if (!candidate.open) continue;\n\n const candidateInfo = workspace.macros.getMacro(candidate.name);\n if (!candidateInfo?.block) continue;\n\n // Check if the candidate's pair extends past our macro\n if (candidate.pair !== -1 && candidate.pair > index) {\n // We are inside this container\n if (parentSet.has(candidate.name.toLowerCase())) {\n return true;\n }\n // We're inside a different container \u2014 keep looking for allowed parents\n }\n }\n\n return false;\n}\n\n/**\n * Validate children constraints for a paired container macro.\n */\nfunction validateChildren(\n macros: MacroNode[],\n curIndex: number,\n parentMacro: MacroNode,\n childConstraints: Array<{ name: string; min?: number; max?: number }>,\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n const children: Record<string, number> = Object.create(null);\n const startIndex = curIndex + 1;\n const endIndex = parentMacro.pair;\n\n for (let i = startIndex; i < endIndex; i++) {\n const child = macros[i];\n const childInfo = workspace.macros.getMacro(child.name);\n\n if (!childInfo) continue;\n\n // Skip contents of nested containers\n if (childInfo.block && child.open && child.pair !== -1) {\n i = child.pair;\n continue;\n }\n\n // Count direct children that match constraints\n for (const constraint of childConstraints) {\n if (constraint.name === child.name) {\n children[child.name] = (children[child.name] ?? 0) + 1;\n }\n }\n }\n\n // Check constraints\n for (const constraint of childConstraints) {\n const count = children[constraint.name] ?? 0;\n\n if (constraint.max !== undefined && count > constraint.max) {\n diagnostics.push(makeDiag(\n parentMacro.range,\n DiagnosticCode.ChildMaxExceeded,\n `Too many {${constraint.name}} in {${parentMacro.name}} (max ${constraint.max}, found ${count})`,\n ));\n }\n\n if (constraint.min !== undefined && count < constraint.min) {\n diagnostics.push(makeDiag(\n parentMacro.range,\n DiagnosticCode.ChildMinNotMet,\n `Too few {${constraint.name}} in {${parentMacro.name}} (min ${constraint.min}, found ${count})`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Argument / parameter validation (SP108, SP109, SP110, SP111, SP112)\n// ---------------------------------------------------------------------------\n\nfunction validateArguments(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n passageNames: Set<string>,\n diagnostics: Diagnostic[],\n): void {\n for (const macro of macros) {\n if (!macro.open) continue;\n\n const info = workspace.macros.getMacro(macro.name);\n if (!info) continue;\n if (info.skipArgs) continue;\n if (!info.parameters) continue;\n\n const rawArgs = macro.rawArgs ?? '';\n const args = lexArguments(rawArgs);\n\n const params = new Parameters(info.parameters);\n\n // SP108: empty parameters but received args\n if (params.isEmpty()) {\n if (args.length > 0) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ExpectedNoArguments,\n `Expected no arguments for {${macro.name}}, got ${args.length}`,\n ));\n }\n continue;\n }\n\n const stateInfo = { passages: Array.from(passageNames) };\n const result = params.validate(args, stateInfo);\n\n if (result.variantIndex === null) {\n // No variant matched at all \u2014 covered by isEmpty check above\n continue;\n }\n\n // SP109: parameter type errors\n for (const error of result.errors) {\n // Determine if it's a \"too many\" error or a type error\n if (error.message.startsWith('Too many arguments')) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.TooManyArguments,\n `{${macro.name}}: ${error.message}`,\n ));\n } else {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ParameterTypeError,\n `{${macro.name}}: ${error.message}`,\n ));\n }\n }\n\n // SP110: parameter warnings\n for (const warning of result.warnings) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ParameterWarning,\n `{${macro.name}}: ${warning.message}`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Variable validation (SP200, SP202)\n// ---------------------------------------------------------------------------\n\nfunction validateVariables(\n uri: string,\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n if (!workspace.variables.hasStoryVariables()) {\n // SP202: no StoryVariables passage\n // Only emit once per document, and only if there are variable usages\n const undeclared = workspace.variables.getUndeclared(uri);\n // Even with no StoryVariables, getUndeclared returns all usages since nothing is declared\n // Check if there are any variable usages at all\n const text = workspace.documents.getText(uri);\n if (text && /\\$[A-Za-z_$]/.test(text)) {\n // Check if there are non-special passages with variable usages\n const passages = workspace.passages.getPassagesInDocument(uri);\n const hasVarUsage = passages.some(p => {\n const excluded = new Set(['StoryVariables', 'StoryInit', 'StoryData', 'StoryScript', 'StoryInterface']);\n return !excluded.has(p.name) && !p.tags?.includes('script') && !p.tags?.includes('stylesheet');\n });\n if (hasVarUsage) {\n diagnostics.push(makeDiag(\n passages[0].range,\n DiagnosticCode.NoStoryVariables,\n 'No StoryVariables passage found. Declare all story variables with default values in a StoryVariables passage.',\n ));\n }\n }\n return;\n }\n\n // SP200: undeclared variable\n const undeclared = workspace.variables.getUndeclared(uri);\n for (const u of undeclared) {\n diagnostics.push(makeDiag(\n u.range,\n DiagnosticCode.UndeclaredVariable,\n `Variable '$${u.name}' is not declared in StoryVariables`,\n ));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Link validation (SP300)\n// ---------------------------------------------------------------------------\n\nfunction validateLinks(\n text: string,\n passages: Array<{ name: string; range: import('../core/types.js').Range }>,\n passageNames: Set<string>,\n diagnostics: Diagnostic[],\n): void {\n const links = parseLinks(text);\n for (const link of links) {\n if (!passageNames.has(link.name)) {\n diagnostics.push(makeDiag(\n link.range,\n DiagnosticCode.BrokenPassageLink,\n `Passage \"${link.name}\" not found in workspace`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget invocation validation (SP301)\n// ---------------------------------------------------------------------------\n\nfunction validateWidgetInvocations(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n for (const macro of macros) {\n if (!macro.open) continue;\n\n // Skip if it's a known macro (not a widget)\n const info = workspace.macros.getMacro(macro.name);\n if (info) continue;\n\n const widget = workspace.widgets.getWidget(macro.name);\n if (!widget) continue;\n\n // Count arguments provided\n const rawArgs = macro.rawArgs ?? '';\n const argCount = rawArgs.trim() === '' ? 0 : lexArguments(rawArgs).length;\n const expectedCount = widget.params.length;\n\n if (argCount !== expectedCount) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.WidgetArgCountMismatch,\n `Widget {${macro.name}} expects ${expectedCount} argument(s), got ${argCount}`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction makeDiag(\n range: import('../core/types.js').Range,\n code: DiagnosticCodeValue,\n message: string,\n): Diagnostic {\n return {\n range,\n message,\n severity: getSeverity(code),\n code,\n source: 'spindle',\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspDiagnostic(d: Diagnostic): import('vscode-languageserver').Diagnostic {\n const severityMap = {\n error: 1,\n warning: 2,\n info: 3,\n hint: 4,\n } as const;\n\n return {\n range: {\n start: { line: d.range.start.line, character: d.range.start.character },\n end: { line: d.range.end.line, character: d.range.end.character },\n },\n severity: severityMap[d.severity],\n code: d.code,\n source: d.source,\n message: d.message,\n };\n}\n\nexport const diagnosticsPlugin: SpindlePlugin = {\n id: 'diagnostics',\n capabilities: {},\n initialize(ctx: PluginContext) {\n const publishDiagnostics = () => {\n for (const uri of ctx.workspace.documents.getUris()) {\n const diags = computeDiagnostics(uri, ctx.workspace);\n ctx.connection.sendDiagnostics({\n uri,\n diagnostics: diags.map(d => toLspDiagnostic(d)),\n });\n }\n };\n\n ctx.workspace.on('modelReady', publishDiagnostics);\n ctx.workspace.on('documentChanged', (uri: string) => {\n const diags = computeDiagnostics(uri, ctx.workspace);\n ctx.connection.sendDiagnostics({\n uri,\n diagnostics: diags.map(d => toLspDiagnostic(d)),\n });\n });\n },\n};\n", "import { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\n\n/**\n * Spindle project config as loaded from `spindle.config.yaml/yml/json`.\n */\nexport interface SpindleProjectConfig {\n macros: Record<string, any>;\n}\n\nconst CONFIG_FILENAMES = [\n 'spindle.config.yaml',\n 'spindle.config.yml',\n 'spindle.config.json',\n];\n\nconst EMPTY_CONFIG: SpindleProjectConfig = { macros: {} };\n\n/**\n * Parse a config file's content in the given format.\n * Returns a SpindleProjectConfig with at least an empty `macros` record.\n */\nexport function parseConfig(\n content: string,\n format: 'yaml' | 'json',\n): SpindleProjectConfig {\n if (!content.trim()) {\n return { macros: {} };\n }\n\n let raw: unknown;\n if (format === 'json') {\n raw = JSON.parse(content);\n } else {\n raw = parseYaml(content);\n }\n\n if (typeof raw !== 'object' || raw === null) {\n return { macros: {} };\n }\n\n const obj = raw as Record<string, unknown>;\n return {\n macros: (typeof obj.macros === 'object' && obj.macros !== null)\n ? obj.macros as Record<string, any>\n : {},\n };\n}\n\n/**\n * Search for a config file in the workspace root directory.\n * Checks for spindle.config.yaml, spindle.config.yml, and spindle.config.json\n * in that order. Returns the full path of the first match, or null.\n */\nexport function findConfigFile(workspaceRoot: string): string | null {\n for (const name of CONFIG_FILENAMES) {\n const fullPath = join(workspaceRoot, name);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n}\n\n/**\n * Load and parse the project config from the workspace root.\n * Returns a default empty config if no config file is found.\n */\nexport function loadConfigFromDisk(workspaceRoot: string): SpindleProjectConfig {\n const configPath = findConfigFile(workspaceRoot);\n if (!configPath) {\n return { ...EMPTY_CONFIG };\n }\n\n const content = readFileSync(configPath, 'utf-8');\n const format = configPath.endsWith('.json') ? 'json' : 'yaml';\n return parseConfig(content, format);\n}\n", "import { fileURLToPath } from 'node:url';\nimport type { Diagnostic } from '../../core/types.js';\n\n/**\n * ANSI color codes for terminal output.\n */\nconst colors = {\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n};\n\nconst severityColors: Record<string, string> = {\n error: colors.red,\n warning: colors.yellow,\n info: colors.blue,\n hint: colors.cyan,\n};\n\n/**\n * Format diagnostics in a human-readable, colored terminal format.\n *\n * Example:\n * src/story.tw:5:1 error SP101 Malformed container: no matching {/if}\n * src/story.tw:7:1 warning SP100 Unrecognized macro: unknownMacro\n *\n * Found 2 problems (1 error, 1 warning)\n */\nexport function formatPretty(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n if (results.length === 0) {\n return `${colors.bold}No problems found${colors.reset}`;\n }\n\n const lines: string[] = [];\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n let hintCount = 0;\n\n for (const { uri, diagnostics } of results) {\n let filePath: string;\n try {\n filePath = fileURLToPath(uri);\n } catch {\n filePath = uri;\n }\n\n for (const diag of diagnostics) {\n const line = diag.range.start.line + 1;\n const col = diag.range.start.character + 1;\n const color = severityColors[diag.severity] ?? colors.gray;\n\n lines.push(\n `${colors.bold}${filePath}:${line}:${col}${colors.reset} ` +\n `${color}${diag.severity}${colors.reset} ` +\n `${colors.gray}${diag.code}${colors.reset} ` +\n `${diag.message}`,\n );\n\n switch (diag.severity) {\n case 'error': errorCount++; break;\n case 'warning': warningCount++; break;\n case 'info': infoCount++; break;\n case 'hint': hintCount++; break;\n }\n }\n }\n\n const total = errorCount + warningCount + infoCount + hintCount;\n const parts: string[] = [];\n if (errorCount > 0) parts.push(`${errorCount} error${errorCount !== 1 ? 's' : ''}`);\n if (warningCount > 0) parts.push(`${warningCount} warning${warningCount !== 1 ? 's' : ''}`);\n if (infoCount > 0) parts.push(`${infoCount} info`);\n if (hintCount > 0) parts.push(`${hintCount} hint${hintCount !== 1 ? 's' : ''}`);\n\n lines.push('');\n lines.push(\n `${colors.bold}Found ${total} problem${total !== 1 ? 's' : ''} (${parts.join(', ')})${colors.reset}`,\n );\n\n return lines.join('\\n');\n}\n", "import type { Diagnostic } from '../../core/types.js';\n\n/**\n * Format diagnostics as a JSON structure.\n *\n * Output shape:\n * ```json\n * {\n * \"files\": [\n * {\n * \"uri\": \"file:///path/to/story.tw\",\n * \"diagnostics\": [\n * {\n * \"range\": { \"start\": { \"line\": 4, \"character\": 0 }, \"end\": { \"line\": 4, \"character\": 10 } },\n * \"message\": \"...\",\n * \"severity\": \"error\",\n * \"code\": \"SP101\",\n * \"source\": \"spindle\"\n * }\n * ]\n * }\n * ]\n * }\n * ```\n */\nexport function formatJson(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n const output = {\n files: results.map(({ uri, diagnostics }) => ({\n uri,\n diagnostics: diagnostics.map(d => ({\n range: d.range,\n message: d.message,\n severity: d.severity,\n code: d.code,\n source: d.source,\n })),\n })),\n };\n\n return JSON.stringify(output, null, 2);\n}\n", "import type { Diagnostic } from '../../core/types.js';\n\n/**\n * SARIF 2.1.0 severity mapping.\n */\nconst sarifLevelMap: Record<string, string> = {\n error: 'error',\n warning: 'warning',\n info: 'note',\n hint: 'note',\n};\n\n/**\n * Format diagnostics in SARIF 2.1.0 format.\n *\n * @see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n */\nexport function formatSarif(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n // Collect unique rule IDs\n const ruleIds = new Set<string>();\n for (const { diagnostics } of results) {\n for (const d of diagnostics) {\n ruleIds.add(d.code);\n }\n }\n\n // Build SARIF results\n const sarifResults = [];\n for (const { uri, diagnostics } of results) {\n for (const d of diagnostics) {\n sarifResults.push({\n ruleId: d.code,\n level: sarifLevelMap[d.severity] ?? 'note',\n message: { text: d.message },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri },\n region: {\n startLine: d.range.start.line + 1,\n startColumn: d.range.start.character + 1,\n endLine: d.range.end.line + 1,\n endColumn: d.range.end.character + 1,\n },\n },\n },\n ],\n });\n }\n }\n\n const sarif = {\n $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',\n version: '2.1.0' as const,\n runs: [\n {\n tool: {\n driver: {\n name: 'spindle-lsp',\n version: '0.1.0',\n rules: Array.from(ruleIds).map(id => ({\n id,\n shortDescription: { text: `Spindle diagnostic ${id}` },\n })),\n },\n },\n results: sarifResults,\n },\n ],\n };\n\n return JSON.stringify(sarif, null, 2);\n}\n", "import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { glob } from 'glob';\n\nimport { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport { computeDiagnostics } from '../plugins/diagnostics.js';\nimport { loadConfigFromDisk } from '../core/workspace/config-loader.js';\nimport type { Diagnostic } from '../core/types.js';\nimport { formatPretty } from './reporters/pretty.js';\nimport { formatJson } from './reporters/json.js';\nimport { formatSarif } from './reporters/sarif.js';\n\n// ---------------------------------------------------------------------------\n// Argument parsing\n// ---------------------------------------------------------------------------\n\ninterface CheckOptions {\n format: 'pretty' | 'json' | 'sarif';\n severity: 'error' | 'warning' | 'info' | 'hint' | null;\n configPath: string | null;\n patterns: string[];\n}\n\nfunction parseArgs(args: string[]): CheckOptions {\n const options: CheckOptions = {\n format: 'pretty',\n severity: null,\n configPath: null,\n patterns: [],\n };\n\n let i = 0;\n while (i < args.length) {\n const arg = args[i];\n\n if (arg === '--format' && i + 1 < args.length) {\n const fmt = args[i + 1];\n if (fmt === 'pretty' || fmt === 'json' || fmt === 'sarif') {\n options.format = fmt;\n }\n i += 2;\n } else if (arg.startsWith('--format=')) {\n const fmt = arg.slice('--format='.length);\n if (fmt === 'pretty' || fmt === 'json' || fmt === 'sarif') {\n options.format = fmt;\n }\n i++;\n } else if (arg === '--severity' && i + 1 < args.length) {\n const sev = args[i + 1];\n if (sev === 'error' || sev === 'warning' || sev === 'info' || sev === 'hint') {\n options.severity = sev;\n }\n i += 2;\n } else if (arg.startsWith('--severity=')) {\n const sev = arg.slice('--severity='.length);\n if (sev === 'error' || sev === 'warning' || sev === 'info' || sev === 'hint') {\n options.severity = sev;\n }\n i++;\n } else if (arg === '--config' && i + 1 < args.length) {\n options.configPath = args[i + 1];\n i += 2;\n } else if (arg.startsWith('--config=')) {\n options.configPath = arg.slice('--config='.length);\n i++;\n } else if (!arg.startsWith('--')) {\n options.patterns.push(arg);\n i++;\n } else {\n // Skip unknown flags\n i++;\n }\n }\n\n if (options.patterns.length === 0) {\n options.patterns = ['**/*.{tw,twee}'];\n }\n\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Severity filtering\n// ---------------------------------------------------------------------------\n\nconst SEVERITY_ORDER = ['hint', 'info', 'warning', 'error'] as const;\n\nfunction filterBySeverity(\n diagnostics: Diagnostic[],\n minSeverity: 'error' | 'warning' | 'info' | 'hint',\n): Diagnostic[] {\n const minIdx = SEVERITY_ORDER.indexOf(minSeverity);\n return diagnostics.filter(d => {\n const idx = SEVERITY_ORDER.indexOf(d.severity);\n return idx >= minIdx;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\nexport async function runCheck(args: string[]): Promise<number> {\n const options = parseArgs(args);\n\n // Determine workspace root (cwd)\n const cwd = process.cwd();\n\n // Resolve files via glob\n const files: string[] = [];\n for (const pattern of options.patterns) {\n const matches = await glob(pattern, {\n cwd,\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n // Deduplicate\n const uniqueFiles = [...new Set(files)];\n\n if (uniqueFiles.length === 0) {\n if (options.format === 'pretty') {\n console.log('No files found');\n } else if (options.format === 'json') {\n console.log(JSON.stringify({ files: [] }, null, 2));\n } else {\n console.log(formatSarif([]));\n }\n return 0;\n }\n\n // Load project config\n const configRoot = options.configPath\n ? resolve(cwd, options.configPath, '..')\n : cwd;\n const projectConfig = loadConfigFromDisk(configRoot);\n\n // Create workspace and load files\n const workspace = new WorkspaceModel();\n const fileContents = new Map<string, string>();\n for (const filePath of uniqueFiles) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = pathToFileURL(filePath).toString();\n fileContents.set(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n workspace.initialize(fileContents);\n\n // Load user macros from config\n if (Object.keys(projectConfig.macros).length > 0) {\n workspace.macros.loadSupplements(projectConfig.macros);\n }\n\n // Compute diagnostics for each file\n const allResults: Array<{ uri: string; diagnostics: Diagnostic[] }> = [];\n let hasErrors = false;\n\n for (const uri of fileContents.keys()) {\n let diags = computeDiagnostics(uri, workspace);\n\n // Filter by severity if specified\n if (options.severity) {\n diags = filterBySeverity(diags, options.severity);\n }\n\n if (diags.length > 0) {\n allResults.push({ uri, diagnostics: diags });\n if (diags.some(d => d.severity === 'error')) {\n hasErrors = true;\n }\n }\n }\n\n // Format output\n switch (options.format) {\n case 'pretty':\n console.log(formatPretty(allResults));\n break;\n case 'json':\n console.log(formatJson(allResults));\n break;\n case 'sarif':\n console.log(formatSarif(allResults));\n break;\n }\n\n // Cleanup\n workspace.dispose();\n\n return hasErrors ? 1 : 0;\n}\n", "import type { Range } from '../core/types.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\n\n// ---------------------------------------------------------------------------\n// Block macro patterns for indentation\n// ---------------------------------------------------------------------------\n\n/**\n * Matches opening block macros: {if ...}, {for ...}, {switch ...}, {unless ...}\n * Also handles custom block macros via generic pattern.\n */\nconst BLOCK_OPEN_REGEX = /^\\s*\\{(if|for|switch|unless|widget)\\b/i;\n\n/**\n * Matches closing block macros: {/if}, {/for}, {/switch}, {/unless}\n */\nconst BLOCK_CLOSE_REGEX = /^\\s*\\{\\/(if|for|switch|unless|widget)\\b/i;\n\n/**\n * Passage header pattern.\n */\nconst PASSAGE_HEADER_REGEX = /^(::)\\s+/;\n\n// ---------------------------------------------------------------------------\n// Core format functions (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Format an entire document.\n *\n * Rules:\n * 1. Indent content inside block macros by 2 spaces per nesting level\n * 2. Remove trailing whitespace from each line\n * 3. Ensure file ends with a single newline\n * 4. Normalize passage headers: `:: Name [tag]` -> `:: Name [tag]`\n */\nexport function formatDocument(text: string): string {\n const lines = text.split('\\n');\n const result: string[] = [];\n let indentLevel = 0;\n\n for (let i = 0; i < lines.length; i++) {\n let line = lines[i];\n\n // Remove trailing whitespace\n line = line.replace(/\\s+$/, '');\n\n // Normalize passage headers\n if (PASSAGE_HEADER_REGEX.test(line)) {\n line = normalizePassageHeader(line);\n // Reset indent at passage boundaries\n indentLevel = 0;\n result.push(line);\n continue;\n }\n\n const trimmed = line.trim();\n\n // Empty lines: keep them but without extra whitespace\n if (trimmed === '') {\n result.push('');\n continue;\n }\n\n // Check if this line closes a block (reduce indent before writing)\n if (BLOCK_CLOSE_REGEX.test(trimmed)) {\n indentLevel = Math.max(0, indentLevel - 1);\n }\n\n // Apply indentation\n const indented = indentLevel > 0\n ? ' '.repeat(indentLevel) + trimmed\n : trimmed;\n result.push(indented);\n\n // Check if this line opens a block (increase indent for subsequent lines)\n if (BLOCK_OPEN_REGEX.test(trimmed)) {\n indentLevel++;\n }\n }\n\n // Ensure file ends with a single newline\n let output = result.join('\\n');\n output = output.replace(/\\n*$/, '\\n');\n\n return output;\n}\n\n/**\n * Format a specific range within a document.\n * Extracts the range, formats it, and replaces back.\n */\nexport function formatRange(text: string, range: Range): string {\n const lines = text.split('\\n');\n const startLine = Math.max(0, range.start.line);\n const endLine = Math.min(lines.length - 1, range.end.line);\n\n // Extract the range\n const rangeLines = lines.slice(startLine, endLine + 1);\n const rangeText = rangeLines.join('\\n');\n\n // Format just that section\n const formatted = formatDocument(rangeText);\n const formattedLines = formatted.replace(/\\n$/, '').split('\\n');\n\n // Reconstruct the full document\n const before = lines.slice(0, startLine);\n const after = lines.slice(endLine + 1);\n const result = [...before, ...formattedLines, ...after].join('\\n');\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a passage header line.\n * Collapses whitespace: `:: Name [tag]` -> `:: Name [tag]`\n */\nfunction normalizePassageHeader(line: string): string {\n // Split into parts: \"::\", name, optional tags/metadata\n const headerMatch = line.match(/^::\\s+(.*)/);\n if (!headerMatch) return line;\n\n const rest = headerMatch[1];\n\n // Check for tags in brackets\n const bracketIdx = rest.indexOf('[');\n const braceIdx = rest.indexOf('{');\n\n let name: string;\n let suffix = '';\n\n if (bracketIdx !== -1 && (braceIdx === -1 || bracketIdx < braceIdx)) {\n name = rest.substring(0, bracketIdx).trim();\n suffix = ' ' + rest.substring(bracketIdx).trim();\n } else if (braceIdx !== -1) {\n name = rest.substring(0, braceIdx).trim();\n suffix = ' ' + rest.substring(braceIdx).trim();\n } else {\n name = rest.trim();\n }\n\n return `:: ${name}${suffix}`;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const formatPlugin: SpindlePlugin = {\n id: 'format',\n capabilities: {\n documentFormattingProvider: true,\n documentRangeFormattingProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentFormatting((params) => {\n const text = ctx.workspace.documents.getText(params.textDocument.uri);\n if (text === undefined) return [];\n\n const formatted = formatDocument(text);\n if (formatted === text) return [];\n\n const lines = text.split('\\n');\n return [{\n range: {\n start: { line: 0, character: 0 },\n end: { line: lines.length - 1, character: lines[lines.length - 1].length },\n },\n newText: formatted,\n }];\n });\n\n ctx.connection.onDocumentRangeFormatting((params) => {\n const text = ctx.workspace.documents.getText(params.textDocument.uri);\n if (text === undefined) return [];\n\n const range: Range = {\n start: { line: params.range.start.line, character: params.range.start.character },\n end: { line: params.range.end.line, character: params.range.end.character },\n };\n\n const formatted = formatRange(text, range);\n if (formatted === text) return [];\n\n const lines = text.split('\\n');\n return [{\n range: {\n start: { line: 0, character: 0 },\n end: { line: lines.length - 1, character: lines[lines.length - 1].length },\n },\n newText: formatted,\n }];\n });\n },\n};\n", "import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { glob } from 'glob';\n\nimport { formatDocument } from '../plugins/format.js';\n\n// ---------------------------------------------------------------------------\n// Argument parsing\n// ---------------------------------------------------------------------------\n\ninterface FormatOptions {\n check: boolean;\n patterns: string[];\n}\n\nfunction parseArgs(args: string[]): FormatOptions {\n const options: FormatOptions = {\n check: false,\n patterns: [],\n };\n\n for (const arg of args) {\n if (arg === '--check') {\n options.check = true;\n } else if (!arg.startsWith('--')) {\n options.patterns.push(arg);\n }\n }\n\n if (options.patterns.length === 0) {\n options.patterns = ['**/*.{tw,twee}'];\n }\n\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\nexport async function runFormat(args: string[]): Promise<number> {\n const options = parseArgs(args);\n const cwd = process.cwd();\n\n // Resolve files via glob\n const files: string[] = [];\n for (const pattern of options.patterns) {\n const matches = await glob(pattern, {\n cwd,\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n const uniqueFiles = [...new Set(files)];\n\n if (uniqueFiles.length === 0) {\n console.log('No files found');\n return 0;\n }\n\n const unformatted: string[] = [];\n\n for (const filePath of uniqueFiles) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const formatted = formatDocument(text);\n\n if (formatted !== text) {\n if (options.check) {\n const relative = filePath.startsWith(cwd)\n ? filePath.slice(cwd.length + 1)\n : filePath;\n unformatted.push(relative);\n } else {\n writeFileSync(filePath, formatted, 'utf-8');\n }\n }\n } catch {\n // Skip unreadable/unwritable files\n }\n }\n\n if (options.check) {\n if (unformatted.length > 0) {\n for (const file of unformatted) {\n console.log(file);\n }\n console.log(`\\n${unformatted.length} file${unformatted.length !== 1 ? 's' : ''} would be reformatted`);\n return 1;\n }\n return 0;\n }\n\n return 0;\n}\n", "import type { ServerCapabilities } from 'vscode-languageserver';\nimport type { SpindlePlugin, SpindleConfig } from './plugin-api.js';\n\n/**\n * Filter plugins based on the disabled list in config.\n * Returns only plugins whose id is NOT in `config.disabledPlugins`.\n */\nexport function loadPlugins(\n allPlugins: SpindlePlugin[],\n config: SpindleConfig,\n): SpindlePlugin[] {\n const disabled = new Set(config.disabledPlugins ?? []);\n return allPlugins.filter((p) => !disabled.has(p.id));\n}\n\n/**\n * Deep-merge capabilities from all plugins into a single ServerCapabilities object.\n *\n * For boolean capabilities, any plugin providing `true` wins.\n * For object capabilities, properties are merged (later plugins override on collision).\n */\nexport function mergeCapabilities(\n plugins: SpindlePlugin[],\n): Partial<ServerCapabilities> {\n const merged: Record<string, unknown> = {};\n\n for (const plugin of plugins) {\n for (const [key, value] of Object.entries(plugin.capabilities)) {\n const existing = merged[key];\n if (existing === undefined) {\n merged[key] = value;\n } else if (\n typeof existing === 'object' &&\n existing !== null &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(existing) &&\n !Array.isArray(value)\n ) {\n // Deep merge plain objects one level\n merged[key] = { ...(existing as Record<string, unknown>), ...(value as Record<string, unknown>) };\n } else {\n // Primitives / booleans: later value wins (true wins over false)\n merged[key] = value;\n }\n }\n }\n\n return merged as Partial<ServerCapabilities>;\n}\n", "import { TextDocumentSyncKind } from 'vscode-languageserver';\nimport type { ServerCapabilities } from 'vscode-languageserver';\nimport type { SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { mergeCapabilities } from '../core/plugin/plugin-loader.js';\n\n/**\n * Build the full ServerCapabilities object by combining the base capabilities\n * (text document sync) with all plugin-contributed capabilities.\n */\nexport function buildCapabilities(\n plugins: SpindlePlugin[],\n): ServerCapabilities {\n const pluginCaps = mergeCapabilities(plugins);\n return {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n ...pluginCaps,\n };\n}\n", "import type { CompletionItem } from 'vscode-languageserver';\nimport type { Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core completion function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute completion items for a given position within a document.\n *\n * Contexts:\n * - After `{/` -> closing macro names (open block macros above cursor)\n * - After `{` -> macro names + widget names\n * - After `$` -> story variable names\n * - After `_` -> temp variable names from current document\n * - After `@` -> local variable names from current document\n * - After `$var.` -> declared object fields\n * - After `[[` -> passage names\n */\nexport function getCompletions(\n uri: string,\n position: Position,\n triggerChar: string | undefined,\n workspace: WorkspaceModel,\n): CompletionItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return [];\n const lineText = lines[position.line].substring(0, position.character);\n\n // --- Context: closing macro `{/` ---\n if (/\\{\\/[A-Za-z\\w-]*$/.test(lineText)) {\n return getClosingMacroCompletions(text, position, workspace);\n }\n\n // --- Context: dot-path field `$var.` ---\n const dotPathMatch = /\\$([A-Za-z_$][\\w$]*)\\.([A-Za-z_$][\\w$]*)?$/.exec(lineText);\n if (dotPathMatch) {\n return getDotPathCompletions(dotPathMatch[1], workspace);\n }\n\n // --- Context: story variable `$` ---\n if (/\\$[A-Za-z_$]?[\\w$]*$/.test(lineText) && !/\\$[A-Za-z_$][\\w$]*\\./.test(lineText)) {\n return getStoryVariableCompletions(workspace);\n }\n\n // --- Context: temporary variable `_` ---\n if (/_[A-Za-z_$]?[\\w$]*$/.test(lineText)) {\n return getTempVariableCompletions(text);\n }\n\n // --- Context: local variable `@` ---\n if (/@[A-Za-z_$]?[\\w$]*$/.test(lineText)) {\n return getLocalVariableCompletions(text);\n }\n\n // --- Context: passage link `[[` ---\n if (/\\[\\[[^\\]]*$/.test(lineText)) {\n return getPassageNameCompletions(workspace);\n }\n\n // --- Context: macro invocation `{` or `{partial` ---\n if (/(?:^|[^\\\\])\\{[A-Za-z\\w-]*$/.test(lineText)) {\n return getMacroCompletions(workspace);\n }\n\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getClosingMacroCompletions(\n text: string,\n position: Position,\n workspace: WorkspaceModel,\n): CompletionItem[] {\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n const openStack: string[] = [];\n for (const macro of macros) {\n if (macro.range.start.line > position.line ||\n (macro.range.start.line === position.line && macro.range.start.character >= position.character)) {\n break;\n }\n if (!macro.open) continue;\n if (!workspace.macros.isBlock(macro.name)) continue;\n\n if (macro.pair === -1) {\n openStack.push(macro.name);\n } else {\n const pairMacro = macros[macro.pair];\n if (pairMacro && (pairMacro.range.start.line > position.line ||\n (pairMacro.range.start.line === position.line && pairMacro.range.start.character > position.character))) {\n openStack.push(macro.name);\n }\n }\n }\n\n if (openStack.length === 0) return [];\n\n const seen = new Set<string>();\n const suggestions: string[] = [];\n for (let i = openStack.length - 1; i >= 0; i--) {\n const name = openStack[i];\n if (!seen.has(name)) {\n seen.add(name);\n suggestions.push(name);\n }\n }\n\n return suggestions.map((name, idx) => ({\n label: `{/${name}}`,\n kind: 14, // CompletionItemKind.Keyword\n detail: `Close {${name}}`,\n sortText: String(idx).padStart(3, '0'),\n insertText: `{/${name}}`,\n }));\n}\n\nfunction getMacroCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const items: CompletionItem[] = [];\n\n for (const macro of workspace.macros.getAllMacros()) {\n items.push({\n label: macro.name,\n kind: 3, // CompletionItemKind.Function\n detail: macro.block ? `(container macro) ${macro.name}` : `(macro) ${macro.name}`,\n documentation: macro.description ?? undefined,\n });\n }\n\n for (const widget of workspace.widgets.getAllWidgets()) {\n items.push({\n label: widget.name,\n kind: 3, // CompletionItemKind.Function\n detail: `(widget) ${widget.name}`,\n documentation: widget.params.length > 0\n ? `Parameters: ${widget.params.map(p => `@${p}`).join(', ')}`\n : undefined,\n });\n }\n\n return items;\n}\n\nfunction getStoryVariableCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const declared = workspace.variables.getDeclared();\n if (declared.size === 0) return [];\n\n const items: CompletionItem[] = [];\n for (const [name, decl] of declared) {\n items.push({\n label: `$${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'story variable',\n insertText: name,\n documentation: decl.fields && decl.fields.length > 0\n ? `Fields: ${decl.fields.join(', ')}`\n : undefined,\n });\n }\n return items;\n}\n\nfunction getTempVariableCompletions(text: string): CompletionItem[] {\n const tempVarRegex = /_([A-Za-z_$][\\w$]*)/g;\n const names = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = tempVarRegex.exec(text)) !== null) {\n names.add(m[1]);\n }\n if (names.size === 0) return [];\n\n return Array.from(names).map(name => ({\n label: `_${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'temporary variable',\n insertText: name,\n }));\n}\n\nfunction getLocalVariableCompletions(text: string): CompletionItem[] {\n const atVarRegex = /@([A-Za-z_$][\\w$]*)/g;\n const names = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = atVarRegex.exec(text)) !== null) {\n names.add(m[1]);\n }\n if (names.size === 0) return [];\n\n return Array.from(names).map(name => ({\n label: `@${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'local/parameter variable',\n insertText: name,\n }));\n}\n\nfunction getDotPathCompletions(varName: string, workspace: WorkspaceModel): CompletionItem[] {\n const declared = workspace.variables.getDeclared();\n const decl = declared.get(varName);\n if (!decl || !decl.fields || decl.fields.length === 0) return [];\n\n return decl.fields.map(field => ({\n label: field,\n kind: 5, // CompletionItemKind.Field\n detail: `field of $${varName}`,\n }));\n}\n\nfunction getPassageNameCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const passages = workspace.passages.getAllPassages();\n if (passages.length === 0) return [];\n\n return passages.map(p => ({\n label: p.name,\n kind: 18, // CompletionItemKind.Reference\n detail: p.uri,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const completionsPlugin: SpindlePlugin = {\n id: 'completions',\n capabilities: {\n completionProvider: {\n triggerCharacters: ['{', '$', '_', '@', '[', '.'],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCompletion((params) => {\n const uri = params.textDocument.uri;\n const position: Position = {\n line: params.position.line,\n character: params.position.character,\n };\n const triggerChar = params.context?.triggerCharacter;\n return getCompletions(uri, position, triggerChar, ctx.workspace);\n });\n },\n};\n", "import type { Hover, Range as LspRange } from 'vscode-languageserver';\nimport type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\n\n// ---------------------------------------------------------------------------\n// Core hover function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface HoverResult {\n contents: string;\n range: Range;\n}\n\n/**\n * Compute hover information for the symbol at the given position.\n *\n * Provides information for:\n * - Macro names -> description, parameters, block/inline\n * - Variables -> \"Story variable\" / \"Temp variable\" / \"Local variable\" + type info\n * - Widget names -> widget info with params\n */\nexport function getHoverInfo(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Macro name hover ---\n // Check if cursor is on a macro name inside {macroName ...} or {/macroName}\n const macroResult = getMacroHover(line, position, workspace);\n if (macroResult) return macroResult;\n\n // --- Variable hover ---\n const varResult = getVariableHover(line, position, workspace);\n if (varResult) return varResult;\n\n // --- Widget invocation hover ---\n const widgetResult = getWidgetHover(line, position, workspace);\n if (widgetResult) return widgetResult;\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getMacroHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Match macro patterns: {macroName ...} or {/macroName}\n const macroRegex = /\\{(\\/)?(?:(?:[#.][a-zA-Z][\\w-]*\\s*)*)([A-Za-z][\\w-]*)/g;\n let match: RegExpExecArray | null;\n\n while ((match = macroRegex.exec(line)) !== null) {\n const name = match[2];\n const nameStart = match.index + match[0].indexOf(name);\n const nameEnd = nameStart + name.length;\n\n if (position.character >= nameStart && position.character <= nameEnd) {\n const info = workspace.macros.getMacro(name);\n if (info) {\n const parts: string[] = [];\n parts.push(`**${info.name}** _(${info.block ? 'container' : 'inline'} macro)_`);\n if (info.description) {\n parts.push('', info.description);\n }\n if (info.parameters && info.parameters.length > 0) {\n parts.push('', `Parameters: \\`${info.parameters.join(' ')}\\``);\n }\n\n return {\n contents: parts.join('\\n'),\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n\n // Check widgets\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return buildWidgetHover(widget, position.line, nameStart, nameEnd);\n }\n }\n }\n\n return null;\n}\n\nfunction getVariableHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Story variables: $name\n {\n const re = /\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const baseName = match[1].split('.')[0];\n const decl = workspace.variables.getDeclared().get(baseName);\n const typeInfo = decl?.fields && decl.fields.length > 0\n ? `\\n\\nFields: ${decl.fields.map(f => `\\`${f}\\``).join(', ')}`\n : '';\n return {\n contents: `**Story variable** \\`$${match[1]}\\`${typeInfo}`,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // Temp variables: _name\n {\n const re = /(?<!\\w)_([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n contents: `**Temp variable** \\`_${match[1]}\\``,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // Local variables: @name\n {\n const re = /(?<!\\w)@([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n contents: `**Local variable** \\`@${match[1]}\\``,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n return null;\n}\n\nfunction getWidgetHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Widget invocation: {widgetName ...}\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1; // skip '{'\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return buildWidgetHover(widget, position.line, nameStart, nameEnd);\n }\n }\n }\n return null;\n}\n\nfunction buildWidgetHover(\n widget: import('../core/types.js').WidgetDef,\n line: number,\n nameStart: number,\n nameEnd: number,\n): HoverResult {\n const sig = widget.params.length > 0\n ? widget.params.map(p => `@${p}`).join(', ')\n : 'no parameters';\n return {\n contents: `**Widget** \\`${widget.name}\\`\\n\\nParameters: ${sig}\\n\\nDefined in: \\`${widget.uri}\\``,\n range: {\n start: { line, character: nameStart },\n end: { line, character: nameEnd },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): LspRange {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const hoverPlugin: SpindlePlugin = {\n id: 'hover',\n capabilities: {\n hoverProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onHover((params): Hover | null => {\n const result = getHoverInfo(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n contents: { kind: 'markdown', value: result.contents },\n range: toLspRange(result.range),\n };\n });\n },\n};\n", "import type { SignatureHelp, SignatureInformation, ParameterInformation } from 'vscode-languageserver';\nimport type { Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Core signature help function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface SignatureHelpResult {\n signatures: Array<{\n label: string;\n documentation?: string;\n parameters: Array<{ label: string }>;\n }>;\n activeSignature: number;\n activeParameter: number;\n}\n\n/**\n * Compute signature help for the macro at the given position.\n *\n * When the cursor is inside macro arguments, shows parameter information\n * and highlights the active parameter based on argument count before cursor.\n */\nexport function getSignatureHelp(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): SignatureHelpResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const lineText = lines[position.line];\n const textBefore = lineText.substring(0, position.character);\n\n // Find the enclosing macro: {macroName args...\n const macroMatch = textBefore.match(/\\{(?:[#.][a-zA-Z][\\w-]*\\s*)*([A-Za-z][\\w-]*)\\s+([^}]*)$/);\n if (!macroMatch) return null;\n\n const macroName = macroMatch[1];\n const argsBefore = macroMatch[2];\n\n // Count arguments before cursor to determine active parameter\n const activeParameter = argsBefore.trim() === '' ? 0 : lexArguments(argsBefore).length;\n\n // Check builtin macros\n const macroInfo = workspace.macros.getMacro(macroName);\n if (macroInfo && macroInfo.parameters && macroInfo.parameters.length > 0) {\n const paramLabels = macroInfo.parameters;\n return {\n signatures: [{\n label: `{${macroName} ${paramLabels.join(' ')}}`,\n documentation: macroInfo.description ?? undefined,\n parameters: paramLabels.map(p => ({ label: p })),\n }],\n activeSignature: 0,\n activeParameter,\n };\n }\n\n // Check widgets\n const widget = workspace.widgets.getWidget(macroName);\n if (widget && widget.params.length > 0) {\n const paramLabels = widget.params.map(p => `@${p}`);\n return {\n signatures: [{\n label: `{${macroName} ${paramLabels.join(', ')}}`,\n documentation: `Widget defined in: ${widget.uri}`,\n parameters: paramLabels.map(p => ({ label: p })),\n }],\n activeSignature: 0,\n activeParameter,\n };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const signaturePlugin: SpindlePlugin = {\n id: 'signature',\n capabilities: {\n signatureHelpProvider: {\n triggerCharacters: [' ', '\"', \"'\"],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onSignatureHelp((params): SignatureHelp | null => {\n const result = getSignatureHelp(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n\n const signatures: SignatureInformation[] = result.signatures.map(sig => ({\n label: sig.label,\n documentation: sig.documentation,\n parameters: sig.parameters.map(p => ({ label: p.label }) as ParameterInformation),\n }));\n\n return {\n signatures,\n activeSignature: result.activeSignature,\n activeParameter: result.activeParameter,\n };\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core definition function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DefinitionResult {\n uri: string;\n range: Range;\n}\n\n/**\n * Compute go-to-definition for the symbol at the given position.\n *\n * Supports:\n * - Passage name in [[link]] -> jump to passage header\n * - Passage name in macro args (goto, include, link, button) -> jump to passage\n * - Widget name in {widgetName} -> jump to widget definition\n */\nexport function getDefinition(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Passage ref in [[link]] ---\n const linkResult = getPassageLinkDefinition(text, position, workspace);\n if (linkResult) return linkResult;\n\n // --- Passage ref in macro args (goto, include, link, button) ---\n const macroPassageResult = getMacroPassageDefinition(line, position, workspace);\n if (macroPassageResult) return macroPassageResult;\n\n // --- Widget name -> definition ---\n const widgetResult = getWidgetDefinition(line, position, workspace);\n if (widgetResult) return widgetResult;\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getPassageLinkDefinition(\n text: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n const links = parseLinks(text);\n for (const link of links) {\n if (link.range.start.line === position.line &&\n position.character >= link.range.start.character &&\n position.character <= link.range.end.character) {\n const passage = workspace.passages.getPassage(link.name);\n if (passage) {\n return {\n uri: passage.uri,\n range: passage.headerEnd,\n };\n }\n }\n }\n return null;\n}\n\nfunction getMacroPassageDefinition(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n // Match {goto \"passage\"}, {include \"passage\"}, {link \"text\" \"passage\"}, {button \"text\" \"passage\"}\n const patterns = [\n /\\{(?:goto|include)\\s+\"([^\"]+)\"\\s*\\}/gi,\n /\\{(?:link|button)\\s+\"[^\"]*\"\\s+\"([^\"]+)\"\\s*\\}/gi,\n ];\n\n for (const pattern of patterns) {\n pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(line)) !== null) {\n const passageName = match[1];\n const nameStart = match.index + match[0].indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n const passage = workspace.passages.getPassage(passageName);\n if (passage) {\n return {\n uri: passage.uri,\n range: passage.headerEnd,\n };\n }\n }\n }\n }\n return null;\n}\n\nfunction getWidgetDefinition(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n // Match {widgetName ...} invocations\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1; // skip '{'\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n // Only if it's not a known macro\n if (workspace.macros.getMacro(name)) continue;\n\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return {\n uri: widget.uri,\n range: widget.range,\n };\n }\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const definitionPlugin: SpindlePlugin = {\n id: 'definition',\n capabilities: {\n definitionProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDefinition((params) => {\n const result = getDefinition(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n uri: result.uri,\n range: toLspRange(result.range),\n };\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core references function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface ReferenceLocation {\n uri: string;\n range: Range;\n}\n\n/**\n * Find all references to the symbol at the given position.\n *\n * Supports:\n * - Passage header -> all [[links]] + macro refs to that passage\n * - Variable -> all usages across workspace\n * - Widget -> all invocations\n */\nexport function findReferences(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return [];\n const line = lines[position.line];\n\n // --- Passage header ---\n const passageHeaderRegex = /^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/;\n if (line.trimStart().startsWith('::')) {\n const headerMatch = passageHeaderRegex.exec(line);\n if (headerMatch) {\n const passageName = headerMatch[1].trim();\n const nameStart = line.indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return findPassageReferences(passageName, workspace, includeDeclaration);\n }\n }\n }\n\n // --- $variable ---\n {\n const varRegex = /\\$([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = varRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const varName = match[1];\n return findVariableReferences(varName, workspace, includeDeclaration);\n }\n }\n }\n\n // --- Widget ---\n {\n const widgetRegex = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = widgetRegex.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1;\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n if (!workspace.macros.getMacro(name) && workspace.widgets.getWidget(name)) {\n return findWidgetReferences(name, workspace, includeDeclaration);\n }\n }\n }\n }\n\n // --- Passage name in link (also check passage names) ---\n {\n const allPassages = workspace.passages.getAllPassages();\n const passageNames = new Set(allPassages.map(p => p.name));\n // Try to extract a word at cursor and see if it's a passage name\n const wordRegex = /[A-Za-z_$][\\w$\\s]*/g;\n let match: RegExpExecArray | null;\n while ((match = wordRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const word = match[0].trim();\n if (passageNames.has(word)) {\n return findPassageReferences(word, workspace, includeDeclaration);\n }\n }\n }\n }\n\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Reference finders\n// ---------------------------------------------------------------------------\n\n/**\n * Find all references to a passage across the workspace.\n */\nexport function findPassageReferences(\n passageName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration (passage header)\n if (includeDeclaration) {\n const passage = workspace.passages.getPassage(passageName);\n if (passage) {\n locations.push({\n uri: passage.uri,\n range: passage.headerEnd,\n });\n }\n }\n\n // Scan all documents for passage references\n const gotoRegex = /\\{(?:goto|include)\\s+\"([^\"]+)\"\\s*\\}/gi;\n const linkMacroRegex = /\\{(?:link|button)\\s+\"[^\"]*\"\\s+\"([^\"]+)\"\\s*\\}/gi;\n\n for (const docUri of workspace.documents.getUris()) {\n const docText = workspace.documents.getText(docUri);\n if (!docText) continue;\n\n // Find [[passage]] links\n const links = parseLinks(docText);\n for (const link of links) {\n if (link.name === passageName) {\n locations.push({ uri: docUri, range: link.range });\n }\n }\n\n // Find {goto \"passage\"} and {include \"passage\"}\n const lines = docText.split('\\n');\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n for (const regex of [gotoRegex, linkMacroRegex]) {\n regex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(line)) !== null) {\n if (match[1] === passageName) {\n const nameStart = match.index + match[0].indexOf(match[1]);\n locations.push({\n uri: docUri,\n range: {\n start: { line: lineNum, character: nameStart },\n end: { line: lineNum, character: nameStart + match[1].length },\n },\n });\n }\n }\n }\n }\n }\n\n return locations;\n}\n\n/**\n * Find all references to a variable across the workspace.\n */\nexport function findVariableReferences(\n varName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration from StoryVariables\n if (includeDeclaration) {\n const decl = workspace.variables.getDeclared().get(varName);\n if (decl?.declarationRange && decl.declarationUri) {\n locations.push({\n uri: decl.declarationUri,\n range: decl.declarationRange,\n });\n }\n }\n\n // Get all usages from the variable tracker\n const usages = workspace.variables.getUsages(varName);\n for (const u of usages) {\n locations.push({ uri: u.uri, range: u.range });\n }\n\n return locations;\n}\n\n/**\n * Find all references to a widget across the workspace.\n */\nexport function findWidgetReferences(\n widgetName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration\n if (includeDeclaration) {\n const widget = workspace.widgets.getWidget(widgetName);\n if (widget) {\n locations.push({ uri: widget.uri, range: widget.range });\n }\n }\n\n // Scan all documents for {widgetName ...} invocations\n const widgetInvocationRegex = /\\{([A-Za-z_$][\\w$]*)\\b/g;\n\n for (const docUri of workspace.documents.getUris()) {\n const docText = workspace.documents.getText(docUri);\n if (!docText) continue;\n\n const lines = docText.split('\\n');\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // Skip widget definition lines\n if (/\\{widget\\s+\"/i.test(line)) continue;\n\n widgetInvocationRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = widgetInvocationRegex.exec(line)) !== null) {\n if (match[1] === widgetName) {\n const nameStart = match.index + 1; // skip '{'\n locations.push({\n uri: docUri,\n range: {\n start: { line: lineNum, character: nameStart },\n end: { line: lineNum, character: nameStart + widgetName.length },\n },\n });\n }\n }\n }\n }\n\n return locations;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const referencesPlugin: SpindlePlugin = {\n id: 'references',\n capabilities: {\n referencesProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onReferences((params) => {\n const refs = findReferences(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n params.context.includeDeclaration,\n );\n return refs.map(r => ({\n uri: r.uri,\n range: toLspRange(r.range),\n }));\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport {\n findPassageReferences,\n findVariableReferences,\n findWidgetReferences,\n} from './references.js';\n\n// ---------------------------------------------------------------------------\n// Core rename functions (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface PrepareRenameResult {\n range: Range;\n placeholder: string;\n}\n\nexport interface RenameEdit {\n range: Range;\n newText: string;\n}\n\n/**\n * Determine if the symbol at the cursor is renameable, and return its range + placeholder.\n */\nexport function prepareRename(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): PrepareRenameResult | null {\n const symbol = resolveSymbolAtCursor(uri, position, workspace);\n if (!symbol) return null;\n return { range: symbol.range, placeholder: symbol.name };\n}\n\n/**\n * Compute all text edits for a rename operation.\n * Returns a map of URI -> list of edits.\n */\nexport function computeRename(\n uri: string,\n position: Position,\n newName: string,\n workspace: WorkspaceModel,\n): Map<string, RenameEdit[]> {\n const symbol = resolveSymbolAtCursor(uri, position, workspace);\n if (!symbol) return new Map();\n\n const edits = new Map<string, RenameEdit[]>();\n\n function addEdit(editUri: string, range: Range, text: string) {\n const existing = edits.get(editUri) ?? [];\n existing.push({ range, newText: text });\n edits.set(editUri, existing);\n }\n\n switch (symbol.kind) {\n case 'passage': {\n const refs = findPassageReferences(symbol.name, workspace, true);\n for (const ref of refs) {\n addEdit(ref.uri, ref.range, newName);\n }\n break;\n }\n\n case 'variable': {\n const bareName = newName.startsWith('$') ? newName.slice(1) : newName;\n const refs = findVariableReferences(symbol.name, workspace, true);\n for (const ref of refs) {\n addEdit(ref.uri, ref.range, bareName);\n }\n break;\n }\n\n case 'widget': {\n // Rename invocations\n const invocationRefs = findWidgetReferences(symbol.name, workspace, false);\n for (const ref of invocationRefs) {\n addEdit(ref.uri, ref.range, newName);\n }\n\n // Rename definition\n const widget = workspace.widgets.getWidget(symbol.name);\n if (widget) {\n // The widget definition is {widget \"name\" ...}\n // We need to find and replace just the name inside the quotes\n const docText = workspace.documents.getText(widget.uri);\n if (docText) {\n const lines = docText.split('\\n');\n const defLine = lines[widget.range.start.line];\n if (defLine) {\n const defSlice = defLine.slice(widget.range.start.character);\n const nameMatch = /\\{widget\\s+\"([^\"]+)\"/.exec(defSlice);\n if (nameMatch) {\n const nameOffsetInSlice = defSlice.indexOf(nameMatch[1]);\n const nameStart = widget.range.start.character + nameOffsetInSlice;\n addEdit(widget.uri, {\n start: { line: widget.range.start.line, character: nameStart },\n end: { line: widget.range.start.line, character: nameStart + symbol.name.length },\n }, newName);\n }\n }\n }\n }\n break;\n }\n }\n\n return edits;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol resolution\n// ---------------------------------------------------------------------------\n\ninterface SymbolInfo {\n kind: 'passage' | 'variable' | 'widget';\n name: string;\n range: Range;\n}\n\nfunction resolveSymbolAtCursor(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): SymbolInfo | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Passage header ---\n const passageHeaderRegex = /^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/;\n if (line.trimStart().startsWith('::')) {\n const headerMatch = passageHeaderRegex.exec(line);\n if (headerMatch) {\n const passageName = headerMatch[1].trim();\n const nameStart = line.indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return {\n kind: 'passage',\n name: passageName,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n\n // --- $variable ---\n {\n const varRegex = /\\$([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = varRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n kind: 'variable',\n name: match[1],\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // --- Widget definition: {widget \"name\" ...} ---\n {\n const widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"/gi;\n let match: RegExpExecArray | null;\n while ((match = widgetDefRegex.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + match[0].indexOf(name);\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return {\n kind: 'widget',\n name,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n\n // --- Widget invocation: {widgetName ...} ---\n {\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1;\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n if (!workspace.macros.getMacro(name) && workspace.widgets.getWidget(name)) {\n return {\n kind: 'widget',\n name,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const renamePlugin: SpindlePlugin = {\n id: 'rename',\n capabilities: {\n renameProvider: {\n prepareProvider: true,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onPrepareRename((params) => {\n const result = prepareRename(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n range: toLspRange(result.range),\n placeholder: result.placeholder,\n };\n });\n\n ctx.connection.onRenameRequest((params) => {\n const editsMap = computeRename(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n params.newName,\n ctx.workspace,\n );\n\n const changes: Record<string, import('vscode-languageserver').TextEdit[]> = {};\n for (const [editUri, edits] of editsMap) {\n changes[editUri] = edits.map(e => ({\n range: toLspRange(e.range),\n newText: e.newText,\n }));\n }\n\n return { changes };\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport {\n findPassageReferences,\n findVariableReferences,\n findWidgetReferences,\n} from './references.js';\n\n// ---------------------------------------------------------------------------\n// Core code lens function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface CodeLensItem {\n range: Range;\n command: {\n title: string;\n };\n}\n\n/**\n * Compute code lenses for a document.\n *\n * Shows:\n * - Above passage headers: \"N references\"\n * - Above widget definitions: \"N usages\"\n * - Above StoryVariables declarations: \"N usages\"\n */\nexport function computeCodeLenses(uri: string, workspace: WorkspaceModel): CodeLensItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n const lenses: CodeLensItem[] = [];\n\n const storyVarsPassage = workspace.passages.getStoryVariables();\n const isStoryVarsFile = storyVarsPassage && storyVarsPassage.uri === uri;\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // --- Passage headers ---\n const passageMatch = line.match(/^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/);\n if (passageMatch) {\n const passageName = passageMatch[1].trim();\n if (passageName === 'StoryData') continue;\n\n const refs = findPassageReferences(passageName, workspace, true);\n const refCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${refCount} reference${refCount !== 1 ? 's' : ''}`,\n },\n });\n continue;\n }\n\n // --- Widget definitions ---\n const widgetMatch = line.match(/\\{widget\\s+\"([^\"]+)\"/);\n if (widgetMatch) {\n const widgetName = widgetMatch[1];\n const refs = findWidgetReferences(widgetName, workspace, true);\n const usageCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${usageCount} usage${usageCount !== 1 ? 's' : ''}`,\n },\n });\n }\n\n // --- StoryVariables declarations ---\n if (isStoryVarsFile) {\n const varDeclMatch = line.match(/^\\$([A-Za-z_$][\\w$]*)\\s*=/);\n if (varDeclMatch) {\n const varName = varDeclMatch[1];\n const refs = findVariableReferences(varName, workspace, true);\n const usageCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${usageCount} usage${usageCount !== 1 ? 's' : ''}`,\n },\n });\n }\n }\n }\n\n return lenses;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const codeLensPlugin: SpindlePlugin = {\n id: 'code-lens',\n capabilities: {\n codeLensProvider: {\n resolveProvider: false,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCodeLens((params) => {\n const lenses = computeCodeLenses(params.textDocument.uri, ctx.workspace);\n return lenses.map(l => ({\n range: toLspRange(l.range),\n command: {\n title: l.command.title,\n command: 'spindle.findReferences',\n },\n }));\n });\n },\n};\n", "import type { Range, Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Core inlay hints function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface InlayHintItem {\n position: Position;\n label: string;\n kind: 'type' | 'parameter';\n}\n\n/**\n * Compute inlay hints for a document within a range.\n *\n * Provides:\n * - Widget invocation args -> parameter name hints\n * - Variable type hints in StoryVariables\n */\nexport function computeInlayHints(\n uri: string,\n range: Range,\n workspace: WorkspaceModel,\n): InlayHintItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const hints: InlayHintItem[] = [];\n\n addWidgetParamHints(text, range, workspace, hints);\n addVariableTypeHints(uri, text, range, workspace, hints);\n\n return hints;\n}\n\n// ---------------------------------------------------------------------------\n// Widget parameter hints\n// ---------------------------------------------------------------------------\n\nfunction addWidgetParamHints(\n text: string,\n range: Range,\n workspace: WorkspaceModel,\n hints: InlayHintItem[],\n): void {\n const allWidgets = workspace.widgets.getAllWidgets();\n if (allWidgets.length === 0) return;\n\n const widgetMap = new Map(allWidgets.map(w => [w.name, w]));\n const macros = parseMacros(text);\n\n for (const macro of macros) {\n if (!macro.open) continue;\n // Check if macro is within the requested range\n if (macro.range.start.line < range.start.line || macro.range.start.line > range.end.line) continue;\n\n const widget = widgetMap.get(macro.name);\n if (!widget || widget.params.length === 0) continue;\n\n if (!macro.rawArgs || macro.rawArgs.trim() === '') continue;\n\n const args = lexArguments(macro.rawArgs);\n\n // Find the position of each arg in the original text line\n const lines = text.split('\\n');\n const macroLine = lines[macro.range.start.line];\n if (!macroLine) continue;\n\n const macroText = macroLine.substring(macro.range.start.character, macro.range.end.character);\n const nameEnd = macroText.indexOf(macro.name) + macro.name.length;\n const argsText = macroText.substring(nameEnd).replace(/^\\s+/, '').replace(/\\}$/, '');\n if (!argsText) continue;\n\n for (let i = 0; i < Math.min(args.length, widget.params.length); i++) {\n const argText = args[i].text;\n const idx = macroLine.indexOf(argText, macro.range.start.character + nameEnd);\n if (idx >= 0) {\n hints.push({\n position: { line: macro.range.start.line, character: idx },\n label: `@${widget.params[i]}:`,\n kind: 'parameter',\n });\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Variable type hints in StoryVariables\n// ---------------------------------------------------------------------------\n\nfunction addVariableTypeHints(\n uri: string,\n text: string,\n range: Range,\n workspace: WorkspaceModel,\n hints: InlayHintItem[],\n): void {\n const storyVarsPassage = workspace.passages.getStoryVariables();\n if (!storyVarsPassage) return;\n if (storyVarsPassage.uri !== uri) return;\n\n const lines = text.split('\\n');\n const startLine = Math.max(range.start.line, 0);\n const endLine = Math.min(range.end.line, lines.length - 1);\n\n for (let lineNum = startLine; lineNum <= endLine; lineNum++) {\n const line = lines[lineNum];\n const declMatch = line.match(/^\\$([A-Za-z_$][\\w$]*)\\s*=\\s*(.+)$/);\n if (!declMatch) continue;\n\n const valueStr = declMatch[2].trim();\n const inferredType = inferType(valueStr);\n if (!inferredType) continue;\n\n const eqIdx = line.indexOf('=');\n hints.push({\n position: { line: lineNum, character: eqIdx },\n label: `: ${inferredType}`,\n kind: 'type',\n });\n }\n}\n\nfunction inferType(value: string): string | null {\n if (/^\\d+(\\.\\d+)?$/.test(value)) return 'number';\n if (/^\"[^\"]*\"$/.test(value) || /^'[^']*'$/.test(value)) return 'string';\n if (/^\\[/.test(value)) return 'array';\n if (/^\\{/.test(value)) return 'object';\n if (value === 'true' || value === 'false') return 'boolean';\n if (value === 'null') return 'null';\n if (value === 'undefined') return 'undefined';\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const inlayHintsPlugin: SpindlePlugin = {\n id: 'inlay-hints',\n capabilities: {\n inlayHintProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.languages.inlayHint.on((params) => {\n const range: Range = {\n start: { line: params.range.start.line, character: params.range.start.character },\n end: { line: params.range.end.line, character: params.range.end.character },\n };\n\n const hints = computeInlayHints(params.textDocument.uri, range, ctx.workspace);\n\n return hints.map(h => ({\n position: { line: h.position.line, character: h.position.character },\n label: h.label,\n kind: h.kind === 'type' ? 1 : 2,\n paddingRight: h.kind === 'parameter',\n paddingLeft: h.kind === 'type',\n }));\n });\n },\n};\n", "import type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Token legend\n// ---------------------------------------------------------------------------\n\nexport const tokenTypesLegend: string[] = [\n 'function', 'variable', 'parameter', 'property', 'keyword',\n 'string', 'number', 'comment', 'namespace', 'type',\n 'macro', 'regexp',\n];\n\nexport const tokenModifiersLegend: string[] = [\n 'declaration', 'defaultLibrary', 'global', 'local', 'readonly',\n];\n\nconst tokenTypeIndex = new Map<string, number>(\n tokenTypesLegend.map((t, i) => [t, i]),\n);\nconst tokenModifierIndex = new Map<string, number>(\n tokenModifiersLegend.map((m, i) => [m, i]),\n);\n\nfunction encodeType(type: string): number {\n return tokenTypeIndex.get(type) ?? 0;\n}\n\nfunction encodeModifiers(modifiers: string[]): number {\n let bits = 0;\n for (const m of modifiers) {\n const idx = tokenModifierIndex.get(m);\n if (idx !== undefined) bits |= (1 << idx);\n }\n return bits;\n}\n\n// ---------------------------------------------------------------------------\n// Core semantic tokens function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/** A single absolute-positioned semantic token before delta-encoding. */\nexport interface AbsoluteToken {\n line: number;\n startChar: number;\n length: number;\n tokenType: number;\n tokenModifiers: number;\n}\n\n/**\n * Compute semantic tokens for a document.\n *\n * Tokens emitted:\n * - Macro names -> 'function' (with 'defaultLibrary' if known macro)\n * - Story variables ($var) -> 'variable' + 'global'\n * - Temp variables (_var) -> 'variable' + 'local'\n * - Local variables (@var) -> 'variable' + 'readonly'\n * - Sugar keywords -> 'keyword'\n * - Passage headers -> 'namespace'\n *\n * Returns absolute tokens (for testing). Use `encodeTokens` to delta-encode.\n */\nexport function computeSemanticTokensAbsolute(\n uri: string,\n workspace: WorkspaceModel,\n): AbsoluteToken[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n const tokens: AbsoluteToken[] = [];\n\n // Find header lines for skipping during content scanning\n const headerLines = new Set<number>();\n const passages = workspace.passages.getPassagesInDocument(uri);\n for (const passage of passages) {\n const headerLine = passage.headerEnd.start.line;\n headerLines.add(headerLine);\n\n // Emit passage header tokens\n const rawLine = lines[headerLine] ?? '';\n // :: token\n tokens.push({\n line: headerLine,\n startChar: 0,\n length: 2,\n tokenType: encodeType('namespace'),\n tokenModifiers: 0,\n });\n\n // passage name\n const nameMatch = rawLine.match(/^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/);\n if (nameMatch) {\n const name = nameMatch[1].trim();\n const nameStart = rawLine.indexOf(name);\n tokens.push({\n line: headerLine,\n startChar: nameStart,\n length: name.length,\n tokenType: encodeType('namespace'),\n tokenModifiers: encodeModifiers(['declaration']),\n });\n }\n }\n\n // Macro name tokens\n const macros = parseMacros(text);\n for (const macro of macros) {\n const macroLine = macro.range.start.line;\n const macroChar = macro.range.start.character;\n if (headerLines.has(macroLine)) continue;\n\n const isDefined = !!workspace.macros.getMacro(macro.name);\n\n let nameOffset = 1; // for '{'\n if (!macro.open) nameOffset += 1; // for '/'\n if (macro.cssPrefix) nameOffset += macro.cssPrefix.length + 1;\n\n tokens.push({\n line: macroLine,\n startChar: macroChar + nameOffset,\n length: macro.name.length,\n tokenType: encodeType('function'),\n tokenModifiers: encodeModifiers(isDefined ? ['defaultLibrary'] : []),\n });\n }\n\n // Variable and keyword tokens\n const storyVarRegex = /(?<!\\w)\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n const tempVarRegex = /(?<!\\w)_([A-Za-z_$][\\w$]*)/g;\n const localVarRegex = /(?<!\\w)@([A-Za-z_$][\\w$]*)/g;\n const sugarKeywordRegex = /\\b(to|is|isnot|eq|neq|gt|gte|lt|lte|and|or|not|def|ndef)\\b/g;\n\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\n if (headerLines.has(lineIndex)) continue;\n const line = lines[lineIndex];\n\n // Story vars ($var)\n storyVarRegex.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = storyVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['global']),\n });\n }\n\n // Temp vars (_var)\n tempVarRegex.lastIndex = 0;\n while ((m = tempVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['local']),\n });\n }\n\n // Local vars (@var)\n localVarRegex.lastIndex = 0;\n while ((m = localVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['readonly']),\n });\n }\n\n // Sugar keywords\n sugarKeywordRegex.lastIndex = 0;\n while ((m = sugarKeywordRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('keyword'),\n tokenModifiers: 0,\n });\n }\n }\n\n // Sort by line, then by start character\n tokens.sort((a, b) => a.line - b.line || a.startChar - b.startChar);\n\n return tokens;\n}\n\n/**\n * Delta-encode absolute tokens into the LSP wire format.\n *\n * Each token becomes 5 integers: deltaLine, deltaStartChar, length, tokenType, tokenModifiers.\n */\nexport function encodeTokens(absoluteTokens: AbsoluteToken[]): number[] {\n const data: number[] = [];\n let prevLine = 0;\n let prevChar = 0;\n\n for (const token of absoluteTokens) {\n const deltaLine = token.line - prevLine;\n const deltaStart = deltaLine === 0 ? token.startChar - prevChar : token.startChar;\n\n data.push(deltaLine, deltaStart, token.length, token.tokenType, token.tokenModifiers);\n\n prevLine = token.line;\n prevChar = token.startChar;\n }\n\n return data;\n}\n\n/**\n * Compute delta-encoded semantic tokens for a document.\n */\nexport function computeSemanticTokens(uri: string, workspace: WorkspaceModel): number[] {\n const absoluteTokens = computeSemanticTokensAbsolute(uri, workspace);\n return encodeTokens(absoluteTokens);\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const semanticTokensPlugin: SpindlePlugin = {\n id: 'semantic-tokens',\n capabilities: {\n semanticTokensProvider: {\n full: true,\n legend: {\n tokenTypes: tokenTypesLegend,\n tokenModifiers: tokenModifiersLegend,\n },\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.languages.semanticTokens.on((params) => {\n const data = computeSemanticTokens(params.textDocument.uri, ctx.workspace);\n return { data };\n });\n },\n};\n", "import type { Diagnostic, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { DiagnosticCode } from '../core/diagnostic-codes.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CodeAction {\n title: string;\n kind: string;\n diagnosticCodes: string[];\n edits: Array<{ uri: string; range: Range; newText: string }>;\n}\n\n// ---------------------------------------------------------------------------\n// Core code actions function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute quick-fix code actions for the given diagnostics.\n *\n * Supported fixes:\n * - SP100 (undefined macro) -> \"Add 'macroName' to spindle.config.yaml\"\n * - SP200 (undeclared variable) -> \"Declare '$varName' in StoryVariables\"\n * - SP202 (no StoryVariables) -> \"Create StoryVariables passage\"\n */\nexport function computeCodeActions(\n uri: string,\n diagnostics: Diagnostic[],\n workspace: WorkspaceModel,\n): CodeAction[] {\n const actions: CodeAction[] = [];\n\n for (const diag of diagnostics) {\n switch (diag.code) {\n case DiagnosticCode.UndefinedMacro: {\n const action = fixUndefinedMacro(diag);\n if (action) actions.push(action);\n break;\n }\n case DiagnosticCode.UndeclaredVariable: {\n const action = fixUndeclaredVariable(diag, workspace);\n if (action) actions.push(action);\n break;\n }\n case DiagnosticCode.NoStoryVariables: {\n const action = fixNoStoryVariables(uri, workspace);\n if (action) actions.push(action);\n break;\n }\n // No quick fix for other diagnostic codes\n }\n }\n\n return actions;\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP100 \u2014 Add macro to spindle.config.yaml\n// ---------------------------------------------------------------------------\n\nfunction fixUndefinedMacro(diag: Diagnostic): CodeAction | null {\n // Extract macro name from message: \"Unrecognized macro: {macroName}\"\n const match = diag.message.match(/\\{(\\w[\\w-]*)\\}/);\n if (!match) return null;\n\n const macroName = match[1];\n const configUri = 'file:///spindle.config.yaml';\n\n // Generate YAML snippet to append\n const yamlSnippet = `\\n ${macroName}:\\n description: \"\"\\n`;\n\n return {\n title: `Add '${macroName}' to spindle.config.yaml`,\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.UndefinedMacro],\n edits: [{\n uri: configUri,\n range: {\n start: { line: Number.MAX_SAFE_INTEGER, character: 0 },\n end: { line: Number.MAX_SAFE_INTEGER, character: 0 },\n },\n newText: yamlSnippet,\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP200 \u2014 Declare variable in StoryVariables\n// ---------------------------------------------------------------------------\n\nfunction fixUndeclaredVariable(\n diag: Diagnostic,\n workspace: WorkspaceModel,\n): CodeAction | null {\n // Extract variable name from message: \"Variable '$varName' is not declared in StoryVariables\"\n const match = diag.message.match(/'\\$(\\w+)'/);\n if (!match) return null;\n\n const varName = match[1];\n\n const storyVars = workspace.passages.getStoryVariables();\n if (!storyVars) return null;\n\n const storyVarsUri = storyVars.uri;\n const text = workspace.documents.getText(storyVarsUri);\n if (text === undefined) return null;\n\n // Find the end of the StoryVariables passage content\n const lines = text.split('\\n');\n const contentStart = storyVars.headerEnd.end.line + 1;\n let contentEnd = lines.length;\n for (let i = contentStart; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEnd = i;\n break;\n }\n }\n\n // Insert at the end of StoryVariables content\n const insertLine = contentEnd;\n\n return {\n title: `Declare '$${varName}' in StoryVariables`,\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.UndeclaredVariable],\n edits: [{\n uri: storyVarsUri,\n range: {\n start: { line: insertLine, character: 0 },\n end: { line: insertLine, character: 0 },\n },\n newText: `$${varName} = null\\n`,\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP202 \u2014 Create StoryVariables passage\n// ---------------------------------------------------------------------------\n\nfunction fixNoStoryVariables(\n uri: string,\n workspace: WorkspaceModel,\n): CodeAction | null {\n // Find the first document in the workspace to append the passage\n const uris = workspace.documents.getUris();\n const targetUri = uris.length > 0 ? uris[0] : uri;\n\n const text = workspace.documents.getText(targetUri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n const lastLine = lines.length;\n\n return {\n title: 'Create StoryVariables passage',\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.NoStoryVariables],\n edits: [{\n uri: targetUri,\n range: {\n start: { line: lastLine, character: 0 },\n end: { line: lastLine, character: 0 },\n },\n newText: '\\n:: StoryVariables\\n',\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const codeActionsPlugin: SpindlePlugin = {\n id: 'code-actions',\n capabilities: {\n codeActionProvider: {\n codeActionKinds: ['quickfix'],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCodeAction((params) => {\n // Convert LSP diagnostics back to our Diagnostic type\n const diagnostics: Diagnostic[] = params.context.diagnostics\n .filter(d => d.source === 'spindle')\n .map(d => ({\n range: {\n start: { line: d.range.start.line, character: d.range.start.character },\n end: { line: d.range.end.line, character: d.range.end.character },\n },\n message: d.message,\n severity: d.severity === 1 ? 'error' as const\n : d.severity === 2 ? 'warning' as const\n : d.severity === 3 ? 'info' as const\n : 'hint' as const,\n code: String(d.code ?? ''),\n source: d.source ?? 'spindle',\n }));\n\n const actions = computeCodeActions(\n params.textDocument.uri,\n diagnostics,\n ctx.workspace,\n );\n\n return actions.map(a => ({\n title: a.title,\n kind: a.kind,\n diagnostics: params.context.diagnostics.filter(d =>\n a.diagnosticCodes.includes(String(d.code)),\n ),\n edit: {\n changes: Object.fromEntries(\n a.edits.map(e => [\n e.uri,\n [{ range: toLspRange(e.range), newText: e.newText }],\n ]),\n ),\n },\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { SymbolKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core document symbol function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DocSymbol {\n name: string;\n kind: SymbolKind;\n range: Range;\n selectionRange: Range;\n children?: DocSymbol[];\n}\n\n/**\n * Compute document symbols for the outline view and breadcrumbs.\n *\n * Returns:\n * - Passages as Namespace symbols (full passage range)\n * - Widget definitions inside [widget] passages as nested Function symbols\n * - Variable declarations in StoryVariables as nested Variable symbols\n */\nexport function computeDocumentSymbols(uri: string, workspace: WorkspaceModel): DocSymbol[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const storyVarsPassage = workspace.passages.getStoryVariables();\n const lines = text.split('\\n');\n const symbols: DocSymbol[] = [];\n\n for (const passage of passages) {\n const headerLine = passage.range.start.line;\n const selectionRange: Range = {\n start: { line: headerLine, character: 0 },\n end: { line: headerLine, character: lines[headerLine]?.length ?? 0 },\n };\n\n const passageSymbol: DocSymbol = {\n name: passage.name,\n kind: SymbolKind.Namespace,\n range: passage.range,\n selectionRange,\n children: [],\n };\n\n // Widget definitions inside [widget] passages\n if (passage.tags?.includes('widget')) {\n const contentStart = passage.range.start.line + 1;\n const contentEnd = passage.range.end.line + 1;\n const widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"[^}]*\\}/gi;\n\n for (let i = contentStart; i < contentEnd && i < lines.length; i++) {\n widgetDefRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = widgetDefRegex.exec(lines[i])) !== null) {\n const charStart = match.index;\n const charEnd = charStart + match[0].length;\n passageSymbol.children!.push({\n name: match[1],\n kind: SymbolKind.Function,\n range: {\n start: { line: i, character: charStart },\n end: { line: i, character: charEnd },\n },\n selectionRange: {\n start: { line: i, character: charStart },\n end: { line: i, character: charEnd },\n },\n });\n }\n }\n }\n\n // Variable declarations in StoryVariables\n if (storyVarsPassage && storyVarsPassage.uri === uri && passage.name === 'StoryVariables') {\n const contentStart = passage.range.start.line + 1;\n const contentEnd = passage.range.end.line + 1;\n\n for (let i = contentStart; i < contentEnd && i < lines.length; i++) {\n const varMatch = lines[i].match(/^\\$([A-Za-z_$][\\w$]*)\\s*=/);\n if (varMatch) {\n const charEnd = varMatch[0].length;\n passageSymbol.children!.push({\n name: '$' + varMatch[1],\n kind: SymbolKind.Variable,\n range: {\n start: { line: i, character: 0 },\n end: { line: i, character: lines[i].length },\n },\n selectionRange: {\n start: { line: i, character: 0 },\n end: { line: i, character: charEnd },\n },\n });\n }\n }\n }\n\n symbols.push(passageSymbol);\n }\n\n return symbols;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nfunction toLspDocumentSymbol(sym: DocSymbol): import('vscode-languageserver').DocumentSymbol {\n return {\n name: sym.name,\n kind: sym.kind,\n range: toLspRange(sym.range),\n selectionRange: toLspRange(sym.selectionRange),\n children: sym.children?.map(toLspDocumentSymbol),\n };\n}\n\nexport const documentSymbolPlugin: SpindlePlugin = {\n id: 'document-symbol',\n capabilities: {\n documentSymbolProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentSymbol((params) => {\n const symbols = computeDocumentSymbols(params.textDocument.uri, ctx.workspace);\n return symbols.map(toLspDocumentSymbol);\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { SymbolKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core workspace symbol function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface WorkspaceSymbolItem {\n name: string;\n kind: SymbolKind;\n uri: string;\n range: Range;\n}\n\n/**\n * Search for symbols across the entire workspace.\n *\n * Returns:\n * - All passages as Namespace symbols\n * - All widgets as Function symbols\n * - All declared variables as Variable symbols\n *\n * Results are filtered by the query string (case-insensitive substring match).\n */\nexport function searchWorkspaceSymbols(query: string, workspace: WorkspaceModel): WorkspaceSymbolItem[] {\n const lowerQuery = query.toLowerCase();\n const results: WorkspaceSymbolItem[] = [];\n\n // Passages\n for (const passage of workspace.passages.getAllPassages()) {\n if (lowerQuery && !passage.name.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: passage.name,\n kind: SymbolKind.Namespace,\n uri: passage.uri,\n range: passage.range,\n });\n }\n\n // Widgets\n for (const widget of workspace.widgets.getAllWidgets()) {\n if (lowerQuery && !widget.name.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: widget.name,\n kind: SymbolKind.Function,\n uri: widget.uri,\n range: widget.range,\n });\n }\n\n // Declared variables\n for (const [name, decl] of workspace.variables.getDeclared()) {\n const displayName = '$' + name;\n if (lowerQuery && !displayName.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: displayName,\n kind: SymbolKind.Variable,\n uri: decl.declarationUri ?? '',\n range: decl.declarationRange ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },\n });\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const workspaceSymbolPlugin: SpindlePlugin = {\n id: 'workspace-symbol',\n capabilities: {\n workspaceSymbolProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onWorkspaceSymbol((params) => {\n const symbols = searchWorkspaceSymbols(params.query, ctx.workspace);\n return symbols.map(s => ({\n name: s.name,\n kind: s.kind,\n location: {\n uri: s.uri,\n range: toLspRange(s.range),\n },\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\nimport { FoldingRangeKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core folding range function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface FoldingRangeItem {\n startLine: number;\n endLine: number;\n kind?: string;\n}\n\n/**\n * Compute folding ranges for a document.\n *\n * Returns foldable regions for:\n * - Passages: each passage header to the end of the passage (FoldingRangeKind.Region)\n * - Block macros: matched {if}...{/if}, {for}...{/for}, etc.\n */\nexport function computeFoldingRanges(uri: string, workspace: WorkspaceModel): FoldingRangeItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const ranges: FoldingRangeItem[] = [];\n\n // Passage folding ranges\n const passages = workspace.passages.getPassagesInDocument(uri);\n for (const passage of passages) {\n const startLine = passage.range.start.line;\n const endLine = passage.range.end.line;\n if (endLine > startLine) {\n ranges.push({\n startLine,\n endLine,\n kind: 'region',\n });\n }\n }\n\n // Block macro folding ranges\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n for (const macro of macros) {\n if (macro.open && macro.pair !== -1) {\n const closingMacro = macros[macro.pair];\n const startLine = macro.range.start.line;\n const endLine = closingMacro.range.start.line;\n if (endLine > startLine) {\n ranges.push({\n startLine,\n endLine,\n });\n }\n }\n }\n\n return ranges;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const foldingRangePlugin: SpindlePlugin = {\n id: 'folding-range',\n capabilities: {\n foldingRangeProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onFoldingRanges((params) => {\n const ranges = computeFoldingRanges(params.textDocument.uri, ctx.workspace);\n return ranges.map(r => ({\n startLine: r.startLine,\n endLine: r.endLine,\n kind: r.kind === 'region' ? FoldingRangeKind.Region : undefined,\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core document link function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DocumentLinkItem {\n range: Range;\n target: string | undefined;\n}\n\n/**\n * Compute document links for [[passage]] references.\n *\n * For each [[Target]] or [[Display|Target]] link:\n * - Returns a DocumentLink with the range covering the full link syntax\n * - Sets `target` to the URI of the file containing the target passage,\n * with a fragment pointing to the line number\n *\n * Links to unknown passages get `target: undefined`.\n */\nexport function computeDocumentLinks(uri: string, workspace: WorkspaceModel): DocumentLinkItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const links: DocumentLinkItem[] = [];\n\n // Parse links from each passage's content\n for (const passage of passages) {\n const contentStartLine = passage.range.start.line + 1;\n const contentEndLine = passage.range.end.line + 1;\n const lines = text.split('\\n');\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n const content = contentLines.join('\\n');\n\n const passageLinks = parseLinks(content, contentStartLine);\n\n for (const ref of passageLinks) {\n const targetPassage = workspace.passages.getPassage(ref.name);\n let target: string | undefined;\n if (targetPassage) {\n target = `${targetPassage.uri}#L${targetPassage.range.start.line + 1}`;\n }\n\n links.push({\n range: ref.range,\n target,\n });\n }\n }\n\n return links;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const documentLinkPlugin: SpindlePlugin = {\n id: 'document-link',\n capabilities: {\n documentLinkProvider: {\n resolveProvider: false,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentLinks((params) => {\n const links = computeDocumentLinks(params.textDocument.uri, ctx.workspace);\n return links.map(l => ({\n range: toLspRange(l.range),\n target: l.target,\n }));\n });\n },\n};\n", "import type { SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { diagnosticsPlugin } from './diagnostics.js';\nimport { completionsPlugin } from './completions.js';\nimport { hoverPlugin } from './hover.js';\nimport { signaturePlugin } from './signature.js';\nimport { definitionPlugin } from './definition.js';\nimport { referencesPlugin } from './references.js';\nimport { renamePlugin } from './rename.js';\nimport { codeLensPlugin } from './code-lens.js';\nimport { inlayHintsPlugin } from './inlay-hints.js';\nimport { semanticTokensPlugin } from './semantic-tokens.js';\nimport { codeActionsPlugin } from './code-actions.js';\nimport { formatPlugin } from './format.js';\nimport { documentSymbolPlugin } from './document-symbol.js';\nimport { workspaceSymbolPlugin } from './workspace-symbol.js';\nimport { foldingRangePlugin } from './folding-range.js';\nimport { documentLinkPlugin } from './document-link.js';\n\n/**\n * Registry of all feature plugins.\n */\nexport const allPlugins: SpindlePlugin[] = [\n diagnosticsPlugin,\n completionsPlugin,\n hoverPlugin,\n signaturePlugin,\n definitionPlugin,\n referencesPlugin,\n renamePlugin,\n codeLensPlugin,\n inlayHintsPlugin,\n semanticTokensPlugin,\n codeActionsPlugin,\n formatPlugin,\n documentSymbolPlugin,\n workspaceSymbolPlugin,\n foldingRangePlugin,\n documentLinkPlugin,\n];\n", "import {\n createConnection,\n ProposedFeatures,\n DidChangeWatchedFilesNotification,\n FileChangeType,\n} from 'vscode-languageserver/node.js';\nimport { TextDocument } from 'vscode-languageserver-textdocument';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { glob } from 'glob';\n\nimport { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport { loadPlugins } from '../core/plugin/plugin-loader.js';\nimport { buildCapabilities } from './capabilities.js';\nimport { allPlugins } from '../plugins/index.js';\nimport type { SpindleConfig, SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { loadConfigFromDisk } from '../core/workspace/config-loader.js';\n\n/**\n * Convert a file:// URI to a filesystem path.\n * Returns the original string if it is not a file URI.\n */\nfunction uriToFsPath(uri: string): string {\n try {\n return fileURLToPath(uri);\n } catch {\n return uri;\n }\n}\n\n/**\n * Convert a filesystem path to a file:// URI string.\n */\nfunction fsPathToUri(fsPath: string): string {\n return pathToFileURL(fsPath).toString();\n}\n\n/**\n * Start the Spindle LSP server.\n *\n * Supports `--stdio` (default) and `--socket=<port>` transport modes.\n */\nexport function startServer(_args: string[]): void {\n const connection = createConnection(ProposedFeatures.all);\n const documents = new Map<string, TextDocument>();\n let workspace: WorkspaceModel;\n let activePlugins: SpindlePlugin[] = [];\n let workspaceRoot: string | undefined;\n\n connection.onInitialize((params) => {\n const initOptions = (params.initializationOptions ?? {}) as Partial<SpindleConfig>;\n\n // Determine workspace root from LSP params\n workspaceRoot =\n initOptions.workspaceRoot ??\n (params.workspaceFolders?.[0]?.uri\n ? uriToFsPath(params.workspaceFolders[0].uri)\n : undefined);\n\n // Load project config from disk if we have a workspace root\n const projectConfig = workspaceRoot\n ? loadConfigFromDisk(workspaceRoot)\n : { macros: {} };\n\n const config: SpindleConfig = {\n disabledPlugins: initOptions.disabledPlugins,\n diagnostics: initOptions.diagnostics,\n workspaceRoot,\n };\n\n // Create workspace model\n workspace = new WorkspaceModel();\n\n // Load and filter plugins\n activePlugins = loadPlugins(allPlugins, config);\n\n // Initialize each plugin with context\n for (const plugin of activePlugins) {\n plugin.initialize({ connection, workspace, config });\n }\n\n // Load user-defined macros from project config\n if (Object.keys(projectConfig.macros).length > 0) {\n workspace.macros.loadSupplements(projectConfig.macros);\n }\n\n return {\n capabilities: buildCapabilities(activePlugins),\n };\n });\n\n connection.onInitialized(async () => {\n // Register for file watching\n connection.client.register(DidChangeWatchedFilesNotification.type, {\n watchers: [\n { globPattern: '**/*.tw' },\n { globPattern: '**/*.twee' },\n { globPattern: '**/*.js' },\n { globPattern: '**/*.ts' },\n { globPattern: '**/spindle.config.*' },\n ],\n });\n\n // Initial workspace scan\n if (workspace) {\n const fileContents = await scanWorkspaceFiles(workspaceRoot);\n workspace.initialize(fileContents);\n }\n });\n\n // --- Document synchronization ---\n\n connection.onDidOpenTextDocument(({ textDocument }) => {\n const doc = TextDocument.create(\n textDocument.uri,\n textDocument.languageId,\n textDocument.version,\n textDocument.text,\n );\n documents.set(textDocument.uri, doc);\n if (workspace) {\n workspace.documents.open(textDocument.uri, textDocument.text);\n }\n });\n\n connection.onDidChangeTextDocument(({ textDocument, contentChanges }) => {\n const existing = documents.get(textDocument.uri);\n if (existing) {\n const updated = TextDocument.update(\n existing,\n contentChanges,\n textDocument.version,\n );\n documents.set(textDocument.uri, updated);\n if (workspace) {\n workspace.documents.update(textDocument.uri, updated.getText());\n }\n }\n });\n\n connection.onDidCloseTextDocument(({ textDocument }) => {\n documents.delete(textDocument.uri);\n if (workspace) {\n workspace.documents.close(textDocument.uri);\n }\n });\n\n // --- File watcher events ---\n\n connection.onDidChangeWatchedFiles(({ changes }) => {\n if (!workspace) return;\n\n for (const change of changes) {\n if (change.type === FileChangeType.Deleted) {\n workspace.documents.close(change.uri);\n documents.delete(change.uri);\n } else {\n // Created or Changed \u2014 re-read from disk\n try {\n const fsPath = uriToFsPath(change.uri);\n const text = readFileSync(fsPath, 'utf-8');\n if (workspace.documents.has(change.uri)) {\n workspace.documents.update(change.uri, text);\n } else {\n workspace.documents.open(change.uri, text);\n }\n } catch {\n // File may have been deleted between event and read\n }\n }\n }\n });\n\n // --- Lifecycle ---\n\n connection.onShutdown(() => {\n for (const plugin of activePlugins) {\n plugin.dispose?.();\n }\n workspace?.dispose();\n });\n\n connection.listen();\n}\n\n/**\n * Scan workspace for .tw and .twee files and return their contents.\n */\nasync function scanWorkspaceFiles(\n root: string | undefined,\n): Promise<Map<string, string>> {\n const contents = new Map<string, string>();\n if (!root) return contents;\n\n try {\n const files = await glob('**/*.{tw,twee}', {\n cwd: root,\n absolute: true,\n nodir: true,\n });\n for (const filePath of files) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = fsPathToUri(filePath);\n contents.set(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Glob failure \u2014 return empty\n }\n\n return contents;\n}\n", "export {};\n\nconst args = process.argv.slice(2);\n\nif (args[0] === 'check') {\n const { runCheck } = await import('./cli/check.js');\n const exitCode = await runCheck(args.slice(1));\n process.exit(exitCode);\n} else if (args[0] === 'format') {\n const { runFormat } = await import('./cli/format.js');\n const exitCode = await runFormat(args.slice(1));\n process.exit(exitCode);\n} else {\n // Default: start LSP server\n const { startServer } = await import('./server/server.js');\n startServer(args);\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAF9B,IAaa;AAbb;AAAA;AAAA;AAaO,IAAM,gBAAN,cAA4B,aAAa;AAAA,MACtC,OAAO,oBAAI,IAA2B;AAAA;AAAA,MAG9C,KAAK,KAAa,MAAc,SAAwB;AACtD,aAAK,KAAK,IAAI,KAAK,EAAE,MAAM,SAAS,WAAW,EAAE,CAAC;AAClD,aAAK,KAAK,kBAAkB,GAAG;AAAA,MACjC;AAAA;AAAA,MAGA,OAAO,KAAa,MAAc,SAAwB;AACxD,cAAM,WAAW,KAAK,KAAK,IAAI,GAAG;AAClC,cAAM,aAAa,YAAY,WAAW,SAAS,UAAU,IAAI;AACjE,aAAK,KAAK,IAAI,KAAK,EAAE,MAAM,SAAS,WAAW,CAAC;AAChD,aAAK,KAAK,mBAAmB,GAAG;AAAA,MAClC;AAAA;AAAA,MAGA,MAAM,KAAmB;AACvB,aAAK,KAAK,OAAO,GAAG;AACpB,aAAK,KAAK,kBAAkB,GAAG;AAAA,MACjC;AAAA;AAAA,MAGA,QAAQ,KAAiC;AACvC,eAAO,KAAK,KAAK,IAAI,GAAG,GAAG;AAAA,MAC7B;AAAA;AAAA,MAGA,WAAW,KAAqB;AAC9B,eAAO,KAAK,KAAK,IAAI,GAAG,GAAG,WAAW;AAAA,MACxC;AAAA;AAAA,MAGA,UAAoB;AAClB,eAAO,MAAM,KAAK,KAAK,KAAK,KAAK,CAAC;AAAA,MACpC;AAAA;AAAA,MAGA,IAAI,KAAsB;AACxB,eAAO,KAAK,KAAK,IAAI,GAAG;AAAA,MAC1B;AAAA;AAAA,MAGA,aAAa,OAAuB;AAClC,mBAAW,YAAY,OAAO;AAC5B,cAAI;AACF,kBAAM,OAAO,aAAa,UAAU,OAAO;AAC3C,kBAAM,MAAM,cAAc,QAAQ,EAAE;AACpC,iBAAK,KAAK,KAAK,IAAI;AAAA,UACrB,QAAQ;AAAA,UAER;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACjCO,SAAS,mBAAmB,MAAc,YAAgD;AAE/F,QAAM,UAAU,KAAK,QAAQ,QAAQ,IAAI;AACzC,QAAM,QAAQ,mBAAmB,KAAK,OAAO;AAC7C,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,SAAS,MAAM,CAAC,KAAK;AAC3B,QAAM,UAAU,MAAM,CAAC,KAAK;AAC5B,QAAM,UAAU,MAAM,CAAC,KAAK;AAC5B,QAAM,UAAU,MAAM,CAAC,KAAK;AAG5B,QAAM,YAAY,OAAO;AACzB,QAAM,UAAU,YAAY,QAAQ;AACpC,QAAM,OAAO,KAAK,UAAU,WAAW,OAAO,EAAE,KAAK;AAErD,MAAI,CAAC,KAAM,QAAO;AAGlB,QAAM,cAAc,KAAK,QAAQ,QAAQ,IAAI;AAC7C,MAAI,aAAa,KAAK,WAAW,EAAG,QAAO;AAG3C,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,OAAiB,CAAC;AACtB,MAAI,SAAS;AACX,UAAM,QAAQ,QAAQ,UAAU,GAAG,QAAQ,SAAS,CAAC,EAAE,KAAK;AAE5D,QAAI,aAAa,KAAK,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAAG,QAAO;AAC3D,WAAO,QAAQ,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,EACvC;AAGA,MAAI;AACJ,QAAM,UAAU,QAAQ,KAAK;AAC7B,MAAI,SAAS;AACX,QAAI;AACF,aAAO,KAAK,MAAM,KAAK,UAAU,YAAY,QAAQ,SAAS,QAAQ,QAAQ,YAAY,QAAQ,SAAS,QAAQ,SAAS,QAAQ,MAAM,EAAE,KAAK,CAAC;AAAA,IACpJ,QAAQ;AAEN,aAAO;AAAA,IACT;AAAA,EACF;AAEA,QAAM,cAAqB;AAAA,IACzB,OAAO,EAAE,MAAM,YAAY,WAAW,EAAE;AAAA,IACxC,KAAK,EAAE,MAAM,YAAY,WAAW,KAAK,OAAO;AAAA,EAClD;AAKA,QAAM,gBAAgB,OAAO;AAC7B,QAAM,cAAc,gBAAgB,KAAK;AAEzC,QAAM,YAAmB;AAAA,IACvB,OAAO,EAAE,MAAM,YAAY,WAAW,cAAc;AAAA,IACpD,KAAK,EAAE,MAAM,YAAY,WAAW,YAAY;AAAA,EAClD;AAEA,SAAO;AAAA,IACL,MAAM,KAAK,QAAQ,UAAU,IAAI;AAAA;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAtGA,IAiBM;AAjBN;AAAA;AAAA;AAiBA,IAAM,qBAAqB;AAAA;AAAA;;;ACjB3B,IAOa;AAPb;AAAA;AAAA;AACA;AAMO,IAAM,eAAN,MAAmB;AAAA;AAAA,MAEhB,QAAQ,oBAAI,IAAuB;AAAA;AAAA;AAAA;AAAA;AAAA,MAM3C,QAAQ,KAAa,MAAoB;AAEvC,aAAK,MAAM,OAAO,GAAG;AAErB,cAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,cAAM,WAAsB,CAAC;AAE7B,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,SAAS,mBAAmB,MAAM,CAAC,GAAG,CAAC;AAC7C,cAAI,CAAC,OAAQ;AAKb,gBAAM,UAAmB;AAAA,YACvB,MAAM,OAAO;AAAA,YACb,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;AAAA,cAC/B,KAAK,EAAE,MAAM,GAAG,WAAW,MAAM,CAAC,EAAE,OAAO;AAAA;AAAA,YAC7C;AAAA,YACA,WAAW,OAAO;AAAA,YAClB;AAAA,YACA,MAAM,OAAO,KAAK,SAAS,IAAI,OAAO,OAAO;AAAA,YAC7C,MAAM,OAAO;AAAA,UACf;AACA,mBAAS,KAAK,OAAO;AAAA,QACvB;AAGA,iBAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,gBAAM,YAAY,IAAI,IAAI,SAAS,SAC/B,SAAS,IAAI,CAAC,EAAE,MAAM,MAAM,OAAO,IACnC,MAAM,SAAS;AACnB,mBAAS,CAAC,EAAE,QAAQ;AAAA,YAClB,OAAO,SAAS,CAAC,EAAE,MAAM;AAAA,YACzB,KAAK,EAAE,MAAM,WAAW,WAAW,MAAM,SAAS,GAAG,UAAU,EAAE;AAAA,UACnE;AAAA,QACF;AAEA,YAAI,SAAS,SAAS,GAAG;AACvB,eAAK,MAAM,IAAI,KAAK,QAAQ;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA,MAGA,OAAO,KAAmB;AACxB,aAAK,MAAM,OAAO,GAAG;AAAA,MACvB;AAAA;AAAA,MAGA,WAAW,MAAmC;AAC5C,mBAAW,YAAY,KAAK,MAAM,OAAO,GAAG;AAC1C,qBAAW,KAAK,UAAU;AACxB,gBAAI,EAAE,SAAS,KAAM,QAAO;AAAA,UAC9B;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,aAAa,KAAa,MAAmC;AAC3D,cAAM,WAAW,KAAK,MAAM,IAAI,GAAG;AACnC,YAAI,CAAC,SAAU,QAAO;AAGtB,iBAAS,IAAI,SAAS,SAAS,GAAG,KAAK,GAAG,KAAK;AAC7C,cAAI,SAAS,CAAC,EAAE,MAAM,MAAM,QAAQ,MAAM;AACxC,mBAAO,SAAS,CAAC;AAAA,UACnB;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,sBAAsB,KAAwB;AAC5C,eAAO,KAAK,MAAM,IAAI,GAAG,KAAK,CAAC;AAAA,MACjC;AAAA;AAAA,MAGA,iBAA4B;AAC1B,cAAM,SAAoB,CAAC;AAC3B,mBAAW,YAAY,KAAK,MAAM,OAAO,GAAG;AAC1C,iBAAO,KAAK,GAAG,QAAQ;AAAA,QACzB;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,oBAAyC;AACvC,eAAO,KAAK,WAAW,gBAAgB;AAAA,MACzC;AAAA;AAAA,MAGA,eAAoC;AAClC,eAAO,KAAK,WAAW,WAAW;AAAA,MACpC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,gBAAwC;AACtC,cAAM,SAAS,oBAAI,IAAuB;AAC1C,mBAAW,YAAY,KAAK,MAAM,OAAO,GAAG;AAC1C,qBAAW,KAAK,UAAU;AACxB,kBAAM,WAAW,OAAO,IAAI,EAAE,IAAI;AAClC,gBAAI,UAAU;AACZ,uBAAS,KAAK,CAAC;AAAA,YACjB,OAAO;AACL,qBAAO,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;AAAA,YACxB;AAAA,UACF;AAAA,QACF;AAEA,cAAM,aAAa,oBAAI,IAAuB;AAC9C,mBAAW,CAAC,MAAM,QAAQ,KAAK,QAAQ;AACrC,cAAI,SAAS,SAAS,GAAG;AACvB,uBAAW,IAAI,MAAM,QAAQ;AAAA,UAC/B;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA,IACF;AAAA;AAAA;;;ACzIA,SAAS,YAAY,gBAAAA,qBAAoB;AACzC,SAAS,SAAS,MAAM,SAAS,iBAAiB;AAClD,SAAS,qBAAqB;AAF9B,IAsCa;AAtCb;AAAA;AAAA;AAsCO,IAAM,gBAAN,MAAoB;AAAA,MACjB,SAAS,oBAAI,IAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOnC,WAAqB,CAAC;AAAA,MAE/B,eAAqB;AACnB,YAAI,gBAAqC,CAAC;AAE1C,YAAI;AAGF,gBAAM,UAAU,QAAQ,cAAc,YAAY,GAAG,CAAC;AACtD,gBAAM,eAAe,KAAK,oBAAoB,OAAO;AACrD,cAAI,cAAc;AAChB,kBAAM,MAAMA,cAAa,cAAc,OAAO;AAC9C,kBAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,gBAAI,CAAC,MAAM,QAAQ,MAAM,GAAG;AAC1B,mBAAK,SAAS;AAAA,gBACZ,4CAA4C,OAAO,MAAM;AAAA,cAC3D;AAAA,YACF,OAAO;AACL,8BAAgB;AAAA,YAClB;AAAA,UACF;AAAA,QACF,SAAS,KAAc;AAErB,gBAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,eAAK,SAAS;AAAA,YACZ,kCAAkC,OAAO;AAAA,UAC3C;AAAA,QACF;AAEA,mBAAW,KAAK,eAAe;AAC7B,cAAI;AACF,kBAAM,MAAM,EAAE,KAAK,YAAY;AAC/B,iBAAK,OAAO,IAAI,KAAK;AAAA,cACnB,MAAM,EAAE;AAAA,cACR,OAAO,EAAE;AAAA,cACT,WAAW,EAAE,aAAa,CAAC;AAAA,cAC3B,UAAU,EAAE;AAAA,cACZ,aAAa,EAAE;AAAA,cACf,QAAQ,EAAE;AAAA,cACV,QAAQ,EAAE,WAAW,YAAY,YAAY;AAAA,YAC/C,CAAC;AAAA,UACH,QAAQ;AAEN,iBAAK,SAAS,KAAK,0CAA0C,KAAK,UAAU,CAAC,CAAC,EAAE;AAAA,UAClF;AAAA,QACF;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAOA,gBAAgB,aAAoD;AAClE,aAAK,aAAa,WAAW;AAAA,MAC/B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,WAAW,QAA+C;AACxD,aAAK,aAAa,MAAM;AAAA,MAC1B;AAAA;AAAA,MAGA,SAAS,MAAmD;AAC1D,cAAM,MAAM,KAAK,KAAK,YAAY;AAClC,cAAM,WAAW,KAAK,OAAO,IAAI,GAAG;AACpC,aAAK,OAAO,IAAI,KAAK;AAAA,UACnB,MAAM,KAAK;AAAA,UACX,OAAO,KAAK,SAAS,UAAU,SAAS;AAAA,UACxC,WAAW,KAAK,aAAa,UAAU,aAAa,CAAC;AAAA,UACrD,QAAQ,KAAK,UAAU,UAAU,UAAU;AAAA,UAC3C,UAAU,KAAK,YAAY,UAAU;AAAA,UACrC,aAAa,KAAK,eAAe,UAAU;AAAA,UAC3C,QAAQ,KAAK,UAAU,UAAU;AAAA,UACjC,aAAa,KAAK,eAAe,UAAU;AAAA,UAC3C,YAAY,KAAK,cAAc,UAAU;AAAA,UACzC,UAAU,KAAK,YAAY,UAAU;AAAA,UACrC,SAAS,KAAK,WAAW,UAAU;AAAA,UACnC,UAAU,KAAK,YAAY,UAAU;AAAA,QACvC,CAAC;AAAA,MACH;AAAA;AAAA,MAGA,SAAS,MAAqC;AAC5C,eAAO,KAAK,OAAO,IAAI,KAAK,YAAY,CAAC;AAAA,MAC3C;AAAA;AAAA,MAGA,QAAQ,MAAuB;AAC7B,eAAO,KAAK,OAAO,IAAI,KAAK,YAAY,CAAC,GAAG,SAAS;AAAA,MACvD;AAAA;AAAA,MAGA,WAAW,MAAuB;AAChC,cAAM,OAAO,KAAK,OAAO,IAAI,KAAK,YAAY,CAAC;AAC/C,eAAQ,MAAM,WAAW,QAAQ,KAAK,QAAQ,SAAS;AAAA,MACzD;AAAA;AAAA,MAGA,eAA4B;AAC1B,eAAO,MAAM,KAAK,KAAK,OAAO,OAAO,CAAC;AAAA,MACxC;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,oBAAoB,UAAiC;AAC3D,cAAM,SAAS,KAAK,gBAAgB,YAAY,WAAW,QAAQ,OAAO,qBAAqB;AAC/F,YAAI,MAAM;AACV,cAAM,EAAE,KAAK,IAAI,UAAU,GAAG;AAC9B,eAAO,QAAQ,MAAM;AACnB,gBAAM,YAAY,KAAK,KAAK,MAAM;AAClC,cAAI,WAAW,SAAS,GAAG;AACzB,mBAAO;AAAA,UACT;AACA,gBAAM,QAAQ,GAAG;AAAA,QACnB;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGQ,aAAa,SAAgD;AACnE,mBAAW,CAAC,QAAQ,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AACrD,gBAAM,MAAM,OAAO,YAAY;AAC/B,gBAAM,WAAW,KAAK,OAAO,IAAI,GAAG;AAEpC,cAAI,UAAU;AAEZ,gBAAI,MAAM,gBAAgB,OAAW,UAAS,cAAc,MAAM;AAClE,gBAAI,MAAM,eAAe,OAAW,UAAS,aAAa,MAAM;AAChE,gBAAI,MAAM,aAAa,OAAW,UAAS,WAAW,MAAM;AAC5D,gBAAI,MAAM,YAAY,OAAW,UAAS,UAAU,MAAM;AAC1D,gBAAI,MAAM,aAAa,OAAW,UAAS,WAAW,MAAM;AAC5D,gBAAI,MAAM,cAAc,OAAW,UAAS,QAAQ,MAAM;AAAA,UAC5D,OAAO;AAEL,iBAAK,OAAO,IAAI,KAAK;AAAA,cACnB,MAAM,MAAM,QAAQ;AAAA,cACpB,OAAO,MAAM,aAAa;AAAA,cAC1B,WAAW,CAAC;AAAA,cACZ,QAAQ;AAAA,cACR,aAAa,MAAM;AAAA,cACnB,YAAY,MAAM;AAAA,cAClB,UAAU,MAAM;AAAA,cAChB,SAAS,MAAM;AAAA,cACf,UAAU,MAAM;AAAA,YAClB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA;AAAA;;;ACxMA,IAIM,aAGA,mBAKA,gBAmBO;AA/Bb;AAAA;AAAA;AACA;AAGA,IAAM,cAAc;AAGpB,IAAM,oBAAoB,oBAAI,IAAI;AAAA,MAChC;AAAA,MAAkB;AAAA,MAAa;AAAA,MAAa;AAAA,MAAe;AAAA,IAC7D,CAAC;AAGD,IAAM,iBAAiB;AAAA,MACrB;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,MACA;AAAA;AAAA,IACF;AAYO,IAAM,kBAAN,MAAsB;AAAA,MACnB,WAAW,oBAAI,IAA8B;AAAA,MAC7C,qBAAqB;AAAA;AAAA,MAGrB,cAAc,oBAAI,IAA6B;AAAA;AAAA;AAAA;AAAA;AAAA,MAMvD,oBAAoB,SAAuB;AACzC,aAAK,SAAS,MAAM;AACpB,aAAK,qBAAqB;AAE1B,cAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,mBAAW,QAAQ,OAAO;AACxB,gBAAM,UAAU,KAAK,KAAK;AAC1B,cAAI,CAAC,WAAW,QAAQ,WAAW,IAAI,KAAK,QAAQ,WAAW,MAAM,EAAG;AAExE,gBAAM,QAAQ,oCAAoC,KAAK,OAAO;AAC9D,cAAI,CAAC,MAAO;AAEZ,gBAAM,OAAO,MAAM,CAAC;AACpB,gBAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,gBAAM,OAAyB,EAAE,MAAM,OAAO,IAAI;AAGlD,cAAI,KAAK,WAAW,GAAG,GAAG;AACxB,kBAAM,aAAa;AACnB,gBAAI;AACJ,kBAAM,SAAmB,CAAC;AAC1B,oBAAQ,aAAa,WAAW,KAAK,IAAI,OAAO,MAAM;AACpD,qBAAO,KAAK,WAAW,CAAC,CAAC;AAAA,YAC3B;AACA,gBAAI,OAAO,SAAS,GAAG;AACrB,mBAAK,SAAS;AAAA,YAChB;AAAA,UACF;AAEA,eAAK,SAAS,IAAI,MAAM,IAAI;AAAA,QAC9B;AAAA,MACF;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,aAAa,KAAa,MAAc,SAA4B;AAElE,aAAK,YAAY,OAAO,GAAG;AAE3B,cAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,cAAM,SAA0B,CAAC;AAGjC,cAAM,oBAAgE,CAAC;AACvE,iBAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,gBAAM,SAAS,mBAAmB,MAAM,CAAC,GAAG,CAAC;AAC7C,cAAI,QAAQ;AACV,8BAAkB,KAAK,EAAE,MAAM,OAAO,MAAM,WAAW,EAAE,CAAC;AAAA,UAC5D;AAAA,QACF;AAGA,iBAAS,KAAK,GAAG,KAAK,kBAAkB,QAAQ,MAAM;AACpD,gBAAM,UAAU,kBAAkB,EAAE;AACpC,cAAI,kBAAkB,IAAI,QAAQ,IAAI,EAAG;AAEzC,gBAAM,mBAAmB,QAAQ,YAAY;AAC7C,gBAAM,iBAAiB,KAAK,IAAI,kBAAkB,SAC9C,kBAAkB,KAAK,CAAC,EAAE,YAC1B,MAAM;AAEV,gBAAM,eAAe,MAAM,MAAM,kBAAkB,cAAc;AACjE,gBAAM,UAAU,aAAa,KAAK,IAAI;AAGtC,cAAI,UAAU;AACd,qBAAW,WAAW,gBAAgB;AACpC,sBAAU,QAAQ,QAAQ,SAAS,CAAC,MAAM,IAAI,OAAO,EAAE,MAAM,CAAC;AAAA,UAChE;AAGA,gBAAM,cAAwB,CAAC,CAAC;AAChC,mBAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK;AACvC,gBAAI,QAAQ,CAAC,MAAM,KAAM,aAAY,KAAK,IAAI,CAAC;AAAA,UACjD;AAGA,gBAAM,KAAK,IAAI,OAAO,YAAY,QAAQ,GAAG;AAC7C,cAAI;AACJ,kBAAQ,QAAQ,GAAG,KAAK,OAAO,OAAO,MAAM;AAC1C,kBAAM,WAAW,MAAM,CAAC;AACxB,kBAAM,WAAW,SAAS,MAAM,GAAG,EAAE,CAAC;AACtC,kBAAM,aAAa,MAAM;AAGzB,gBAAI,YAAY;AAChB,qBAAS,IAAI,GAAG,IAAI,YAAY,QAAQ,KAAK;AAC3C,kBAAI,YAAY,CAAC,IAAI,WAAY;AACjC,0BAAY;AAAA,YACd;AACA,kBAAM,YAAY,aAAa,YAAY,SAAS;AACpD,kBAAM,eAAe,mBAAmB;AAExC,kBAAM,QAAe;AAAA,cACnB,OAAO,EAAE,MAAM,cAAc,UAAU;AAAA,cACvC,KAAK,EAAE,MAAM,cAAc,WAAW,YAAY,MAAM,CAAC,EAAE,OAAO;AAAA,YACpE;AAEA,mBAAO,KAAK,EAAE,KAAK,UAAU,UAAU,MAAM,CAAC;AAAA,UAChD;AAAA,QACF;AAEA,YAAI,OAAO,SAAS,GAAG;AACrB,eAAK,YAAY,IAAI,KAAK,MAAM;AAAA,QAClC;AAAA,MACF;AAAA;AAAA,MAGA,cAA6C;AAC3C,eAAO,KAAK;AAAA,MACd;AAAA;AAAA,MAGA,UAAU,MAAoD;AAC5D,cAAM,UAAgD,CAAC;AACvD,mBAAW,UAAU,KAAK,YAAY,OAAO,GAAG;AAC9C,qBAAW,KAAK,QAAQ;AACtB,gBAAI,EAAE,aAAa,MAAM;AACvB,sBAAQ,KAAK,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,CAAC;AAAA,YAC7C;AAAA,UACF;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,cAAc,KAAoD;AAChE,cAAM,SAAS,KAAK,YAAY,IAAI,GAAG;AACvC,YAAI,CAAC,OAAQ,QAAO,CAAC;AAErB,cAAM,UAAiD,CAAC;AACxD,cAAM,OAAO,oBAAI,IAAY;AAE7B,mBAAW,KAAK,QAAQ;AACtB,cAAI,CAAC,KAAK,SAAS,IAAI,EAAE,QAAQ,KAAK,CAAC,KAAK,IAAI,EAAE,QAAQ,GAAG;AAC3D,iBAAK,IAAI,EAAE,QAAQ;AACnB,oBAAQ,KAAK,EAAE,MAAM,EAAE,UAAU,OAAO,EAAE,MAAM,CAAC;AAAA,UACnD;AAAA,QACF;AACA,eAAO;AAAA,MACT;AAAA;AAAA,MAGA,oBAA6B;AAC3B,eAAO,KAAK;AAAA,MACd;AAAA,IACF;AAAA;AAAA;;;AC9LA,IAGM,gBAGA,YAMO;AAZb;AAAA;AAAA;AAGA,IAAM,iBAAiB;AAGvB,IAAM,aAAa;AAMZ,IAAM,iBAAN,MAAqB;AAAA,MAClB,UAAU,oBAAI,IAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAS7C,KAAK,UAAqB,YAAuD;AAC/E,aAAK,QAAQ,MAAM;AAEnB,mBAAW,WAAW,UAAU;AAC9B,cAAI,CAAC,QAAQ,MAAM,SAAS,QAAQ,EAAG;AAEvC,gBAAM,OAAO,WAAW,QAAQ,GAAG;AACnC,cAAI,CAAC,KAAM;AAGX,gBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,gBAAM,mBAAmB,QAAQ,MAAM,MAAM,OAAO;AAEpD,cAAI,iBAAiB,MAAM;AAC3B,mBAAS,IAAI,kBAAkB,IAAI,MAAM,QAAQ,KAAK;AACpD,gBAAI,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3B,+BAAiB;AACjB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,eAAe,MAAM,MAAM,kBAAkB,cAAc;AAEjE,mBAAS,IAAI,GAAG,IAAI,aAAa,QAAQ,KAAK;AAC5C,kBAAM,OAAO,aAAa,CAAC;AAC3B,2BAAe,YAAY;AAC3B,gBAAI;AAEJ,oBAAQ,QAAQ,eAAe,KAAK,IAAI,OAAO,MAAM;AACnD,oBAAM,aAAa,MAAM,CAAC;AAC1B,oBAAM,cAAc,MAAM,CAAC,KAAK;AAChC,oBAAM,SAAmB,CAAC;AAC1B,kBAAI;AACJ,yBAAW,YAAY;AACvB,sBAAQ,aAAa,WAAW,KAAK,WAAW,OAAO,MAAM;AAC3D,uBAAO,KAAK,WAAW,CAAC,CAAC;AAAA,cAC3B;AAEA,oBAAM,UAAU,mBAAmB;AACnC,oBAAM,YAAY,MAAM;AACxB,oBAAM,UAAU,YAAY,MAAM,CAAC,EAAE;AAErC,oBAAM,QAAe;AAAA,gBACnB,OAAO,EAAE,MAAM,SAAS,WAAW,UAAU;AAAA,gBAC7C,KAAK,EAAE,MAAM,SAAS,WAAW,QAAQ;AAAA,cAC3C;AAEA,mBAAK,QAAQ,IAAI,YAAY;AAAA,gBAC3B,MAAM;AAAA,gBACN;AAAA,gBACA,KAAK,QAAQ;AAAA,gBACb;AAAA,cACF,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,UAAU,MAAqC;AAC7C,eAAO,KAAK,QAAQ,IAAI,IAAI;AAAA,MAC9B;AAAA;AAAA,MAGA,gBAA6B;AAC3B,eAAO,MAAM,KAAK,KAAK,QAAQ,OAAO,CAAC;AAAA,MACzC;AAAA,IACF;AAAA;AAAA;;;ACnEA,SAAS,gBAAgB,MAAwB;AAC/C,QAAM,SAAS,CAAC,CAAC;AACjB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB,aAAO,KAAK,IAAI,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAAS,iBAAiB,QAAgB,YAA2D;AAEnG,MAAI,MAAM;AACV,MAAI,OAAO,WAAW,SAAS;AAC/B,SAAO,MAAM,MAAM;AACjB,UAAM,MAAO,MAAM,OAAO,KAAM;AAChC,QAAI,WAAW,GAAG,KAAK,QAAQ;AAC7B,YAAM;AAAA,IACR,OAAO;AACL,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACA,SAAO,EAAE,MAAM,KAAK,WAAW,SAAS,WAAW,GAAG,EAAE;AAC1D;AAQO,SAAS,YAAY,MAA2B;AAErD,QAAM,UAAU,KAAK,QAAQ,4BAA4B,CAACC,WAAU;AAClE,WAAO,IAAI,OAAOA,OAAM,MAAM;AAAA,EAChC,CAAC;AAED,QAAM,aAAa,gBAAgB,IAAI;AACvC,QAAM,SAAsB,CAAC;AAC7B,MAAI,KAAK;AAGT,aAAW,YAAY;AACvB,MAAI;AAEJ,UAAQ,QAAQ,WAAW,KAAK,OAAO,OAAO,MAAM;AAClD,UAAM,aAAa,MAAM,CAAC;AAC1B,UAAM,aAAa,MAAM,CAAC,KAAK,IAAI,KAAK;AACxC,UAAM,YAAY,MAAM,CAAC;AACzB,UAAM,UAAU,MAAM,CAAC;AAEvB,UAAM,OAAO,eAAe;AAE5B,UAAM,aAAa,MAAM;AACzB,UAAM,WAAW,aAAa,MAAM,CAAC,EAAE;AAEvC,UAAM,WAAW,iBAAiB,YAAY,UAAU;AACxD,UAAM,SAAS,iBAAiB,UAAU,UAAU;AAEpD,UAAM,QAAe;AAAA,MACnB,OAAO;AAAA,MACP,KAAK;AAAA,IACP;AAEA,WAAO,KAAK;AAAA,MACV;AAAA,MACA,MAAM;AAAA,MACN,MAAM;AAAA,MACN;AAAA,MACA;AAAA,MACA,WAAW,aAAa;AAAA,MACxB,SAAS,WAAW;AAAA,IACtB,CAAC;AAED;AAAA,EACF;AAEA,SAAO;AACT;AAWO,SAAS,WAAW,QAAqB,SAA0C;AACxF,QAAM,SAAmC,CAAC;AAE1C,aAAW,SAAS,QAAQ;AAC1B,UAAM,OAAO,MAAM,KAAK,YAAY;AAEpC,QAAI,CAAC,QAAQ,MAAM,IAAI,EAAG;AAE1B,QAAI,MAAM,MAAM;AACd,UAAI,CAAC,OAAO,IAAI,EAAG,QAAO,IAAI,IAAI,CAAC;AACnC,aAAO,IAAI,EAAE,KAAK,MAAM,EAAE;AAAA,IAC5B,OAAO;AAEL,YAAM,QAAQ,OAAO,IAAI;AACzB,UAAI,SAAS,MAAM,SAAS,GAAG;AAC7B,cAAM,SAAS,MAAM,IAAI;AACzB,eAAO,MAAM,EAAE,OAAO,MAAM;AAC5B,cAAM,OAAO;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAxIA,IAMM,4BAUA;AAhBN;AAAA;AAAA;AAMA,IAAM,6BAA6B;AAUnC,IAAM,aAAa;AAAA;AAAA;;;AChBnB;AAAA;AAAA;AAAA;AAAA,MACE,IAAM;AAAA,QACJ,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,QAAQ,KAAO,EAAE;AAAA,UAC3B,EAAE,MAAQ,SAAS;AAAA,QACrB;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,SAAW,CAAC,IAAI;AAAA,QAChB,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW,CAAC,IAAI;AAAA,QAChB,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,KAAO;AAAA,QACL,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,OAAO;AAAA,UACjB,EAAE,MAAQ,OAAO;AAAA,QACnB;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,UAAY;AAAA,MACd;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW,CAAC,KAAK;AAAA,QACjB,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW,CAAC,OAAO,QAAQ;AAAA,QAC3B,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,QAAQ,KAAO,EAAE;AAAA,UAC3B,EAAE,MAAQ,WAAW,KAAO,EAAE;AAAA,QAChC;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,SAAW,CAAC,QAAQ;AAAA,QACpB,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,SAAW,CAAC,QAAQ;AAAA,QACpB,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,KAAO;AAAA,QACL,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,UAAY;AAAA,QACV,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,IAAM;AAAA,QACJ,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,gBAAgB,EAAE;AAAA,MACnC;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,gBAAgB,EAAE;AAAA,MACnC;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,OAAO;AAAA,QACnB;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,OAAO;AAAA,QACnB;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,UAAU,KAAO,EAAE;AAAA,QAC/B;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,UAAU;AAAA,MAC3B;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,UAAY;AAAA,UACV,EAAE,MAAQ,UAAU,KAAO,EAAE;AAAA,QAC/B;AAAA,QACA,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,UAAU;AAAA,MAC3B;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,SAAW,CAAC,WAAW,OAAO;AAAA,QAC9B,aAAe;AAAA,QACf,YAAc,CAAC,mBAAmB,MAAM;AAAA,MAC1C;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,kBAAkB;AAAA,MACnC;AAAA,MACA,WAAa;AAAA,QACX,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,kBAAkB;AAAA,MACnC;AAAA,MACA,UAAY;AAAA,QACV,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,kBAAkB;AAAA,MACnC;AAAA,MACA,UAAY;AAAA,QACV,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,kBAAkB;AAAA,MACnC;AAAA,MACA,aAAe;AAAA,QACb,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,0BAA0B;AAAA,MAC3C;AAAA,MACA,WAAa;AAAA,QACX,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,WAAa;AAAA,QACX,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,UAAY;AAAA,QACV,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,eAAe;AAAA,QACb,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,QAAU;AAAA,QACR,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC,MAAM;AAAA,MACvB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,MAAQ;AAAA,QACN,MAAQ;AAAA,QACR,WAAa;AAAA,QACb,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,gBAAgB;AAAA,QACd,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,qBAAqB;AAAA,QACnB,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC;AAAA,MACjB;AAAA,MACA,OAAS;AAAA,QACP,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,MACA,SAAW;AAAA,QACT,MAAQ;AAAA,QACR,aAAe;AAAA,QACf,YAAc,CAAC,SAAS;AAAA,MAC1B;AAAA,IACF;AAAA;AAAA;;;AC1RA,SAAS,gBAAAC,qBAAoB;AAA7B,IAqBa;AArBb;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAcO,IAAM,iBAAN,cAA6BA,cAAa;AAAA,MACtC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAED,gBAAsD;AAAA,MAC7C,cAAc;AAAA;AAAA,MAGvB;AAAA,MACA;AAAA,MACA;AAAA,MAER,YAAY,QAA+B;AACzC,cAAM;AACN,aAAK,YAAY,IAAI,cAAc;AACnC,aAAK,WAAW,IAAI,aAAa;AACjC,aAAK,SAAS,IAAI,cAAc;AAChC,aAAK,YAAY,IAAI,gBAAgB;AACrC,aAAK,UAAU,IAAI,eAAe;AAGlC,aAAK,oBAAoB,CAAC,QAAgB,KAAK,qBAAqB,GAAG;AACvE,aAAK,mBAAmB,CAAC,QAAgB,KAAK,qBAAqB,GAAG;AACtE,aAAK,mBAAmB,CAAC,QAAgB,KAAK,oBAAoB,GAAG;AAGrE,aAAK,UAAU,GAAG,mBAAmB,KAAK,iBAAiB;AAC3D,aAAK,UAAU,GAAG,kBAAkB,KAAK,gBAAgB;AACzD,aAAK,UAAU,GAAG,kBAAkB,KAAK,gBAAgB;AAAA,MAC3D;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,WAAW,cAAyC;AAElD,aAAK,OAAO,aAAa;AACzB,aAAK,OAAO,gBAAgB,yBAAkC;AAK9D,aAAK,UAAU,eAAe,kBAAkB,KAAK,gBAAgB;AACrE,aAAK,UAAU,eAAe,mBAAmB,KAAK,iBAAiB;AAEvE,mBAAW,CAAC,KAAK,IAAI,KAAK,cAAc;AACtC,eAAK,UAAU,KAAK,KAAK,IAAI;AAAA,QAC/B;AAGA,aAAK,UAAU,GAAG,kBAAkB,KAAK,gBAAgB;AACzD,aAAK,UAAU,GAAG,mBAAmB,KAAK,iBAAiB;AAG3D,aAAK,WAAW;AAGhB,aAAK,mBAAmB;AAAA,MAC1B;AAAA;AAAA,MAGA,UAAgB;AACd,aAAK,UAAU,eAAe,mBAAmB,KAAK,iBAAiB;AACvE,aAAK,UAAU,eAAe,kBAAkB,KAAK,gBAAgB;AACrE,aAAK,UAAU,eAAe,kBAAkB,KAAK,gBAAgB;AAErE,YAAI,KAAK,eAAe;AACtB,uBAAa,KAAK,aAAa;AAC/B,eAAK,gBAAgB;AAAA,QACvB;AAEA,aAAK,mBAAmB;AAAA,MAC1B;AAAA;AAAA,MAGQ,qBAAqB,KAAmB;AAC9C,cAAM,OAAO,KAAK,UAAU,QAAQ,GAAG;AACvC,YAAI,SAAS,QAAW;AACtB,eAAK,SAAS,QAAQ,KAAK,IAAI;AAAA,QACjC;AACA,aAAK,QAAQ;AACb,aAAK,KAAK,mBAAmB,GAAG;AAChC,aAAK,KAAK,mBAAmB,GAAG;AAChC,aAAK,mBAAmB;AAAA,MAC1B;AAAA;AAAA,MAGQ,oBAAoB,KAAmB;AAC7C,aAAK,SAAS,OAAO,GAAG;AACxB,aAAK,QAAQ;AACb,aAAK,KAAK,kBAAkB,GAAG;AAC/B,aAAK,KAAK,mBAAmB,GAAG;AAChC,aAAK,mBAAmB;AAAA,MAC1B;AAAA;AAAA,MAGQ,aAAmB;AACzB,mBAAW,OAAO,KAAK,UAAU,QAAQ,GAAG;AAC1C,gBAAM,OAAO,KAAK,UAAU,QAAQ,GAAG;AACvC,cAAI,SAAS,QAAW;AACtB,iBAAK,SAAS,QAAQ,KAAK,IAAI;AAAA,UACjC;AAAA,QACF;AACA,aAAK,QAAQ;AAAA,MACf;AAAA;AAAA;AAAA;AAAA;AAAA,MAMQ,UAAgB;AAEtB,cAAM,YAAY,KAAK,SAAS,kBAAkB;AAClD,YAAI,WAAW;AACb,gBAAM,OAAO,KAAK,UAAU,QAAQ,UAAU,GAAG;AACjD,cAAI,MAAM;AACR,kBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,kBAAM,eAAe,UAAU,UAAU,IAAI,OAAO;AAEpD,gBAAI,aAAa,MAAM;AACvB,qBAAS,IAAI,cAAc,IAAI,MAAM,QAAQ,KAAK;AAChD,kBAAI,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3B,6BAAa;AACb;AAAA,cACF;AAAA,YACF;AACA,kBAAM,UAAU,MAAM,MAAM,cAAc,UAAU,EAAE,KAAK,IAAI;AAC/D,iBAAK,UAAU,oBAAoB,OAAO;AAAA,UAC5C;AAAA,QACF;AAGA,mBAAW,OAAO,KAAK,UAAU,QAAQ,GAAG;AAC1C,gBAAM,OAAO,KAAK,UAAU,QAAQ,GAAG;AACvC,cAAI,MAAM;AACR,kBAAM,SAAS,YAAY,IAAI;AAC/B,iBAAK,UAAU,aAAa,KAAK,MAAM,MAAM;AAAA,UAC/C;AAAA,QACF;AAGA,cAAM,cAAc,KAAK,SAAS,eAAe;AACjD,aAAK,QAAQ,KAAK,aAAa,CAAC,QAAQ,KAAK,UAAU,QAAQ,GAAG,CAAC;AAAA,MACrE;AAAA;AAAA,MAGQ,qBAA2B;AACjC,YAAI,KAAK,eAAe;AACtB,uBAAa,KAAK,aAAa;AAAA,QACjC;AACA,aAAK,gBAAgB,WAAW,MAAM;AACpC,eAAK,gBAAgB;AACrB,eAAK,KAAK,YAAY;AAAA,QACxB,GAAG,KAAK,WAAW;AAAA,MACrB;AAAA,IACF;AAAA;AAAA;;;ACtIO,SAAS,YAAY,MAAqC;AAC/D,SAAO,YAAY,IAAI;AACzB;AAhDA,IAAa,gBAyBP;AAzBN;AAAA;AAAA;AAAO,IAAM,iBAAiB;AAAA,MAC5B,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,MACjB,qBAAqB;AAAA,MACrB,oBAAoB;AAAA,MACpB,kBAAkB;AAAA,MAClB,kBAAkB;AAAA,MAClB,wBAAwB;AAAA,MACxB,kBAAkB;AAAA,MAClB,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,MACpB,iBAAiB;AAAA,MACjB,kBAAkB;AAAA,MAClB,mBAAmB;AAAA,MACnB,wBAAwB;AAAA,MACxB,gBAAgB;AAAA,MAChB,oBAAoB;AAAA,IACtB;AAMA,IAAM,cAAqD;AAAA,MACzD,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,MACP,OAAO;AAAA,IACT;AAAA;AAAA;;;ACEO,SAAS,aAAa,QAAuB;AAClD,QAAM,QAAQ,IAAI,MAAM,QAAQ,QAAQ;AACxC,QAAM,WAAW,MAAM,IAAI;AAE3B,QAAMC,QAAc,CAAC;AACrB,aAAW,QAAQ,UAAU;AAC3B,QAAI,KAAK,SAAS,eAAe;AAE/B;AAAA,IACF;AACA,IAAAA,MAAK,KAAK,cAAc,IAAI,CAAC;AAAA,EAC/B;AACA,SAAOA;AACT;AAeA,SAAS,cAAc,MAA+B;AACpD,QAAM,OAAO,KAAK;AAClB,QAAM,OAAO,EAAE,MAAM,OAAO,KAAK,OAAO,KAAK,KAAK,SAAS;AAE3D,UAAQ,KAAK,MAAM;AAAA,IACjB,KAAK;AACH,aAAO,EAAE,GAAG,MAAM,MAAM,eAAe;AAAA,IAEzC,KAAK;AACH,aAAO,EAAE,GAAG,MAAM,MAAM,mBAAmB;AAAA,IAE7C,KAAK,uBAAuB;AAI1B,YAAM,QAAQ,KAAK,MAAM,CAAC;AAC1B,UAAI,uBAAuB,KAAK,KAAK,GAAG;AACtC,eAAO,EAAE,GAAG,MAAM,MAAM,cAAc;AAAA,MACxC;AACA,aAAO,EAAE,GAAG,MAAM,MAAM,aAAa;AAAA,IACvC;AAAA,IAEA,KAAK,kBAAkB;AAErB,UAAI,cAAc,KAAK,IAAI,GAAG;AAC5B,cAAM,QAAQ,KAAK,CAAC;AACpB,cAAM,YAAY,KAAK,MAAM,CAAC,EAAE,MAAM,GAAG;AACzC,eAAO;AAAA,UACL,GAAG;AAAA,UACH,MAAM;AAAA,UACN;AAAA,UACA,MAAM;AAAA,QACR;AAAA,MACF;AAGA,UAAI,SAAS,OAAQ,QAAO,EAAE,GAAG,MAAM,MAAM,aAAa;AAC1D,UAAI,SAAS,YAAa,QAAO,EAAE,GAAG,MAAM,MAAM,mBAAkB;AACpE,UAAI,SAAS,OAAQ,QAAO,EAAE,GAAG,MAAM,MAAM,gBAAgB;AAC7D,UAAI,SAAS,QAAS,QAAO,EAAE,GAAG,MAAM,MAAM,gBAAgB;AAC9D,UAAI,SAAS,MAAO,QAAO,EAAE,GAAG,MAAM,MAAM,YAAY;AAGxD,YAAM,QAAQ,OAAO,IAAI;AACzB,UAAI,CAAC,OAAO,MAAM,KAAK,GAAG;AACxB,eAAO,EAAE,GAAG,MAAM,MAAM,eAAe;AAAA,MACzC;AAGA,aAAO,EAAE,GAAG,MAAM,MAAM,iBAAiB;AAAA,IAC3C;AAAA,IAEA;AACE,aAAO,EAAE,GAAG,MAAM,MAAM,iBAAiB;AAAA,EAC7C;AACF;AAsHA,SAAS,WAAW,OAAuB,UAAiC;AAC1E,aAAS;AACP,UAAM,OAAO,MAAM,KAAK;AACxB,QAAI,SAAS,MAAM;AACjB,YAAM,KAAK,MAAM,KAAK;AACtB,UAAI,OAAO,OAAO,OAAO,KAAM;AAAA,IACjC,WAAW,SAAS,KAAK;AACvB,aAAO;AAAA,IACT,WAAW,SAAS,QAAQ,aAAa,KAAK;AAC5C,aAAO;AAAA,IACT,WAAW,SAAS,UAAU;AAC5B;AAAA,IACF;AAAA,EACF;AACA,SAAO,MAAM;AACf;AAEA,SAAS,SAAS,OAAmD;AACnE,QAAM,SAAS,MAAM,OAAO,MAAM,MAAM,GAAG,EAAE,OAAO,aAAa;AAEjE,MAAI,WAAW,GAAI,QAAO;AAC1B,MAAI,WAAW,GAAG;AAChB,UAAM,OAAO;AACb,UAAM,OAAO;AAAA,EACf;AAGA,MAAI,MAAM,KAAK,MAAM,KAAK;AACxB,UAAM,KAAK;AACX,UAAM,OAAO;AACb,WAAO;AAAA,EACT;AAEA,UAAQ,MAAM,KAAK,GAAG;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT,KAAK;AACH,aAAO;AAAA,IACT;AACE,aAAO;AAAA,EACX;AACF;AAEA,SAAS,cAAc,OAAmD;AACxE,MAAI,WAAW,OAAO,GAAG,MAAM,KAAK;AAClC,WAAO,MAAM,MAAM,eAAe,mCAAmC;AAAA,EACvE;AACA,QAAM,KAAK,kBAAkB;AAC7B,SAAO;AACT;AAEA,SAAS,eAAe,OAAmD;AACzE,MAAI,WAAW,OAAO,GAAG,MAAM,KAAK;AAClC,WAAO,MAAM,MAAM,eAAe,mCAAmC;AAAA,EACvE;AACA,QAAM,KAAK,cAAc;AACzB,SAAO;AACT;AAEA,SAAS,eAAe,OAAmD;AACzE,MAAI,WAAW,OAAO,GAAG,MAAM,KAAK;AAClC,WAAO,MAAM,MAAM,eAAe,mCAAmC;AAAA,EACvE;AACA,QAAM,KAAK,cAAc;AACzB,SAAO;AACT;AAEA,SAAS,iBAAiB,OAAmD;AAC3E,QAAM,UAAU;AAChB,MAAI;AAEJ,MAAI,MAAM,OAAO,OAAO,GAAG;AACzB,WAAO;AACP,UAAM,UAAU,OAAO;AAAA,EACzB,OAAO;AACL,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,MAAM,OAAO,GAAG,GAAG;AACtB,WAAO,MAAM,MAAM,eAAe,aAAa,IAAI,SAAS;AAAA,EAC9D;AAEA,QAAM,QAAQ;AAEd,aAAS;AACP,YAAQ,MAAM,KAAK,GAAG;AAAA,MACpB,KAAK,MAAM;AACT,cAAM,KAAK,MAAM,KAAK;AACtB,YAAI,OAAO,OAAO,OAAO,KAAM;AAAA,MACjC;AAAA;AAAA,MAEA,KAAK;AAAA,MACL,KAAK;AACH,eAAO,MAAM,MAAM,eAAe,gBAAgB,IAAI,SAAS;AAAA,MACjE,KAAK;AACH,UAAE,MAAM;AACR;AAAA,MACF,KAAK;AACH,UAAE,MAAM;AACR,YAAI,MAAM,QAAQ,GAAG;AACnB,iBAAO,MAAM,MAAM,eAAe,qCAAqC;AAAA,QACzE;AACA,YAAI,MAAM,UAAU,GAAG;AACrB,cAAI,MAAM,KAAK,MAAM,KAAK;AACxB,cAAE,MAAM;AAER,kBAAM,KAAK,qBAAqB;AAChC,mBAAO;AAAA,UACT;AACA,gBAAM,OAAO;AAAA,QACf;AACA;AAAA,IACJ;AAAA,EACF;AACF;AAEA,SAAS,YAAY,OAAmD;AACtE,QAAM,SAAS,MAAM,OAAO,MAAM,MAAM,GAAG,EAAE,OAAO,UAAU;AAC9D,MAAI,WAAW,IAAI;AAEjB,QAAI,MAAM,MAAM,OAAO;AAEvB,WAAO,MAAM,MAAM,OAAO,MAAM,OAAO,MAAM,CAAC,MAAM,KAAK;AACvD;AAAA,IACF;AACA,UAAM,MAAM;AACZ,UAAM,KAAK,gBAAgB;AAE3B,QAAI,MAAM,MAAM,OAAO,QAAQ;AAC7B,YAAM,MAAM,MAAM;AAClB,YAAM,OAAO;AACb,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAGA,QAAM,cAAc,MAAM,OAAO,MAAM,MAAM,GAAG,EAAE,QAAQ,GAAG;AAC7D,MAAI,gBAAgB,MAAM,cAAc,QAAQ;AAC9C,UAAM,OAAO;AACb,UAAM,KAAK,gBAAgB;AAC3B,UAAM;AACN,UAAM,OAAO;AACb,WAAO;AAAA,EACT;AAEA,QAAM,OAAO;AACb,QAAM,KAAK,gBAAgB;AAC3B,SAAO;AACT;AAhZA,IAwEM,eAyEA,KAGA,OAgGA,eACA;AArPN;AAAA;AAAA;AAwEA,IAAM,gBAAgB;AAyEtB,IAAM,MAAM;AAGZ,IAAM,QAAN,MAAe;AAAA,MACJ;AAAA,MACT;AAAA,MACA,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,QAAQ;AAAA,MACR,QAAwB,CAAC;AAAA,MAEzB,YAAY,QAAgB,SAAwB;AAClD,aAAK,SAAS;AACd,aAAK,QAAQ;AAAA,MACf;AAAA,MAEA,MAAsB;AACpB,eAAO,KAAK,UAAU,MAAM;AAC1B,eAAK,QAAQ,KAAK,MAAM,IAAI;AAAA,QAC9B;AACA,eAAO,KAAK;AAAA,MACd;AAAA,MAEA,OAAsB;AACpB,cAAM,KAAK,KAAK,KAAK;AACrB,aAAK;AACL,eAAO;AAAA,MACT;AAAA,MAEA,OAAsB;AACpB,YAAI,KAAK,OAAO,KAAK,OAAO,OAAQ,QAAO;AAC3C,eAAO,KAAK,OAAO,KAAK,GAAG;AAAA,MAC7B;AAAA,MAEA,OAAO,MAAM,GAAG;AACd,aAAK,OAAO;AAAA,MACd;AAAA,MAEA,QAAQ,MAAM,GAAG;AACf,aAAK,OAAO;AAAA,MACd;AAAA,MAEA,SAAS;AACP,aAAK,QAAQ,KAAK;AAAA,MACpB;AAAA,MAEA,OAAO,OAAwB;AAC7B,cAAM,KAAK,KAAK,KAAK;AACrB,YAAI,OAAO,IAAK,QAAO;AACvB,YAAI,MAAM,SAAS,EAAY,EAAG,QAAO;AACzC,aAAK,OAAO;AACZ,eAAO;AAAA,MACT;AAAA,MAEA,UAAU,OAAe;AACvB,mBAAS;AACP,gBAAM,KAAK,KAAK,KAAK;AACrB,cAAI,OAAO,IAAK;AAChB,cAAI,CAAC,MAAM,SAAS,EAAY,GAAG;AACjC;AAAA,UACF;AAAA,QACF;AACA,aAAK,OAAO;AAAA,MACd;AAAA,MAEA,KAAK,MAAS;AACZ,aAAK,MAAM,KAAK;AAAA,UACd;AAAA,UACA,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,KAAK,GAAG;AAAA,UAC5C,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,QACjB,CAAC;AACD,aAAK,QAAQ,KAAK;AAAA,MACpB;AAAA,MAEA,MAAM,MAAS,SAAuB;AACpC,aAAK,MAAM,KAAK;AAAA,UACd;AAAA,UACA;AAAA,UACA,MAAM,KAAK,OAAO,MAAM,KAAK,OAAO,KAAK,GAAG;AAAA,UAC5C,OAAO,KAAK;AAAA,UACZ,UAAU,KAAK;AAAA,QACjB,CAAC;AACD,eAAO;AAAA,MACT;AAAA,IACF;AAcA,IAAM,gBAAgB;AACtB,IAAM,aAAa;AAAA;AAAA;;;ACpLnB,SAAS,YAAY,KAAmB;AACtC,SAAO,IAAI,6BAA6B,IAAI;AAC9C;AAgHA,SAAS,kBAAkB,MAAoC;AAC7D,aAAW,MAAM,gBAAgB;AAC/B,QAAI,GAAG,KAAK,SAAS,IAAI,EAAG,QAAO;AAAA,EACrC;AACA,SAAO;AACT;AAyEA,SAAS,UAAU,cAAmC;AACpD,MAAI,MAAM;AACV,QAAM,QAAqB,CAAC;AAC5B,MAAI,OAAO;AAEX,aAAS;AACP,QAAI,EAAE,OAAO,UAAW,OAAM,IAAI,MAAM,qCAAqC;AAC7E,QAAI,OAAO,aAAa,OAAQ;AAEhC,UAAM,KAAK,aAAa,GAAG;AAE3B,QAAI,KAAK,KAAK,EAAE,GAAG;AACjB;AAAA,IACF,WAAW,OAAO,KAAK;AACrB;AACA,YAAM,OAAO,aAAa,GAAG;AAC7B,UAAI,SAAS,KAAK;AAChB;AACA,cAAM,KAAK,EAAE,MAAM,gBAAmB,CAAC;AAAA,MACzC,OAAO;AACL,cAAM,IAAI,MAAM,uCAAuC,QAAQ,KAAK,GAAG;AAAA,MACzE;AAAA,IACF,WAAW,OAAO,KAAK;AACrB;AACA,YAAM,OAAO,aAAa,GAAG;AAC7B,UAAI,SAAS,KAAK;AAChB;AACA,cAAM,KAAK,EAAE,MAAM,kBAAqB,CAAC;AAAA,MAC3C,WAAW,SAAS,QAAW;AAC7B,cAAM,IAAI,MAAM,iCAAiC;AAAA,MACnD,WAAW,KAAK,KAAK,IAAI,GAAG;AAC1B;AACA,cAAM,KAAK,EAAE,MAAM,WAAc,CAAC;AAAA,MACpC,WAAW,aAAa,KAAK,IAAI,KAAK,QAAQ,KAAK,IAAI,GAAG;AACxD,cAAM,KAAK,EAAE,MAAM,WAAc,CAAC;AAAA,MACpC,OAAO;AACL,cAAM,IAAI,MAAM,sCAAsC,IAAI,GAAG;AAAA,MAC/D;AAAA,IACF,WAAW,QAAQ,KAAK,EAAE,GAAG;AAC3B,YAAM,YAAY;AAClB,YAAM,QAAQ;AACd;AACA,aAAO,MAAM,aAAa,UAAU,aAAa,GAAG,MAAM,WAAW;AACnE,YAAI,EAAE,OAAO,UAAW,OAAM,IAAI,MAAM,4CAA4C;AACpF;AAAA,MACF;AACA,UAAI,OAAO,aAAa,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AAClF,YAAM,QAAQ,aAAa,MAAM,QAAQ,GAAG,GAAG;AAC/C;AACA,YAAM,KAAK,EAAE,MAAM,iBAAoB,MAAM,CAAC;AAAA,IAChD,WAAW,OAAO,OAAO,OAAO,KAAK;AACnC;AACA,YAAM,KAAK,EAAE,MAAM,eAAkB,MAAM,OAAO,IAAI,CAAC;AAAA,IACzD,WAAW,aAAa,KAAK,EAAE,GAAG;AAChC,YAAM,QAAQ;AACd;AACA,aAAO,MAAM,aAAa,QAAQ;AAChC,YAAI,EAAE,OAAO,UAAW,OAAM,IAAI,MAAM,gDAAgD;AACxF,cAAM,IAAI,aAAa,GAAG;AAC1B,YAAI,YAAY,KAAK,CAAC,KAAK,MAAM,OAAW;AAC5C,YAAI,aAAa,KAAK,CAAC,GAAG;AACxB;AAAA,QACF,WAAW,QAAQ,KAAK,CAAC,GAAG;AAC1B,gBAAM,IAAI,MAAM,eAAe,CAAC,sCAAsC;AAAA,QACxE,OAAO;AACL,gBAAM,IAAI,MAAM,2BAA2B,CAAC,0BAA0B;AAAA,QACxE;AAAA,MACF;AACA,YAAM,QAAQ,aAAa,MAAM,OAAO,GAAG;AAC3C,YAAM,KAAK,kBAAkB,KAAK;AAClC,UAAI,OAAO,KAAM,OAAM,IAAI,MAAM,gCAAgC,KAAK,GAAG;AACzE,YAAM,KAAK,EAAE,MAAM,cAAiB,MAAM,GAAG,CAAC;AAAA,IAChD,WAAW,OAAO,OAAO,aAAa,MAAM,CAAC,MAAM,OAAO,aAAa,MAAM,CAAC,MAAM,KAAK;AACvF,aAAO;AACP,YAAM,KAAK,EAAE,MAAM,eAAkB,CAAC;AAAA,IACxC,OAAO;AACL,YAAM,IAAI,MAAM,8BAA8B,EAAE,GAAG;AAAA,IACrD;AAAA,EACF;AAEA,SAAO;AACT;AAQA,SAAS,YAAY,cAAqC;AACxD,QAAM,SAAS,UAAU,YAAY;AACrC,MAAI,OAAO,WAAW,EAAG,QAAO;AAEhC,MAAI,QAAQ;AACZ,MAAI,OAAO;AAEX,WAAS,QAAQ,MAA2C;AAC1D,YAAQ,MAAM;AAAA,MACZ,KAAK;AAAe,eAAO,CAAC,GAAG,EAAE;AAAA,MACjC,KAAK;AAAoB,eAAO,CAAC,GAAG,CAAC;AAAA,MACrC,KAAK;AAAsB,eAAO,CAAC,GAAG,CAAC;AAAA,MACvC;AAAS,eAAO;AAAA,IAClB;AAAA,EACF;AAEA,WAAS,SAAS,MAA0B;AAC1C,YAAQ,MAAM;AAAA,MACZ,KAAK;AAAsB,eAAO;AAAA,MAClC,KAAK;AAAmB,eAAO;AAAA,MAC/B;AAAS,cAAM,IAAI,MAAM,0CAA0C,IAAI,EAAE;AAAA,IAC3E;AAAA,EACF;AAEA,WAAS,WAAW,GAAuB;AACzC,WAAO,EAAE,SAAS,qBAAwB,EAAE,SAAS;AAAA,EACvD;AAEA,WAAS,QAAQ,GAA+C;AAC9D,WAAO,EAAE,SAAS,gBAAmB,EAAE,SAAS;AAAA,EAClD;AAEA,WAAS,OAAO,OAAuB;AACrC,QAAI,EAAE,OAAO,YAAa,OAAM,IAAI,MAAM,uCAAuC;AACjF,UAAM,MAAM,OAAO,KAAK;AACxB,QAAI,CAAC,IAAK,OAAM,IAAI,MAAM,wCAAwC;AAClE;AAEA,QAAI;AAEJ,QAAI,WAAW,GAAG,GAAG;AACnB,YAAM,MAAM,SAAS,IAAI,IAAI;AAC7B,YAAM,MAAM,OAAO,GAAG;AACtB,YAAM,EAAE,MAAM,IAAI,MAAM,OAAO,IAAI;AAAA,IACrC,WAAW,IAAI,SAAS,eAAkB;AACxC,YAAM,IAAI;AACV,UAAI,CAAC,EAAE,KAAM,OAAM,IAAI,MAAM,uCAAuC;AACpE,YAAM,OAAO,CAAC;AACd,YAAM,UAAU,OAAO,KAAK;AAC5B,UAAI,CAAC,WAAW,QAAQ,SAAS,iBAAqB,QAA8B,MAAM;AACxF,cAAM,IAAI,MAAM,qCAAqC;AAAA,MACvD;AACA;AAAA,IACF,WAAW,QAAQ,GAAG,GAAG;AACvB,YAAM;AAAA,IACR,OAAO;AACL,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAEA,eAAS;AACP,UAAI,EAAE,OAAO,YAAa,OAAM,IAAI,MAAM,gDAAgD;AAC1F,YAAM,KAAK,OAAO,KAAK;AACvB,UAAI,CAAC,GAAI;AACT,YAAM,KAAK,QAAQ,GAAG,IAAI;AAC1B,UAAI,OAAO,KAAM;AACjB,YAAM,CAAC,KAAK,GAAG,IAAI;AACnB,UAAI,MAAM,MAAO;AACjB;AACA,YAAM,MAAM,OAAO,GAAG;AACtB,YAAM,EAAE,MAAM,GAAG,MAAM,MAAM,KAAK,OAAO,IAAI;AAAA,IAC/C;AAEA,WAAO;AAAA,EACT;AAEA,SAAO,OAAO,CAAC;AACjB;AAMA,SAAS,oBAAoB,QAA8C;AACzE,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK;AAAA,IACL,KAAK;AACH,aAAO,EAAE,KAAK,GAAG,KAAK,EAAE;AAAA,IAC1B,KAAK,iBAAoB;AACvB,YAAM,IAAI,oBAAoB,OAAO,IAAI;AACzC,YAAM,IAAI,oBAAoB,OAAO,KAAK;AAC1C,aAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,KAAK,EAAE,MAAM,EAAE,IAAI;AAAA,IAClD;AAAA,IACA,KAAK,mBAAsB;AACzB,YAAM,IAAI,OAAO,OAAO,oBAAoB,OAAO,IAAI,IAAI,EAAE,KAAK,GAAG,KAAK,EAAE;AAC5E,YAAM,IAAI,oBAAoB,OAAO,KAAK;AAC1C,aAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,EAAE,IAAI;AAAA,IAC1C;AAAA,IACA,KAAK,YAAe;AAClB,YAAM,IAAI,oBAAoB,OAAO,IAAI;AACzC,YAAM,IAAI,oBAAoB,OAAO,KAAK;AAC1C,aAAO,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,KAAK,KAAK,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE;AAAA,IACpE;AAAA,IACA,KAAK;AACH,aAAO,EAAE,KAAK,GAAG,KAAK,SAAS;AAAA,EACnC;AACF;AAoBA,SAAS,UAAU,QAAqB,SAAiB,UAAkB,OAAO,GAAgB;AAChG,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,QAAQ,CAAC,EAAE,SAAS,SAAS,CAAC;AAAA,IAC9B,UAAU,CAAC;AAAA,EACb;AACF;AAEA,SAAS,YAAY,UAAkB,MAAc,WAA8B,CAAC,GAAgB;AAClG,SAAO,EAAE,QAAQ,iBAAqB,MAAM,UAAU,QAAQ,CAAC,GAAG,SAAS;AAC7E;AAEA,SAAS,OAAO,GAAyB;AACvC,SAAO,MAAM,mBAAuB,MAAM;AAC5C;AAMA,SAAS,cACP,QACAC,OACA,YACA,OACa;AACb,MAAI,OAAO;AAEX,WAAS,MAAM,KAAa,QAA6B;AACvD,QAAI,EAAE,OAAO,gBAAgB;AAC3B,YAAM,IAAI,MAAM,mDAAmD,MAAM,EAAE;AAAA,IAC7E;AAEA,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAK,mBAAsB;AACzB,YAAI,OAAO;AACX,YAAI,WAA8B,CAAC;AACnC,YAAI,MAAM;AAEV,YAAI,IAAI,MAAM;AACZ,gBAAM,OAAO,MAAM,IAAI,MAAM,GAAG;AAChC,cAAI,OAAO,KAAK,MAAM,EAAG,QAAO;AAChC,kBAAQ,KAAK;AACb,gBAAM,KAAK;AACX,qBAAW,KAAK;AAAA,QAClB;AAEA,cAAM,QAAQ,MAAM,IAAI,OAAO,GAAG;AAClC,YAAI,MAAM,WAAW,kBAAsB;AACzC,iBAAO,YAAY,KAAK,MAAM,QAAQ;AAAA,QACxC;AACA,YAAI,OAAO,MAAM,MAAM,GAAG;AACxB,gBAAM,SAAS;AACf,iBAAO;AAAA,QACT;AAEA,eAAO,YAAY,MAAM,UAAU,OAAO,MAAM,MAAM,SAAS,OAAO,MAAM,QAAQ,CAAC;AAAA,MACvF;AAAA,MAEA,KAAK,iBAAoB;AACvB,cAAM,OAAO,MAAM,IAAI,MAAM,MAAM;AACnC,YAAI,OAAO,KAAK,MAAM,EAAG,QAAO;AAEhC,cAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,QAAQ;AAC5C,YAAI,OAAO,MAAM,MAAM,EAAG,QAAO;AAEjC,eAAO;AAAA,UACL,MAAM;AAAA,UACN,KAAK,OAAO,MAAM;AAAA,UAClB,KAAK,SAAS,OAAO,MAAM,QAAQ;AAAA,QACrC;AAAA,MACF;AAAA,MAEA,KAAK,YAAe;AAClB,cAAM,OAAO,MAAM,IAAI,MAAM,MAAM;AACnC,YAAI,CAAC,OAAO,KAAK,MAAM,EAAG,QAAO;AAEjC,cAAM,QAAQ,MAAM,IAAI,OAAO,MAAM;AACrC,YAAI,CAAC,OAAO,MAAM,MAAM,EAAG,QAAO;AAGlC,eAAO;AAAA,MACT;AAAA,MAEA,KAAK,gBAAmB;AACtB,YAAI,OAAO;AACX,YAAI,WAA8B,CAAC;AACnC,YAAI,MAAM;AAEV,mBAAS;AACP,gBAAM,IAAI,MAAM,IAAI,OAAO,GAAG;AAC9B,cAAI,OAAO,EAAE,MAAM,EAAG;AACtB,gBAAM,EAAE;AACR,kBAAQ,EAAE;AACV,qBAAW,SAAS,OAAO,EAAE,QAAQ;AAAA,QACvC;AAEA,eAAO,YAAY,KAAK,MAAM,QAAQ;AAAA,MACxC;AAAA,MAEA,KAAK,iBAAoB;AACvB,cAAM,MAAMA,MAAK,MAAM;AACvB,YAAI,QAAQ,QAAW;AACrB,iBAAO,UAAU,kBAAsB,qBAAqB,IAAI,KAAK,2BAA2B,MAAM;AAAA,QACxG;AACA,YAAI,YAAY,GAAG,GAAG;AACpB,iBAAO,YAAY,SAAS,GAAG,YAAY;AAAA,QAC7C;AAGA,cAAM,UAAU,IAAI,0BAA0B,IAAI,KAAK,MAAM,GAAG,EAAE,IAAI,IAAI;AAC1E,YAAI,YAAY,IAAI,OAAO;AACzB,iBAAO,YAAY,SAAS,GAAG,YAAY;AAAA,QAC7C;AAEA,YACG,IAAI,UAAU,UAAU,IAAI,yBAC5B,IAAI,UAAU,eAAe,IAAI,+BACjC,IAAI,UAAU,UAAU,IAAI,4BAA4B,IAAI,SAAS,UACrE,IAAI,UAAU,WAAW,IAAI,4BAA4B,IAAI,SAAS,WACtE,IAAI,UAAU,SAAS,IAAI,sBAC5B;AACA,iBAAO,YAAY,SAAS,GAAG,YAAY;AAAA,QAC7C;AAEA,eAAO,UAAU,iBAAqB,qBAAqB,IAAI,KAAK,KAAK,QAAQ,iBAAiB;AAAA,MACpG;AAAA,MAEA,KAAK,cAAiB;AACpB,cAAM,MAAMA,MAAK,MAAM;AACvB,cAAM,UAAU,IAAI;AAEpB,YAAI,QAAQ,QAAW;AACrB,iBAAO;AAAA,YACL;AAAA,YACA,kBAAkB,QAAQ,KAAK,CAAC,CAAC;AAAA,YACjC;AAAA,UACF;AAAA,QACF;AAEA,YAAI,YAAY,GAAG,GAAG;AACpB,iBAAO,YAAY,SAAS,GAAG,YAAY;AAAA,QAC7C;AAEA,cAAM,SAAS,QAAQ,SAAS,KAAKA,OAAM,QAAQ,KAAK;AACxD,YAAI,kBAAkBC,YAAW;AAC/B,iBAAO;AAAA,YACL,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,UAAU;AAAA,YACV,QAAQ,CAAC,EAAE,SAAS,OAAO,SAAS,UAAU,OAAO,CAAC;AAAA,YACtD,UAAU,CAAC;AAAA,UACb;AAAA,QACF;AACA,YAAI,kBAAkB,aAAa;AACjC,iBAAO,YAAY,SAAS,GAAG,cAAc;AAAA,YAC3C,EAAE,SAAS,OAAO,SAAS,UAAU,OAAO;AAAA,UAC9C,CAAC;AAAA,QACH;AAEA,eAAO,YAAY,SAAS,GAAG,YAAY;AAAA,MAC7C;AAAA,IACF;AAAA,EACF;AAEA,SAAO,MAAM,QAAQ,UAAU;AACjC;AA/nBA,IAqDMA,YAIA,aAaA,gBAoLA,WACA,MACA,cACA,aACA,SACA,SAyFA,aAiJA,gBACA,mBACA,cA+JO;AA1oBb;AAAA;AAAA;AAkBA;AAmCA,IAAMA,aAAN,MAAgB;AAAA,MACd,YAAmB,SAAiB;AAAjB;AAAA,MAAkB;AAAA,IACvC;AAEA,IAAM,cAAN,MAAkB;AAAA,MAChB,YAAmB,SAAiB;AAAjB;AAAA,MAAkB;AAAA,IACvC;AAWA,IAAM,iBAAkC;AAAA,MACtC;AAAA,QACE,MAAM,CAAC,QAAQ,SAAS;AAAA,QACxB,SAAS,KAAK;AACZ,iBAAO,IAAI,2BAA2B,OAAO,IAAIA,WAAU,2BAA2B;AAAA,QACxF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,MAAM;AAAA,QACb,SAAS,KAAK;AACZ,iBAAO,IAAI,wBAAwB,OAAO,IAAIA,WAAU,wBAAwB;AAAA,QAClF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,WAAW;AAAA,QAClB,SAAS,KAAK;AACZ,iBAAO,IAAI,8BAA6B,OAAO,IAAIA,WAAU,6BAA6B;AAAA,QAC5F;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,QAAQ;AAAA,QACf,SAAS,KAAK;AACZ,iBAAO,IAAI,0BAA0B,OAAO,IAAIA,WAAU,0BAA0B;AAAA,QACtF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,KAAK;AAAA,QACZ,SAAS,KAAK;AACZ,iBAAO,IAAI,uBAAuB,OAAO,IAAIA,WAAU,uBAAuB;AAAA,QAChF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,MAAM;AAAA,QACb,SAAS,KAAK;AACZ,iBAAO,IAAI,wBAAwB,OAAO,IAAIA,WAAU,wBAAwB;AAAA,QAClF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,OAAO;AAAA,QACd,SAAS,KAAK;AACZ,iBAAO,IAAI,yBAAyB,OAAO,IAAIA,WAAU,0BAA0B;AAAA,QACrF;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,UAAU;AAAA,QACjB,SAAS,KAAK;AACZ,iBAAO,IAAI,4BAA4B,OAAO,IAAIA,WAAU,4BAA4B;AAAA,QAC1F;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,QAAQ;AAAA,QACf,SAAS,KAAK;AACZ,iBAAO,IAAI,0BAA0B,OAAO,IAAIA,WAAU,iCAAiC;AAAA,QAC7F;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,MAAM;AAAA,QACb,SAAS,KAAK;AACZ,gBAAM,IAAI,IAAI;AACd,cACE,0BACA,wBACA,yBACA,sBACA,qBACA,sBACA;AACA,mBAAO;AAAA,UACT;AACA,iBAAO,IAAIA,WAAU,sBAAsB;AAAA,QAC7C;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,KAAK;AAAA,QACZ,SAAS,KAAK;AACZ,iBAAO,IAAI,4BAA4B,OAAO,IAAIA,WAAU,4BAA4B;AAAA,QAC1F;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,CAAC,SAAS;AAAA,QAChB,SAAS,KAAK,OAAO,QAAQ,OAAO;AAElC,cAAI;AACJ,cAAI,IAAI,yBAAyB;AAE/B,0BAAc,IAAI,KAAK,MAAM,GAAG,EAAE;AAAA,UACpC,WAAW,IAAI,2BAA2B;AACxC,0BAAc,IAAI;AAAA,UACpB,WAAW,IAAI,yBAAyB;AACtC,0BAAc,IAAI;AAAA,UACpB,WAAW,IAAI,sBAAsB;AACnC,0BAAc;AAAA,UAChB;AAEA,cAAI,gBAAgB,QAAW;AAC7B,0BAAc,YAAY,QAAQ,OAAO,EAAE;AAC3C,gBAAI,SAAS,MAAM,SAAS,SAAS,GAAG;AACtC,kBAAI,CAAC,MAAM,SAAS,SAAS,WAAW,GAAG;AACzC,uBAAO,IAAI,YAAY,yBAAyB,WAAW,GAAG;AAAA,cAChE;AAAA,YACF;AACA,mBAAO;AAAA,UACT;AAEA,iBAAO,IAAIA,WAAU,uCAAuC;AAAA,QAC9D;AAAA,MACF;AAAA,IACF;AAyEA,IAAM,YAAY;AAClB,IAAM,OAAO;AACb,IAAM,eAAe;AACrB,IAAM,cAAc;AACpB,IAAM,UAAU;AAChB,IAAM,UAAU;AAyFhB,IAAM,cAAc;AAiJpB,IAAM,iBAAiB;AACvB,IAAM,oBAAoB;AAC1B,IAAM,eAAe;AA+Jd,IAAM,aAAN,MAAiB;AAAA,MACd;AAAA,MAER,YAAY,UAAoB;AAC9B,aAAK,WAAW,SAAS,IAAI,CAAC,OAAO;AAAA,UACnC,cAAc;AAAA,UACd,QAAQ,YAAY,CAAC;AAAA,QACvB,EAAE;AAAA,MACJ;AAAA;AAAA;AAAA;AAAA;AAAA,MAMA,SAASD,OAAa,WAAyC;AAE7D,YAAI,KAAK,SAAS,WAAW,GAAG;AAC9B,cAAIA,MAAK,WAAW,GAAG;AACrB,mBAAO,EAAE,cAAc,MAAM,QAAQ,CAAC,GAAG,UAAU,CAAC,EAAE;AAAA,UACxD;AACA,iBAAO;AAAA,YACL,cAAc;AAAA,YACd,QAAQ,CAAC,EAAE,SAAS,yBAAyB,UAAU,EAAE,CAAC;AAAA,YAC1D,UAAU,CAAC;AAAA,UACb;AAAA,QACF;AAEA,YAAI,YAA2B;AAC/B,YAAI,WAAW;AACf,YAAI,aAA8B,CAAC;AACnC,YAAI,eAAkC,CAAC;AACvC,YAAI,cAAc;AAElB,iBAAS,IAAI,GAAG,IAAI,KAAK,SAAS,QAAQ,KAAK;AAC7C,gBAAM,UAAU,KAAK,SAAS,CAAC;AAE/B,cAAI,QAAQ,WAAW,MAAM;AAE3B,gBAAIA,MAAK,WAAW,GAAG;AAErB,kBAAI,CAAC,eAAe,IAAI,UAAU;AAChC,4BAAY;AACZ,2BAAW;AACX,6BAAa,CAAC;AACd,+BAAe,CAAC;AAChB,8BAAc;AAAA,cAChB;AAAA,YACF,OAAO;AAEL,kBAAI,CAAC,eAAe,cAAc,MAAM;AACtC,4BAAY;AACZ,2BAAW;AACX,6BAAa,CAAC,EAAE,SAAS,yBAAyB,UAAU,EAAE,CAAC;AAC/D,+BAAe,CAAC;AAAA,cAClB;AAAA,YACF;AACA;AAAA,UACF;AAEA,gBAAM,SAAS,cAAc,QAAQ,QAAQA,OAAM,GAAG,SAAS;AAG/D,cAAI,SAAS,OAAO;AACpB,cAAI,OAAO,OAAO,WAAW,KAAK,OAAO,WAAWA,MAAK,QAAQ;AAC/D,qBAAS;AAAA,cACP;AAAA,gBACE,SAAS,gCAAgC,OAAO,QAAQ,SAASA,MAAK,MAAM;AAAA,gBAC5E,UAAU,OAAO;AAAA,cACnB;AAAA,YACF;AAAA,UACF;AAEA,gBAAM,OAAO,OAAO;AACpB,gBAAM,UAAU,OAAO,WAAW;AAElC,cAAI,YAAY,CAAC,eAAe,OAAO,WAAW;AAEhD,wBAAY;AACZ,uBAAW;AACX,yBAAa,CAAC;AACd,2BAAe,OAAO;AACtB,0BAAc;AAAA,UAChB,WAAW,CAAC,WAAW,CAAC,eAAe,OAAO,UAAU;AAEtD,wBAAY;AACZ,uBAAW;AACX,yBAAa;AACb,2BAAe,OAAO;AAAA,UACxB,WAAW,cAAc,MAAM;AAE7B,wBAAY;AACZ,uBAAW;AACX,yBAAa;AACb,2BAAe,OAAO;AACtB,0BAAc;AAAA,UAChB;AAAA,QACF;AAEA,eAAO;AAAA,UACL,cAAc;AAAA,UACd,QAAQ;AAAA,UACR,UAAU;AAAA,QACZ;AAAA,MACF;AAAA;AAAA;AAAA;AAAA,MAKA,gBAA8C;AAC5C,YAAI,MAAM;AACV,YAAI,MAAM;AAEV,mBAAW,WAAW,KAAK,UAAU;AACnC,cAAI,QAAQ,WAAW,MAAM;AAC3B,kBAAM;AAAA,UACR,OAAO;AACL,kBAAM,QAAQ,oBAAoB,QAAQ,MAAM;AAChD,kBAAM,KAAK,IAAI,KAAK,MAAM,GAAG;AAC7B,kBAAM,KAAK,IAAI,KAAK,MAAM,GAAG;AAAA,UAC/B;AAAA,QACF;AAEA,YAAI,QAAQ,SAAU,OAAM;AAC5B,eAAO,EAAE,KAAK,IAAI;AAAA,MACpB;AAAA;AAAA;AAAA;AAAA,MAKA,UAAmB;AACjB,YAAI,KAAK,SAAS,WAAW,EAAG,QAAO;AACvC,eAAO,CAAC,KAAK,SAAS,KAAK,CAAC,MAAM,EAAE,WAAW,IAAI;AAAA,MACrD;AAAA,IACF;AAAA;AAAA;;;AC5vBA,SAASE,iBAAgB,MAAwB;AAC/C,QAAM,SAAS,CAAC,CAAC;AACjB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,QAAI,KAAK,CAAC,MAAM,MAAM;AACpB,aAAO,KAAK,IAAI,CAAC;AAAA,IACnB;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAASC,kBAAiB,QAAgB,YAA2D;AACnG,MAAI,MAAM;AACV,MAAI,OAAO,WAAW,SAAS;AAC/B,SAAO,MAAM,MAAM;AACjB,UAAM,MAAO,MAAM,OAAO,KAAM;AAChC,QAAI,WAAW,GAAG,KAAK,QAAQ;AAC7B,YAAM;AAAA,IACR,OAAO;AACL,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACA,SAAO,EAAE,MAAM,KAAK,WAAW,SAAS,WAAW,GAAG,EAAE;AAC1D;AAYO,SAAS,WAAW,MAAc,aAAqB,GAAiB;AAC7E,QAAM,aAAaD,iBAAgB,IAAI;AACvC,QAAM,OAAqB,CAAC;AAE5B,YAAU,YAAY;AACtB,MAAI;AAEJ,UAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,UAAM,cAAc,MAAM,CAAC,EAAE,KAAK;AAClC,QAAI,CAAC,YAAa;AAGlB,UAAM,mBAAmB,MAAM,CAAC,EAAE,QAAQ,WAAW;AACrD,UAAM,YAAY,MAAM,QAAQ;AAChC,UAAM,UAAU,YAAY,YAAY;AAExC,UAAM,WAAWC,kBAAiB,WAAW,UAAU;AACvD,UAAM,SAASA,kBAAiB,SAAS,UAAU;AAEnD,UAAM,QAAe;AAAA,MACnB,OAAO,EAAE,MAAM,SAAS,OAAO,YAAY,WAAW,SAAS,UAAU;AAAA,MACzE,KAAK,EAAE,MAAM,OAAO,OAAO,YAAY,WAAW,OAAO,UAAU;AAAA,IACrE;AAEA,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAzFA,IAaM;AAbN;AAAA;AAAA;AAaA,IAAM,YAAY;AAAA;AAAA;;;ACUX,SAAS,mBAAmB,KAAa,WAAyC;AACvF,MAAI;AACF,UAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,QAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,UAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,QAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AAEnC,UAAM,cAA4B,CAAC;AAGnC,UAAM,SAAS,YAAY,IAAI;AAC/B,eAAW,QAAQ,CAAC,SAAS,UAAU,OAAO,QAAQ,IAAI,CAAC;AAG3D,UAAM,cAAc,UAAU,SAAS,eAAe;AACtD,UAAM,eAAe,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,IAAI,CAAC;AAKzD,QAAI;AACF,qBAAe,QAAQ,WAAW,WAAW;AAAA,IAC/C,QAAQ;AAAA,IAER;AAEA,QAAI;AACF,wBAAkB,QAAQ,WAAW,cAAc,WAAW;AAAA,IAChE,QAAQ;AAAA,IAER;AAEA,QAAI;AACF,wBAAkB,KAAK,WAAW,WAAW;AAAA,IAC/C,QAAQ;AAAA,IAER;AAEA,QAAI;AACF,oBAAc,MAAM,UAAU,cAAc,WAAW;AAAA,IACzD,QAAQ;AAAA,IAER;AAEA,QAAI;AACF,gCAA0B,QAAQ,WAAW,WAAW;AAAA,IAC1D,QAAQ;AAAA,IAER;AAEA,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO,CAAC;AAAA,EACV;AACF;AAMA,SAAS,eACP,QACA,WACA,aACM;AACN,WAAS,WAAW,GAAG,WAAW,OAAO,QAAQ,YAAY;AAC3D,UAAM,QAAQ,OAAO,QAAQ;AAC7B,UAAM,OAAO,UAAU,OAAO,SAAS,MAAM,IAAI;AAEjD,QAAI,MAAM;AAER,UAAI,KAAK,OAAO;AAEd,YAAI,MAAM,QAAQ,MAAM,SAAS,IAAI;AACnC,sBAAY,KAAK;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,sCAAsC,MAAM,IAAI;AAAA,UAClD,CAAC;AAAA,QACH,WAAW,CAAC,MAAM,QAAQ,MAAM,SAAS,IAAI;AAC3C,sBAAY,KAAK;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,qCAAqC,MAAM,IAAI;AAAA,UACjD,CAAC;AAAA,QACH;AAGA,YAAI,KAAK,YAAY,KAAK,SAAS,SAAS,KAAK,MAAM,QAAQ,MAAM,SAAS,IAAI;AAChF,2BAAiB,QAAQ,UAAU,OAAO,KAAK,UAAU,WAAW,WAAW;AAAA,QACjF;AAAA,MACF,OAAO;AAEL,YAAI,CAAC,MAAM,MAAM;AACf,sBAAY,KAAK;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,yBAAyB,MAAM,IAAI;AAAA,UACrC,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,KAAK,WAAW,KAAK,QAAQ,SAAS,KAAK,MAAM,MAAM;AACzD,YAAI,CAAC,eAAe,QAAQ,UAAU,KAAK,SAAS,SAAS,GAAG;AAC9D,gBAAM,aAAa,KAAK,QAAQ,KAAK,IAAI;AACzC,sBAAY,KAAK;AAAA,YACf,MAAM;AAAA,YACN,eAAe;AAAA,YACf,aAAa,MAAM,IAAI,yBAAyB,UAAU;AAAA,UAC5D,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,OAAO;AAEL,YAAM,SAAS,UAAU,QAAQ,UAAU,MAAM,IAAI;AACrD,UAAI,CAAC,UAAU,MAAM,MAAM;AAEzB,oBAAY,KAAK;AAAA,UACf,MAAM;AAAA,UACN,eAAe;AAAA,UACf,wBAAwB,MAAM,IAAI;AAAA,QACpC,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,eACP,QACA,OACA,SACA,WACS;AACT,QAAM,YAAY,IAAI,IAAI,QAAQ,IAAI,OAAK,EAAE,YAAY,CAAC,CAAC;AAG3D,WAAS,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK;AACnC,UAAM,YAAY,OAAO,CAAC;AAC1B,QAAI,CAAC,UAAU,KAAM;AAErB,UAAM,gBAAgB,UAAU,OAAO,SAAS,UAAU,IAAI;AAC9D,QAAI,CAAC,eAAe,MAAO;AAG3B,QAAI,UAAU,SAAS,MAAM,UAAU,OAAO,OAAO;AAEnD,UAAI,UAAU,IAAI,UAAU,KAAK,YAAY,CAAC,GAAG;AAC/C,eAAO;AAAA,MACT;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,iBACP,QACA,UACA,aACA,kBACA,WACA,aACM;AACN,QAAM,WAAmC,uBAAO,OAAO,IAAI;AAC3D,QAAM,aAAa,WAAW;AAC9B,QAAM,WAAW,YAAY;AAE7B,WAAS,IAAI,YAAY,IAAI,UAAU,KAAK;AAC1C,UAAM,QAAQ,OAAO,CAAC;AACtB,UAAM,YAAY,UAAU,OAAO,SAAS,MAAM,IAAI;AAEtD,QAAI,CAAC,UAAW;AAGhB,QAAI,UAAU,SAAS,MAAM,QAAQ,MAAM,SAAS,IAAI;AACtD,UAAI,MAAM;AACV;AAAA,IACF;AAGA,eAAW,cAAc,kBAAkB;AACzC,UAAI,WAAW,SAAS,MAAM,MAAM;AAClC,iBAAS,MAAM,IAAI,KAAK,SAAS,MAAM,IAAI,KAAK,KAAK;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AAGA,aAAW,cAAc,kBAAkB;AACzC,UAAM,QAAQ,SAAS,WAAW,IAAI,KAAK;AAE3C,QAAI,WAAW,QAAQ,UAAa,QAAQ,WAAW,KAAK;AAC1D,kBAAY,KAAK;AAAA,QACf,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,aAAa,WAAW,IAAI,SAAS,YAAY,IAAI,UAAU,WAAW,GAAG,WAAW,KAAK;AAAA,MAC/F,CAAC;AAAA,IACH;AAEA,QAAI,WAAW,QAAQ,UAAa,QAAQ,WAAW,KAAK;AAC1D,kBAAY,KAAK;AAAA,QACf,YAAY;AAAA,QACZ,eAAe;AAAA,QACf,YAAY,WAAW,IAAI,SAAS,YAAY,IAAI,UAAU,WAAW,GAAG,WAAW,KAAK;AAAA,MAC9F,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAMA,SAAS,kBACP,QACA,WACA,cACA,aACM;AACN,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,KAAM;AAEjB,UAAM,OAAO,UAAU,OAAO,SAAS,MAAM,IAAI;AACjD,QAAI,CAAC,KAAM;AACX,QAAI,KAAK,SAAU;AACnB,QAAI,CAAC,KAAK,WAAY;AAEtB,UAAM,UAAU,MAAM,WAAW;AACjC,UAAMC,QAAO,aAAa,OAAO;AAEjC,UAAM,SAAS,IAAI,WAAW,KAAK,UAAU;AAG7C,QAAI,OAAO,QAAQ,GAAG;AACpB,UAAIA,MAAK,SAAS,GAAG;AACnB,oBAAY,KAAK;AAAA,UACf,MAAM;AAAA,UACN,eAAe;AAAA,UACf,8BAA8B,MAAM,IAAI,UAAUA,MAAK,MAAM;AAAA,QAC/D,CAAC;AAAA,MACH;AACA;AAAA,IACF;AAEA,UAAM,YAAY,EAAE,UAAU,MAAM,KAAK,YAAY,EAAE;AACvD,UAAM,SAAS,OAAO,SAASA,OAAM,SAAS;AAE9C,QAAI,OAAO,iBAAiB,MAAM;AAEhC;AAAA,IACF;AAGA,eAAW,SAAS,OAAO,QAAQ;AAEjC,UAAI,MAAM,QAAQ,WAAW,oBAAoB,GAAG;AAClD,oBAAY,KAAK;AAAA,UACf,MAAM;AAAA,UACN,eAAe;AAAA,UACf,IAAI,MAAM,IAAI,MAAM,MAAM,OAAO;AAAA,QACnC,CAAC;AAAA,MACH,OAAO;AACL,oBAAY,KAAK;AAAA,UACf,MAAM;AAAA,UACN,eAAe;AAAA,UACf,IAAI,MAAM,IAAI,MAAM,MAAM,OAAO;AAAA,QACnC,CAAC;AAAA,MACH;AAAA,IACF;AAGA,eAAW,WAAW,OAAO,UAAU;AACrC,kBAAY,KAAK;AAAA,QACf,MAAM;AAAA,QACN,eAAe;AAAA,QACf,IAAI,MAAM,IAAI,MAAM,QAAQ,OAAO;AAAA,MACrC,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAMA,SAAS,kBACP,KACA,WACA,aACM;AACN,MAAI,CAAC,UAAU,UAAU,kBAAkB,GAAG;AAG5C,UAAMC,cAAa,UAAU,UAAU,cAAc,GAAG;AAGxD,UAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,QAAI,QAAQ,eAAe,KAAK,IAAI,GAAG;AAErC,YAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,YAAM,cAAc,SAAS,KAAK,OAAK;AACrC,cAAM,WAAW,oBAAI,IAAI,CAAC,kBAAkB,aAAa,aAAa,eAAe,gBAAgB,CAAC;AACtG,eAAO,CAAC,SAAS,IAAI,EAAE,IAAI,KAAK,CAAC,EAAE,MAAM,SAAS,QAAQ,KAAK,CAAC,EAAE,MAAM,SAAS,YAAY;AAAA,MAC/F,CAAC;AACD,UAAI,aAAa;AACf,oBAAY,KAAK;AAAA,UACf,SAAS,CAAC,EAAE;AAAA,UACZ,eAAe;AAAA,UACf;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AACA;AAAA,EACF;AAGA,QAAM,aAAa,UAAU,UAAU,cAAc,GAAG;AACxD,aAAW,KAAK,YAAY;AAC1B,gBAAY,KAAK;AAAA,MACf,EAAE;AAAA,MACF,eAAe;AAAA,MACf,cAAc,EAAE,IAAI;AAAA,IACtB,CAAC;AAAA,EACH;AACF;AAMA,SAAS,cACP,MACA,UACA,cACA,aACM;AACN,QAAM,QAAQ,WAAW,IAAI;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,CAAC,aAAa,IAAI,KAAK,IAAI,GAAG;AAChC,kBAAY,KAAK;AAAA,QACf,KAAK;AAAA,QACL,eAAe;AAAA,QACf,YAAY,KAAK,IAAI;AAAA,MACvB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAMA,SAAS,0BACP,QACA,WACA,aACM;AACN,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,KAAM;AAGjB,UAAM,OAAO,UAAU,OAAO,SAAS,MAAM,IAAI;AACjD,QAAI,KAAM;AAEV,UAAM,SAAS,UAAU,QAAQ,UAAU,MAAM,IAAI;AACrD,QAAI,CAAC,OAAQ;AAGb,UAAM,UAAU,MAAM,WAAW;AACjC,UAAM,WAAW,QAAQ,KAAK,MAAM,KAAK,IAAI,aAAa,OAAO,EAAE;AACnE,UAAM,gBAAgB,OAAO,OAAO;AAEpC,QAAI,aAAa,eAAe;AAC9B,kBAAY,KAAK;AAAA,QACf,MAAM;AAAA,QACN,eAAe;AAAA,QACf,WAAW,MAAM,IAAI,aAAa,aAAa,qBAAqB,QAAQ;AAAA,MAC9E,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAMA,SAAS,SACP,OACA,MACA,SACY;AACZ,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,YAAY,IAAI;AAAA,IAC1B;AAAA,IACA,QAAQ;AAAA,EACV;AACF;AAMA,SAAS,gBAAgB,GAA2D;AAClF,QAAMC,eAAc;AAAA,IAClB,OAAO;AAAA,IACP,SAAS;AAAA,IACT,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAEA,SAAO;AAAA,IACL,OAAO;AAAA,MACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,MAAM,WAAW,EAAE,MAAM,MAAM,UAAU;AAAA,MACtE,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM,WAAW,EAAE,MAAM,IAAI,UAAU;AAAA,IAClE;AAAA,IACA,UAAUA,aAAY,EAAE,QAAQ;AAAA,IAChC,MAAM,EAAE;AAAA,IACR,QAAQ,EAAE;AAAA,IACV,SAAS,EAAE;AAAA,EACb;AACF;AAvcA,IAyca;AAzcb;AAAA;AAAA;AAGA;AAEA;AACA;AACA;AACA;AAicO,IAAM,oBAAmC;AAAA,MAC9C,IAAI;AAAA,MACJ,cAAc,CAAC;AAAA,MACf,WAAW,KAAoB;AAC7B,cAAM,qBAAqB,MAAM;AAC/B,qBAAW,OAAO,IAAI,UAAU,UAAU,QAAQ,GAAG;AACnD,kBAAM,QAAQ,mBAAmB,KAAK,IAAI,SAAS;AACnD,gBAAI,WAAW,gBAAgB;AAAA,cAC7B;AAAA,cACA,aAAa,MAAM,IAAI,OAAK,gBAAgB,CAAC,CAAC;AAAA,YAChD,CAAC;AAAA,UACH;AAAA,QACF;AAEA,YAAI,UAAU,GAAG,cAAc,kBAAkB;AACjD,YAAI,UAAU,GAAG,mBAAmB,CAAC,QAAgB;AACnD,gBAAM,QAAQ,mBAAmB,KAAK,IAAI,SAAS;AACnD,cAAI,WAAW,gBAAgB;AAAA,YAC7B;AAAA,YACA,aAAa,MAAM,IAAI,OAAK,gBAAgB,CAAC,CAAC;AAAA,UAChD,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACheA,SAAS,gBAAAC,eAAc,cAAAC,mBAAkB;AACzC,SAAS,QAAAC,aAAY;AACrB,SAAS,SAAS,iBAAiB;AAqB5B,SAAS,YACd,SACA,QACsB;AACtB,MAAI,CAAC,QAAQ,KAAK,GAAG;AACnB,WAAO,EAAE,QAAQ,CAAC,EAAE;AAAA,EACtB;AAEA,MAAI;AACJ,MAAI,WAAW,QAAQ;AACrB,UAAM,KAAK,MAAM,OAAO;AAAA,EAC1B,OAAO;AACL,UAAM,UAAU,OAAO;AAAA,EACzB;AAEA,MAAI,OAAO,QAAQ,YAAY,QAAQ,MAAM;AAC3C,WAAO,EAAE,QAAQ,CAAC,EAAE;AAAA,EACtB;AAEA,QAAM,MAAM;AACZ,SAAO;AAAA,IACL,QAAS,OAAO,IAAI,WAAW,YAAY,IAAI,WAAW,OACtD,IAAI,SACJ,CAAC;AAAA,EACP;AACF;AAOO,SAAS,eAAe,eAAsC;AACnE,aAAW,QAAQ,kBAAkB;AACnC,UAAM,WAAWA,MAAK,eAAe,IAAI;AACzC,QAAID,YAAW,QAAQ,GAAG;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAMO,SAAS,mBAAmB,eAA6C;AAC9E,QAAM,aAAa,eAAe,aAAa;AAC/C,MAAI,CAAC,YAAY;AACf,WAAO,EAAE,GAAG,aAAa;AAAA,EAC3B;AAEA,QAAM,UAAUD,cAAa,YAAY,OAAO;AAChD,QAAM,SAAS,WAAW,SAAS,OAAO,IAAI,SAAS;AACvD,SAAO,YAAY,SAAS,MAAM;AACpC;AA9EA,IAWM,kBAMA;AAjBN;AAAA;AAAA;AAWA,IAAM,mBAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,IAAM,eAAqC,EAAE,QAAQ,CAAC,EAAE;AAAA;AAAA;;;ACjBxD,SAAS,iBAAAG,sBAAqB;AAgCvB,SAAS,aACd,SACQ;AACR,MAAI,QAAQ,WAAW,GAAG;AACxB,WAAO,GAAG,OAAO,IAAI,oBAAoB,OAAO,KAAK;AAAA,EACvD;AAEA,QAAM,QAAkB,CAAC;AACzB,MAAI,aAAa;AACjB,MAAI,eAAe;AACnB,MAAI,YAAY;AAChB,MAAI,YAAY;AAEhB,aAAW,EAAE,KAAK,YAAY,KAAK,SAAS;AAC1C,QAAI;AACJ,QAAI;AACF,iBAAWA,eAAc,GAAG;AAAA,IAC9B,QAAQ;AACN,iBAAW;AAAA,IACb;AAEA,eAAW,QAAQ,aAAa;AAC9B,YAAM,OAAO,KAAK,MAAM,MAAM,OAAO;AACrC,YAAM,MAAM,KAAK,MAAM,MAAM,YAAY;AACzC,YAAM,QAAQ,eAAe,KAAK,QAAQ,KAAK,OAAO;AAEtD,YAAM;AAAA,QACJ,GAAG,OAAO,IAAI,GAAG,QAAQ,IAAI,IAAI,IAAI,GAAG,GAAG,OAAO,KAAK,IACpD,KAAK,GAAG,KAAK,QAAQ,GAAG,OAAO,KAAK,IACpC,OAAO,IAAI,GAAG,KAAK,IAAI,GAAG,OAAO,KAAK,IACtC,KAAK,OAAO;AAAA,MACjB;AAEA,cAAQ,KAAK,UAAU;AAAA,QACrB,KAAK;AAAS;AAAc;AAAA,QAC5B,KAAK;AAAW;AAAgB;AAAA,QAChC,KAAK;AAAQ;AAAa;AAAA,QAC1B,KAAK;AAAQ;AAAa;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAQ,aAAa,eAAe,YAAY;AACtD,QAAM,QAAkB,CAAC;AACzB,MAAI,aAAa,EAAG,OAAM,KAAK,GAAG,UAAU,SAAS,eAAe,IAAI,MAAM,EAAE,EAAE;AAClF,MAAI,eAAe,EAAG,OAAM,KAAK,GAAG,YAAY,WAAW,iBAAiB,IAAI,MAAM,EAAE,EAAE;AAC1F,MAAI,YAAY,EAAG,OAAM,KAAK,GAAG,SAAS,OAAO;AACjD,MAAI,YAAY,EAAG,OAAM,KAAK,GAAG,SAAS,QAAQ,cAAc,IAAI,MAAM,EAAE,EAAE;AAE9E,QAAM,KAAK,EAAE;AACb,QAAM;AAAA,IACJ,GAAG,OAAO,IAAI,SAAS,KAAK,WAAW,UAAU,IAAI,MAAM,EAAE,KAAK,MAAM,KAAK,IAAI,CAAC,IAAI,OAAO,KAAK;AAAA,EACpG;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAvFA,IAMM,QAUA;AAhBN;AAAA;AAAA;AAMA,IAAM,SAAS;AAAA,MACb,KAAK;AAAA,MACL,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,MAAM;AAAA,MACN,MAAM;AAAA,MACN,OAAO;AAAA,MACP,MAAM;AAAA,IACR;AAEA,IAAM,iBAAyC;AAAA,MAC7C,OAAO,OAAO;AAAA,MACd,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,IACf;AAAA;AAAA;;;ACIO,SAAS,WACd,SACQ;AACR,QAAM,SAAS;AAAA,IACb,OAAO,QAAQ,IAAI,CAAC,EAAE,KAAK,YAAY,OAAO;AAAA,MAC5C;AAAA,MACA,aAAa,YAAY,IAAI,QAAM;AAAA,QACjC,OAAO,EAAE;AAAA,QACT,SAAS,EAAE;AAAA,QACX,UAAU,EAAE;AAAA,QACZ,MAAM,EAAE;AAAA,QACR,QAAQ,EAAE;AAAA,MACZ,EAAE;AAAA,IACJ,EAAE;AAAA,EACJ;AAEA,SAAO,KAAK,UAAU,QAAQ,MAAM,CAAC;AACvC;AA1CA;AAAA;AAAA;AAAA;AAAA;;;ACiBO,SAAS,YACd,SACQ;AAER,QAAM,UAAU,oBAAI,IAAY;AAChC,aAAW,EAAE,YAAY,KAAK,SAAS;AACrC,eAAW,KAAK,aAAa;AAC3B,cAAQ,IAAI,EAAE,IAAI;AAAA,IACpB;AAAA,EACF;AAGA,QAAM,eAAe,CAAC;AACtB,aAAW,EAAE,KAAK,YAAY,KAAK,SAAS;AAC1C,eAAW,KAAK,aAAa;AAC3B,mBAAa,KAAK;AAAA,QAChB,QAAQ,EAAE;AAAA,QACV,OAAO,cAAc,EAAE,QAAQ,KAAK;AAAA,QACpC,SAAS,EAAE,MAAM,EAAE,QAAQ;AAAA,QAC3B,WAAW;AAAA,UACT;AAAA,YACE,kBAAkB;AAAA,cAChB,kBAAkB,EAAE,IAAI;AAAA,cACxB,QAAQ;AAAA,gBACN,WAAW,EAAE,MAAM,MAAM,OAAO;AAAA,gBAChC,aAAa,EAAE,MAAM,MAAM,YAAY;AAAA,gBACvC,SAAS,EAAE,MAAM,IAAI,OAAO;AAAA,gBAC5B,WAAW,EAAE,MAAM,IAAI,YAAY;AAAA,cACrC;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,QAAM,QAAQ;AAAA,IACZ,SAAS;AAAA,IACT,SAAS;AAAA,IACT,MAAM;AAAA,MACJ;AAAA,QACE,MAAM;AAAA,UACJ,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,SAAS;AAAA,YACT,OAAO,MAAM,KAAK,OAAO,EAAE,IAAI,SAAO;AAAA,cACpC;AAAA,cACA,kBAAkB,EAAE,MAAM,sBAAsB,EAAE,GAAG;AAAA,YACvD,EAAE;AAAA,UACJ;AAAA,QACF;AAAA,QACA,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO,KAAK,UAAU,OAAO,MAAM,CAAC;AACtC;AA1EA,IAKM;AALN;AAAA;AAAA;AAKA,IAAM,gBAAwC;AAAA,MAC5C,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,MAAM;AAAA,IACR;AAAA;AAAA;;;ACVA;AAAA;AAAA;AAAA;AAAA,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,iBAAAC,sBAAqB;AAC9B,SAAS,YAAY;AAqBrB,SAAS,UAAUC,OAA8B;AAC/C,QAAM,UAAwB;AAAA,IAC5B,QAAQ;AAAA,IACR,UAAU;AAAA,IACV,YAAY;AAAA,IACZ,UAAU,CAAC;AAAA,EACb;AAEA,MAAI,IAAI;AACR,SAAO,IAAIA,MAAK,QAAQ;AACtB,UAAM,MAAMA,MAAK,CAAC;AAElB,QAAI,QAAQ,cAAc,IAAI,IAAIA,MAAK,QAAQ;AAC7C,YAAM,MAAMA,MAAK,IAAI,CAAC;AACtB,UAAI,QAAQ,YAAY,QAAQ,UAAU,QAAQ,SAAS;AACzD,gBAAQ,SAAS;AAAA,MACnB;AACA,WAAK;AAAA,IACP,WAAW,IAAI,WAAW,WAAW,GAAG;AACtC,YAAM,MAAM,IAAI,MAAM,YAAY,MAAM;AACxC,UAAI,QAAQ,YAAY,QAAQ,UAAU,QAAQ,SAAS;AACzD,gBAAQ,SAAS;AAAA,MACnB;AACA;AAAA,IACF,WAAW,QAAQ,gBAAgB,IAAI,IAAIA,MAAK,QAAQ;AACtD,YAAM,MAAMA,MAAK,IAAI,CAAC;AACtB,UAAI,QAAQ,WAAW,QAAQ,aAAa,QAAQ,UAAU,QAAQ,QAAQ;AAC5E,gBAAQ,WAAW;AAAA,MACrB;AACA,WAAK;AAAA,IACP,WAAW,IAAI,WAAW,aAAa,GAAG;AACxC,YAAM,MAAM,IAAI,MAAM,cAAc,MAAM;AAC1C,UAAI,QAAQ,WAAW,QAAQ,aAAa,QAAQ,UAAU,QAAQ,QAAQ;AAC5E,gBAAQ,WAAW;AAAA,MACrB;AACA;AAAA,IACF,WAAW,QAAQ,cAAc,IAAI,IAAIA,MAAK,QAAQ;AACpD,cAAQ,aAAaA,MAAK,IAAI,CAAC;AAC/B,WAAK;AAAA,IACP,WAAW,IAAI,WAAW,WAAW,GAAG;AACtC,cAAQ,aAAa,IAAI,MAAM,YAAY,MAAM;AACjD;AAAA,IACF,WAAW,CAAC,IAAI,WAAW,IAAI,GAAG;AAChC,cAAQ,SAAS,KAAK,GAAG;AACzB;AAAA,IACF,OAAO;AAEL;AAAA,IACF;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,YAAQ,WAAW,CAAC,gBAAgB;AAAA,EACtC;AAEA,SAAO;AACT;AAQA,SAAS,iBACP,aACA,aACc;AACd,QAAM,SAAS,eAAe,QAAQ,WAAW;AACjD,SAAO,YAAY,OAAO,OAAK;AAC7B,UAAM,MAAM,eAAe,QAAQ,EAAE,QAAQ;AAC7C,WAAO,OAAO;AAAA,EAChB,CAAC;AACH;AAMA,eAAsB,SAASA,OAAiC;AAC9D,QAAM,UAAU,UAAUA,KAAI;AAG9B,QAAM,MAAM,QAAQ,IAAI;AAGxB,QAAM,QAAkB,CAAC;AACzB,aAAW,WAAW,QAAQ,UAAU;AACtC,UAAM,UAAU,MAAM,KAAK,SAAS;AAAA,MAClC;AAAA,MACA,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,UAAM,KAAK,GAAG,OAAO;AAAA,EACvB;AAGA,QAAM,cAAc,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAEtC,MAAI,YAAY,WAAW,GAAG;AAC5B,QAAI,QAAQ,WAAW,UAAU;AAC/B,cAAQ,IAAI,gBAAgB;AAAA,IAC9B,WAAW,QAAQ,WAAW,QAAQ;AACpC,cAAQ,IAAI,KAAK,UAAU,EAAE,OAAO,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC;AAAA,IACpD,OAAO;AACL,cAAQ,IAAI,YAAY,CAAC,CAAC,CAAC;AAAA,IAC7B;AACA,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,QAAQ,aACvB,QAAQ,KAAK,QAAQ,YAAY,IAAI,IACrC;AACJ,QAAM,gBAAgB,mBAAmB,UAAU;AAGnD,QAAM,YAAY,IAAI,eAAe;AACrC,QAAM,eAAe,oBAAI,IAAoB;AAC7C,aAAW,YAAY,aAAa;AAClC,QAAI;AACF,YAAM,OAAOF,cAAa,UAAU,OAAO;AAC3C,YAAM,MAAMC,eAAc,QAAQ,EAAE,SAAS;AAC7C,mBAAa,IAAI,KAAK,IAAI;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,YAAU,WAAW,YAAY;AAGjC,MAAI,OAAO,KAAK,cAAc,MAAM,EAAE,SAAS,GAAG;AAChD,cAAU,OAAO,gBAAgB,cAAc,MAAM;AAAA,EACvD;AAGA,QAAM,aAAgE,CAAC;AACvE,MAAI,YAAY;AAEhB,aAAW,OAAO,aAAa,KAAK,GAAG;AACrC,QAAI,QAAQ,mBAAmB,KAAK,SAAS;AAG7C,QAAI,QAAQ,UAAU;AACpB,cAAQ,iBAAiB,OAAO,QAAQ,QAAQ;AAAA,IAClD;AAEA,QAAI,MAAM,SAAS,GAAG;AACpB,iBAAW,KAAK,EAAE,KAAK,aAAa,MAAM,CAAC;AAC3C,UAAI,MAAM,KAAK,OAAK,EAAE,aAAa,OAAO,GAAG;AAC3C,oBAAY;AAAA,MACd;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,QAAQ,QAAQ;AAAA,IACtB,KAAK;AACH,cAAQ,IAAI,aAAa,UAAU,CAAC;AACpC;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,WAAW,UAAU,CAAC;AAClC;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,YAAY,UAAU,CAAC;AACnC;AAAA,EACJ;AAGA,YAAU,QAAQ;AAElB,SAAO,YAAY,IAAI;AACzB;AApMA,IAsFM;AAtFN;AAAA;AAAA;AAKA;AACA;AACA;AAEA;AACA;AACA;AA2EA,IAAM,iBAAiB,CAAC,QAAQ,QAAQ,WAAW,OAAO;AAAA;AAAA;;;AClDnD,SAAS,eAAe,MAAsB;AACnD,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,SAAmB,CAAC;AAC1B,MAAI,cAAc;AAElB,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,QAAI,OAAO,MAAM,CAAC;AAGlB,WAAO,KAAK,QAAQ,QAAQ,EAAE;AAG9B,QAAI,qBAAqB,KAAK,IAAI,GAAG;AACnC,aAAO,uBAAuB,IAAI;AAElC,oBAAc;AACd,aAAO,KAAK,IAAI;AAChB;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,KAAK;AAG1B,QAAI,YAAY,IAAI;AAClB,aAAO,KAAK,EAAE;AACd;AAAA,IACF;AAGA,QAAI,kBAAkB,KAAK,OAAO,GAAG;AACnC,oBAAc,KAAK,IAAI,GAAG,cAAc,CAAC;AAAA,IAC3C;AAGA,UAAM,WAAW,cAAc,IAC3B,KAAK,OAAO,WAAW,IAAI,UAC3B;AACJ,WAAO,KAAK,QAAQ;AAGpB,QAAI,iBAAiB,KAAK,OAAO,GAAG;AAClC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,SAAS,OAAO,KAAK,IAAI;AAC7B,WAAS,OAAO,QAAQ,QAAQ,IAAI;AAEpC,SAAO;AACT;AAMO,SAAS,YAAY,MAAc,OAAsB;AAC9D,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,YAAY,KAAK,IAAI,GAAG,MAAM,MAAM,IAAI;AAC9C,QAAM,UAAU,KAAK,IAAI,MAAM,SAAS,GAAG,MAAM,IAAI,IAAI;AAGzD,QAAM,aAAa,MAAM,MAAM,WAAW,UAAU,CAAC;AACrD,QAAM,YAAY,WAAW,KAAK,IAAI;AAGtC,QAAM,YAAY,eAAe,SAAS;AAC1C,QAAM,iBAAiB,UAAU,QAAQ,OAAO,EAAE,EAAE,MAAM,IAAI;AAG9D,QAAM,SAAS,MAAM,MAAM,GAAG,SAAS;AACvC,QAAM,QAAQ,MAAM,MAAM,UAAU,CAAC;AACrC,QAAM,SAAS,CAAC,GAAG,QAAQ,GAAG,gBAAgB,GAAG,KAAK,EAAE,KAAK,IAAI;AAEjE,SAAO;AACT;AAUA,SAAS,uBAAuB,MAAsB;AAEpD,QAAM,cAAc,KAAK,MAAM,YAAY;AAC3C,MAAI,CAAC,YAAa,QAAO;AAEzB,QAAM,OAAO,YAAY,CAAC;AAG1B,QAAM,aAAa,KAAK,QAAQ,GAAG;AACnC,QAAM,WAAW,KAAK,QAAQ,GAAG;AAEjC,MAAI;AACJ,MAAI,SAAS;AAEb,MAAI,eAAe,OAAO,aAAa,MAAM,aAAa,WAAW;AACnE,WAAO,KAAK,UAAU,GAAG,UAAU,EAAE,KAAK;AAC1C,aAAS,MAAM,KAAK,UAAU,UAAU,EAAE,KAAK;AAAA,EACjD,WAAW,aAAa,IAAI;AAC1B,WAAO,KAAK,UAAU,GAAG,QAAQ,EAAE,KAAK;AACxC,aAAS,MAAM,KAAK,UAAU,QAAQ,EAAE,KAAK;AAAA,EAC/C,OAAO;AACL,WAAO,KAAK,KAAK;AAAA,EACnB;AAEA,SAAO,MAAM,IAAI,GAAG,MAAM;AAC5B;AAlJA,IAWM,kBAKA,mBAKA,sBAmIO;AAxJb;AAAA;AAAA;AAWA,IAAM,mBAAmB;AAKzB,IAAM,oBAAoB;AAK1B,IAAM,uBAAuB;AAmItB,IAAM,eAA8B;AAAA,MACzC,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,4BAA4B;AAAA,QAC5B,iCAAiC;AAAA,MACnC;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,qBAAqB,CAAC,WAAW;AAC9C,gBAAM,OAAO,IAAI,UAAU,UAAU,QAAQ,OAAO,aAAa,GAAG;AACpE,cAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,gBAAM,YAAY,eAAe,IAAI;AACrC,cAAI,cAAc,KAAM,QAAO,CAAC;AAEhC,gBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,iBAAO,CAAC;AAAA,YACN,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;AAAA,cAC/B,KAAK,EAAE,MAAM,MAAM,SAAS,GAAG,WAAW,MAAM,MAAM,SAAS,CAAC,EAAE,OAAO;AAAA,YAC3E;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,QACH,CAAC;AAED,YAAI,WAAW,0BAA0B,CAAC,WAAW;AACnD,gBAAM,OAAO,IAAI,UAAU,UAAU,QAAQ,OAAO,aAAa,GAAG;AACpE,cAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,gBAAM,QAAe;AAAA,YACnB,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,OAAO,MAAM,MAAM,UAAU;AAAA,YAChF,KAAK,EAAE,MAAM,OAAO,MAAM,IAAI,MAAM,WAAW,OAAO,MAAM,IAAI,UAAU;AAAA,UAC5E;AAEA,gBAAM,YAAY,YAAY,MAAM,KAAK;AACzC,cAAI,cAAc,KAAM,QAAO,CAAC;AAEhC,gBAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,iBAAO,CAAC;AAAA,YACN,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;AAAA,cAC/B,KAAK,EAAE,MAAM,MAAM,SAAS,GAAG,WAAW,MAAM,MAAM,SAAS,CAAC,EAAE,OAAO;AAAA,YAC3E;AAAA,YACA,SAAS;AAAA,UACX,CAAC;AAAA,QACH,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACtMA;AAAA;AAAA;AAAA;AAAA,SAAS,gBAAAE,eAAc,qBAAqB;AAE5C,SAAS,QAAAC,aAAY;AAarB,SAASC,WAAUC,OAA+B;AAChD,QAAM,UAAyB;AAAA,IAC7B,OAAO;AAAA,IACP,UAAU,CAAC;AAAA,EACb;AAEA,aAAW,OAAOA,OAAM;AACtB,QAAI,QAAQ,WAAW;AACrB,cAAQ,QAAQ;AAAA,IAClB,WAAW,CAAC,IAAI,WAAW,IAAI,GAAG;AAChC,cAAQ,SAAS,KAAK,GAAG;AAAA,IAC3B;AAAA,EACF;AAEA,MAAI,QAAQ,SAAS,WAAW,GAAG;AACjC,YAAQ,WAAW,CAAC,gBAAgB;AAAA,EACtC;AAEA,SAAO;AACT;AAMA,eAAsB,UAAUA,OAAiC;AAC/D,QAAM,UAAUD,WAAUC,KAAI;AAC9B,QAAM,MAAM,QAAQ,IAAI;AAGxB,QAAM,QAAkB,CAAC;AACzB,aAAW,WAAW,QAAQ,UAAU;AACtC,UAAM,UAAU,MAAMF,MAAK,SAAS;AAAA,MAClC;AAAA,MACA,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,UAAM,KAAK,GAAG,OAAO;AAAA,EACvB;AAEA,QAAM,cAAc,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC;AAEtC,MAAI,YAAY,WAAW,GAAG;AAC5B,YAAQ,IAAI,gBAAgB;AAC5B,WAAO;AAAA,EACT;AAEA,QAAM,cAAwB,CAAC;AAE/B,aAAW,YAAY,aAAa;AAClC,QAAI;AACF,YAAM,OAAOD,cAAa,UAAU,OAAO;AAC3C,YAAM,YAAY,eAAe,IAAI;AAErC,UAAI,cAAc,MAAM;AACtB,YAAI,QAAQ,OAAO;AACjB,gBAAM,WAAW,SAAS,WAAW,GAAG,IACpC,SAAS,MAAM,IAAI,SAAS,CAAC,IAC7B;AACJ,sBAAY,KAAK,QAAQ;AAAA,QAC3B,OAAO;AACL,wBAAc,UAAU,WAAW,OAAO;AAAA,QAC5C;AAAA,MACF;AAAA,IACF,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,MAAI,QAAQ,OAAO;AACjB,QAAI,YAAY,SAAS,GAAG;AAC1B,iBAAW,QAAQ,aAAa;AAC9B,gBAAQ,IAAI,IAAI;AAAA,MAClB;AACA,cAAQ,IAAI;AAAA,EAAK,YAAY,MAAM,QAAQ,YAAY,WAAW,IAAI,MAAM,EAAE,uBAAuB;AACrG,aAAO;AAAA,IACT;AACA,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAhGA,IAAAI,eAAA;AAAA;AAAA;AAIA;AAAA;AAAA;;;ACGO,SAAS,YACdC,aACA,QACiB;AACjB,QAAM,WAAW,IAAI,IAAI,OAAO,mBAAmB,CAAC,CAAC;AACrD,SAAOA,YAAW,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;AACrD;AAQO,SAAS,kBACd,SAC6B;AAC7B,QAAM,SAAkC,CAAC;AAEzC,aAAW,UAAU,SAAS;AAC5B,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,YAAY,GAAG;AAC9D,YAAM,WAAW,OAAO,GAAG;AAC3B,UAAI,aAAa,QAAW;AAC1B,eAAO,GAAG,IAAI;AAAA,MAChB,WACE,OAAO,aAAa,YACpB,aAAa,QACb,OAAO,UAAU,YACjB,UAAU,QACV,CAAC,MAAM,QAAQ,QAAQ,KACvB,CAAC,MAAM,QAAQ,KAAK,GACpB;AAEA,eAAO,GAAG,IAAI,EAAE,GAAI,UAAsC,GAAI,MAAkC;AAAA,MAClG,OAAO;AAEL,eAAO,GAAG,IAAI;AAAA,MAChB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAjDA;AAAA;AAAA;AAAA;AAAA;;;ACAA,SAAS,4BAA4B;AAS9B,SAAS,kBACd,SACoB;AACpB,QAAM,aAAa,kBAAkB,OAAO;AAC5C,SAAO;AAAA,IACL,kBAAkB,qBAAqB;AAAA,IACvC,GAAG;AAAA,EACL;AACF;AAjBA;AAAA;AAAA;AAGA;AAAA;AAAA;;;ACmBO,SAAS,eACd,KACA,UACA,aACA,WACkB;AAClB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO,CAAC;AAC3C,QAAM,WAAW,MAAM,SAAS,IAAI,EAAE,UAAU,GAAG,SAAS,SAAS;AAGrE,MAAI,oBAAoB,KAAK,QAAQ,GAAG;AACtC,WAAO,2BAA2B,MAAM,UAAU,SAAS;AAAA,EAC7D;AAGA,QAAM,eAAe,6CAA6C,KAAK,QAAQ;AAC/E,MAAI,cAAc;AAChB,WAAO,sBAAsB,aAAa,CAAC,GAAG,SAAS;AAAA,EACzD;AAGA,MAAI,uBAAuB,KAAK,QAAQ,KAAK,CAAC,uBAAuB,KAAK,QAAQ,GAAG;AACnF,WAAO,4BAA4B,SAAS;AAAA,EAC9C;AAGA,MAAI,sBAAsB,KAAK,QAAQ,GAAG;AACxC,WAAO,2BAA2B,IAAI;AAAA,EACxC;AAGA,MAAI,sBAAsB,KAAK,QAAQ,GAAG;AACxC,WAAO,4BAA4B,IAAI;AAAA,EACzC;AAGA,MAAI,cAAc,KAAK,QAAQ,GAAG;AAChC,WAAO,0BAA0B,SAAS;AAAA,EAC5C;AAGA,MAAI,6BAA6B,KAAK,QAAQ,GAAG;AAC/C,WAAO,oBAAoB,SAAS;AAAA,EACtC;AAEA,SAAO,CAAC;AACV;AAMA,SAAS,2BACP,MACA,UACA,WACkB;AAClB,QAAM,SAAS,YAAY,IAAI;AAC/B,aAAW,QAAQ,CAAC,SAAS,UAAU,OAAO,QAAQ,IAAI,CAAC;AAE3D,QAAM,YAAsB,CAAC;AAC7B,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,MAAM,MAAM,OAAO,SAAS,QACnC,MAAM,MAAM,MAAM,SAAS,SAAS,QAAQ,MAAM,MAAM,MAAM,aAAa,SAAS,WAAY;AACjG;AAAA,IACF;AACA,QAAI,CAAC,MAAM,KAAM;AACjB,QAAI,CAAC,UAAU,OAAO,QAAQ,MAAM,IAAI,EAAG;AAE3C,QAAI,MAAM,SAAS,IAAI;AACrB,gBAAU,KAAK,MAAM,IAAI;AAAA,IAC3B,OAAO;AACL,YAAM,YAAY,OAAO,MAAM,IAAI;AACnC,UAAI,cAAc,UAAU,MAAM,MAAM,OAAO,SAAS,QACrD,UAAU,MAAM,MAAM,SAAS,SAAS,QAAQ,UAAU,MAAM,MAAM,YAAY,SAAS,YAAa;AACzG,kBAAU,KAAK,MAAM,IAAI;AAAA,MAC3B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,UAAU,WAAW,EAAG,QAAO,CAAC;AAEpC,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,cAAwB,CAAC;AAC/B,WAAS,IAAI,UAAU,SAAS,GAAG,KAAK,GAAG,KAAK;AAC9C,UAAM,OAAO,UAAU,CAAC;AACxB,QAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AACnB,WAAK,IAAI,IAAI;AACb,kBAAY,KAAK,IAAI;AAAA,IACvB;AAAA,EACF;AAEA,SAAO,YAAY,IAAI,CAAC,MAAM,SAAS;AAAA,IACrC,OAAO,KAAK,IAAI;AAAA,IAChB,MAAM;AAAA;AAAA,IACN,QAAQ,UAAU,IAAI;AAAA,IACtB,UAAU,OAAO,GAAG,EAAE,SAAS,GAAG,GAAG;AAAA,IACrC,YAAY,KAAK,IAAI;AAAA,EACvB,EAAE;AACJ;AAEA,SAAS,oBAAoB,WAA6C;AACxE,QAAM,QAA0B,CAAC;AAEjC,aAAW,SAAS,UAAU,OAAO,aAAa,GAAG;AACnD,UAAM,KAAK;AAAA,MACT,OAAO,MAAM;AAAA,MACb,MAAM;AAAA;AAAA,MACN,QAAQ,MAAM,QAAQ,qBAAqB,MAAM,IAAI,KAAK,WAAW,MAAM,IAAI;AAAA,MAC/E,eAAe,MAAM,eAAe;AAAA,IACtC,CAAC;AAAA,EACH;AAEA,aAAW,UAAU,UAAU,QAAQ,cAAc,GAAG;AACtD,UAAM,KAAK;AAAA,MACT,OAAO,OAAO;AAAA,MACd,MAAM;AAAA;AAAA,MACN,QAAQ,YAAY,OAAO,IAAI;AAAA,MAC/B,eAAe,OAAO,OAAO,SAAS,IAClC,eAAe,OAAO,OAAO,IAAI,OAAK,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC,KACzD;AAAA,IACN,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAEA,SAAS,4BAA4B,WAA6C;AAChF,QAAM,WAAW,UAAU,UAAU,YAAY;AACjD,MAAI,SAAS,SAAS,EAAG,QAAO,CAAC;AAEjC,QAAM,QAA0B,CAAC;AACjC,aAAW,CAAC,MAAM,IAAI,KAAK,UAAU;AACnC,UAAM,KAAK;AAAA,MACT,OAAO,IAAI,IAAI;AAAA,MACf,MAAM;AAAA;AAAA,MACN,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,eAAe,KAAK,UAAU,KAAK,OAAO,SAAS,IAC/C,WAAW,KAAK,OAAO,KAAK,IAAI,CAAC,KACjC;AAAA,IACN,CAAC;AAAA,EACH;AACA,SAAO;AACT;AAEA,SAAS,2BAA2B,MAAgC;AAClE,QAAM,eAAe;AACrB,QAAM,QAAQ,oBAAI,IAAY;AAC9B,MAAI;AACJ,UAAQ,IAAI,aAAa,KAAK,IAAI,OAAO,MAAM;AAC7C,UAAM,IAAI,EAAE,CAAC,CAAC;AAAA,EAChB;AACA,MAAI,MAAM,SAAS,EAAG,QAAO,CAAC;AAE9B,SAAO,MAAM,KAAK,KAAK,EAAE,IAAI,WAAS;AAAA,IACpC,OAAO,IAAI,IAAI;AAAA,IACf,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,EACd,EAAE;AACJ;AAEA,SAAS,4BAA4B,MAAgC;AACnE,QAAM,aAAa;AACnB,QAAM,QAAQ,oBAAI,IAAY;AAC9B,MAAI;AACJ,UAAQ,IAAI,WAAW,KAAK,IAAI,OAAO,MAAM;AAC3C,UAAM,IAAI,EAAE,CAAC,CAAC;AAAA,EAChB;AACA,MAAI,MAAM,SAAS,EAAG,QAAO,CAAC;AAE9B,SAAO,MAAM,KAAK,KAAK,EAAE,IAAI,WAAS;AAAA,IACpC,OAAO,IAAI,IAAI;AAAA,IACf,MAAM;AAAA;AAAA,IACN,QAAQ;AAAA,IACR,YAAY;AAAA,EACd,EAAE;AACJ;AAEA,SAAS,sBAAsB,SAAiB,WAA6C;AAC3F,QAAM,WAAW,UAAU,UAAU,YAAY;AACjD,QAAM,OAAO,SAAS,IAAI,OAAO;AACjC,MAAI,CAAC,QAAQ,CAAC,KAAK,UAAU,KAAK,OAAO,WAAW,EAAG,QAAO,CAAC;AAE/D,SAAO,KAAK,OAAO,IAAI,YAAU;AAAA,IAC/B,OAAO;AAAA,IACP,MAAM;AAAA;AAAA,IACN,QAAQ,aAAa,OAAO;AAAA,EAC9B,EAAE;AACJ;AAEA,SAAS,0BAA0B,WAA6C;AAC9E,QAAM,WAAW,UAAU,SAAS,eAAe;AACnD,MAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AAEnC,SAAO,SAAS,IAAI,QAAM;AAAA,IACxB,OAAO,EAAE;AAAA,IACT,MAAM;AAAA;AAAA,IACN,QAAQ,EAAE;AAAA,EACZ,EAAE;AACJ;AAnOA,IAyOa;AAzOb;AAAA;AAAA;AAIA;AAqOO,IAAM,oBAAmC;AAAA,MAC9C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,oBAAoB;AAAA,UAClB,mBAAmB,CAAC,KAAK,KAAK,KAAK,KAAK,KAAK,GAAG;AAAA,QAClD;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,aAAa,CAAC,WAAW;AACtC,gBAAM,MAAM,OAAO,aAAa;AAChC,gBAAM,WAAqB;AAAA,YACzB,MAAM,OAAO,SAAS;AAAA,YACtB,WAAW,OAAO,SAAS;AAAA,UAC7B;AACA,gBAAM,cAAc,OAAO,SAAS;AACpC,iBAAO,eAAe,KAAK,UAAU,aAAa,IAAI,SAAS;AAAA,QACjE,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACrOO,SAAS,aACd,KACA,UACA,WACoB;AACpB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO;AAE/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO;AAC1C,QAAM,OAAO,MAAM,SAAS,IAAI;AAIhC,QAAM,cAAc,cAAc,MAAM,UAAU,SAAS;AAC3D,MAAI,YAAa,QAAO;AAGxB,QAAM,YAAY,iBAAiB,MAAM,UAAU,SAAS;AAC5D,MAAI,UAAW,QAAO;AAGtB,QAAM,eAAe,eAAe,MAAM,UAAU,SAAS;AAC7D,MAAI,aAAc,QAAO;AAEzB,SAAO;AACT;AAMA,SAAS,cACP,MACA,UACA,WACoB;AAEpB,QAAMC,cAAa;AACnB,MAAI;AAEJ,UAAQ,QAAQA,YAAW,KAAK,IAAI,OAAO,MAAM;AAC/C,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,YAAY,MAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,IAAI;AACrD,UAAM,UAAU,YAAY,KAAK;AAEjC,QAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,YAAM,OAAO,UAAU,OAAO,SAAS,IAAI;AAC3C,UAAI,MAAM;AACR,cAAM,QAAkB,CAAC;AACzB,cAAM,KAAK,KAAK,KAAK,IAAI,QAAQ,KAAK,QAAQ,cAAc,QAAQ,UAAU;AAC9E,YAAI,KAAK,aAAa;AACpB,gBAAM,KAAK,IAAI,KAAK,WAAW;AAAA,QACjC;AACA,YAAI,KAAK,cAAc,KAAK,WAAW,SAAS,GAAG;AACjD,gBAAM,KAAK,IAAI,iBAAiB,KAAK,WAAW,KAAK,GAAG,CAAC,IAAI;AAAA,QAC/D;AAEA,eAAO;AAAA,UACL,UAAU,MAAM,KAAK,IAAI;AAAA,UACzB,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,UAAU;AAAA,YACnD,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,QAAQ;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAGA,YAAM,SAAS,UAAU,QAAQ,UAAU,IAAI;AAC/C,UAAI,QAAQ;AACV,eAAO,iBAAiB,QAAQ,SAAS,MAAM,WAAW,OAAO;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,iBACP,MACA,UACA,WACoB;AAEpB;AACE,UAAM,KAAK;AACX,QAAI;AACJ,YAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,cAAM,WAAW,MAAM,CAAC,EAAE,MAAM,GAAG,EAAE,CAAC;AACtC,cAAM,OAAO,UAAU,UAAU,YAAY,EAAE,IAAI,QAAQ;AAC3D,cAAM,WAAW,MAAM,UAAU,KAAK,OAAO,SAAS,IAClD;AAAA;AAAA,UAAe,KAAK,OAAO,IAAI,OAAK,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,CAAC,KAC1D;AACJ,eAAO;AAAA,UACL,UAAU,yBAAyB,MAAM,CAAC,CAAC,KAAK,QAAQ;AAAA,UACxD,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM;AAAA,YAC/C,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,KAAK;AACX,QAAI;AACJ,YAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,eAAO;AAAA,UACL,UAAU,wBAAwB,MAAM,CAAC,CAAC;AAAA,UAC1C,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM;AAAA,YAC/C,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,KAAK;AACX,QAAI;AACJ,YAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,eAAO;AAAA,UACL,UAAU,yBAAyB,MAAM,CAAC,CAAC;AAAA,UAC3C,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM;AAAA,YAC/C,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,eACP,MACA,UACA,WACoB;AAEpB,QAAM,KAAK;AACX,MAAI;AACJ,UAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,YAAY,MAAM,QAAQ;AAChC,UAAM,UAAU,YAAY,KAAK;AACjC,QAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,YAAM,SAAS,UAAU,QAAQ,UAAU,IAAI;AAC/C,UAAI,QAAQ;AACV,eAAO,iBAAiB,QAAQ,SAAS,MAAM,WAAW,OAAO;AAAA,MACnE;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,iBACP,QACA,MACA,WACA,SACa;AACb,QAAM,MAAM,OAAO,OAAO,SAAS,IAC/B,OAAO,OAAO,IAAI,OAAK,IAAI,CAAC,EAAE,EAAE,KAAK,IAAI,IACzC;AACJ,SAAO;AAAA,IACL,UAAU,gBAAgB,OAAO,IAAI;AAAA;AAAA,cAAqB,GAAG;AAAA;AAAA,gBAAqB,OAAO,GAAG;AAAA,IAC5F,OAAO;AAAA,MACL,OAAO,EAAE,MAAM,WAAW,UAAU;AAAA,MACpC,KAAK,EAAE,MAAM,WAAW,QAAQ;AAAA,IAClC;AAAA,EACF;AACF;AAMA,SAAS,WAAW,GAAoB;AACtC,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AA3NA,IA6Na;AA7Nb;AAAA;AAAA;AA6NO,IAAM,cAA6B;AAAA,MACxC,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,eAAe;AAAA,MACjB;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,QAAQ,CAAC,WAAyB;AAC/C,gBAAM,SAAS;AAAA,YACb,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,IAAI;AAAA,UACN;AACA,cAAI,CAAC,OAAQ,QAAO;AACpB,iBAAO;AAAA,YACL,UAAU,EAAE,MAAM,YAAY,OAAO,OAAO,SAAS;AAAA,YACrD,OAAO,WAAW,OAAO,KAAK;AAAA,UAChC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACtNO,SAAS,iBACd,KACA,UACA,WAC4B;AAC5B,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO;AAE/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO;AAC1C,QAAM,WAAW,MAAM,SAAS,IAAI;AACpC,QAAM,aAAa,SAAS,UAAU,GAAG,SAAS,SAAS;AAG3D,QAAM,aAAa,WAAW,MAAM,yDAAyD;AAC7F,MAAI,CAAC,WAAY,QAAO;AAExB,QAAM,YAAY,WAAW,CAAC;AAC9B,QAAM,aAAa,WAAW,CAAC;AAG/B,QAAM,kBAAkB,WAAW,KAAK,MAAM,KAAK,IAAI,aAAa,UAAU,EAAE;AAGhF,QAAM,YAAY,UAAU,OAAO,SAAS,SAAS;AACrD,MAAI,aAAa,UAAU,cAAc,UAAU,WAAW,SAAS,GAAG;AACxE,UAAM,cAAc,UAAU;AAC9B,WAAO;AAAA,MACL,YAAY,CAAC;AAAA,QACX,OAAO,IAAI,SAAS,IAAI,YAAY,KAAK,GAAG,CAAC;AAAA,QAC7C,eAAe,UAAU,eAAe;AAAA,QACxC,YAAY,YAAY,IAAI,QAAM,EAAE,OAAO,EAAE,EAAE;AAAA,MACjD,CAAC;AAAA,MACD,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAGA,QAAM,SAAS,UAAU,QAAQ,UAAU,SAAS;AACpD,MAAI,UAAU,OAAO,OAAO,SAAS,GAAG;AACtC,UAAM,cAAc,OAAO,OAAO,IAAI,OAAK,IAAI,CAAC,EAAE;AAClD,WAAO;AAAA,MACL,YAAY,CAAC;AAAA,QACX,OAAO,IAAI,SAAS,IAAI,YAAY,KAAK,IAAI,CAAC;AAAA,QAC9C,eAAe,sBAAsB,OAAO,GAAG;AAAA,QAC/C,YAAY,YAAY,IAAI,QAAM,EAAE,OAAO,EAAE,EAAE;AAAA,MACjD,CAAC;AAAA,MACD,iBAAiB;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAhFA,IAsFa;AAtFb;AAAA;AAAA;AAIA;AAkFO,IAAM,kBAAiC;AAAA,MAC5C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,uBAAuB;AAAA,UACrB,mBAAmB,CAAC,KAAK,KAAK,GAAG;AAAA,QACnC;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,gBAAgB,CAAC,WAAiC;AAC/D,gBAAM,SAAS;AAAA,YACb,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,IAAI;AAAA,UACN;AACA,cAAI,CAAC,OAAQ,QAAO;AAEpB,gBAAM,aAAqC,OAAO,WAAW,IAAI,UAAQ;AAAA,YACvE,OAAO,IAAI;AAAA,YACX,eAAe,IAAI;AAAA,YACnB,YAAY,IAAI,WAAW,IAAI,QAAM,EAAE,OAAO,EAAE,MAAM,EAA0B;AAAA,UAClF,EAAE;AAEF,iBAAO;AAAA,YACL;AAAA,YACA,iBAAiB,OAAO;AAAA,YACxB,iBAAiB,OAAO;AAAA,UAC1B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC7FO,SAAS,cACd,KACA,UACA,WACyB;AACzB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO;AAE/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO;AAC1C,QAAM,OAAO,MAAM,SAAS,IAAI;AAGhC,QAAM,aAAa,yBAAyB,MAAM,UAAU,SAAS;AACrE,MAAI,WAAY,QAAO;AAGvB,QAAM,qBAAqB,0BAA0B,MAAM,UAAU,SAAS;AAC9E,MAAI,mBAAoB,QAAO;AAG/B,QAAM,eAAe,oBAAoB,MAAM,UAAU,SAAS;AAClE,MAAI,aAAc,QAAO;AAEzB,SAAO;AACT;AAMA,SAAS,yBACP,MACA,UACA,WACyB;AACzB,QAAM,QAAQ,WAAW,IAAI;AAC7B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,MAAM,MAAM,SAAS,SAAS,QACrC,SAAS,aAAa,KAAK,MAAM,MAAM,aACvC,SAAS,aAAa,KAAK,MAAM,IAAI,WAAW;AAChD,YAAM,UAAU,UAAU,SAAS,WAAW,KAAK,IAAI;AACvD,UAAI,SAAS;AACX,eAAO;AAAA,UACL,KAAK,QAAQ;AAAA,UACb,OAAO,QAAQ;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,0BACP,MACA,UACA,WACyB;AAEzB,QAAM,WAAW;AAAA,IACf;AAAA,IACA;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,YAAQ,YAAY;AACpB,QAAI;AACJ,YAAQ,QAAQ,QAAQ,KAAK,IAAI,OAAO,MAAM;AAC5C,YAAM,cAAc,MAAM,CAAC;AAC3B,YAAM,YAAY,MAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,WAAW;AAC5D,YAAM,UAAU,YAAY,YAAY;AACxC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,cAAM,UAAU,UAAU,SAAS,WAAW,WAAW;AACzD,YAAI,SAAS;AACX,iBAAO;AAAA,YACL,KAAK,QAAQ;AAAA,YACb,OAAO,QAAQ;AAAA,UACjB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,oBACP,MACA,UACA,WACyB;AAEzB,QAAM,KAAK;AACX,MAAI;AACJ,UAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,UAAM,OAAO,MAAM,CAAC;AACpB,UAAM,YAAY,MAAM,QAAQ;AAChC,UAAM,UAAU,YAAY,KAAK;AACjC,QAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AAEpE,UAAI,UAAU,OAAO,SAAS,IAAI,EAAG;AAErC,YAAM,SAAS,UAAU,QAAQ,UAAU,IAAI;AAC/C,UAAI,QAAQ;AACV,eAAO;AAAA,UACL,KAAK,OAAO;AAAA,UACZ,OAAO,OAAO;AAAA,QAChB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AAhJA,IAkJa;AAlJb;AAAA;AAAA;AAGA;AA+IO,IAAM,mBAAkC;AAAA,MAC7C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,oBAAoB;AAAA,MACtB;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,aAAa,CAAC,WAAW;AACtC,gBAAM,SAAS;AAAA,YACb,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,IAAI;AAAA,UACN;AACA,cAAI,CAAC,OAAQ,QAAO;AACpB,iBAAO;AAAA,YACL,KAAK,OAAO;AAAA,YACZ,OAAOA,YAAW,OAAO,KAAK;AAAA,UAChC;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC9IO,SAAS,eACd,KACA,UACA,WACA,oBACqB;AACrB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO,CAAC;AAC3C,QAAM,OAAO,MAAM,SAAS,IAAI;AAGhC,QAAMC,sBAAqB;AAC3B,MAAI,KAAK,UAAU,EAAE,WAAW,IAAI,GAAG;AACrC,UAAM,cAAcA,oBAAmB,KAAK,IAAI;AAChD,QAAI,aAAa;AACf,YAAM,cAAc,YAAY,CAAC,EAAE,KAAK;AACxC,YAAM,YAAY,KAAK,QAAQ,WAAW;AAC1C,YAAM,UAAU,YAAY,YAAY;AACxC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,eAAO,sBAAsB,aAAa,WAAW,kBAAkB;AAAA,MACzE;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,WAAW;AACjB,QAAI;AACJ,YAAQ,QAAQ,SAAS,KAAK,IAAI,OAAO,MAAM;AAC7C,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,cAAM,UAAU,MAAM,CAAC;AACvB,eAAO,uBAAuB,SAAS,WAAW,kBAAkB;AAAA,MACtE;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,cAAc;AACpB,QAAI;AACJ,YAAQ,QAAQ,YAAY,KAAK,IAAI,OAAO,MAAM;AAChD,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,YAAY,MAAM,QAAQ;AAChC,YAAM,UAAU,YAAY,KAAK;AACjC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,YAAI,CAAC,UAAU,OAAO,SAAS,IAAI,KAAK,UAAU,QAAQ,UAAU,IAAI,GAAG;AACzE,iBAAO,qBAAqB,MAAM,WAAW,kBAAkB;AAAA,QACjE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,cAAc,UAAU,SAAS,eAAe;AACtD,UAAM,eAAe,IAAI,IAAI,YAAY,IAAI,OAAK,EAAE,IAAI,CAAC;AAEzD,UAAM,YAAY;AAClB,QAAI;AACJ,YAAQ,QAAQ,UAAU,KAAK,IAAI,OAAO,MAAM;AAC9C,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,cAAM,OAAO,MAAM,CAAC,EAAE,KAAK;AAC3B,YAAI,aAAa,IAAI,IAAI,GAAG;AAC1B,iBAAO,sBAAsB,MAAM,WAAW,kBAAkB;AAAA,QAClE;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,CAAC;AACV;AASO,SAAS,sBACd,aACA,WACA,oBACqB;AACrB,QAAM,YAAiC,CAAC;AAGxC,MAAI,oBAAoB;AACtB,UAAM,UAAU,UAAU,SAAS,WAAW,WAAW;AACzD,QAAI,SAAS;AACX,gBAAU,KAAK;AAAA,QACb,KAAK,QAAQ;AAAA,QACb,OAAO,QAAQ;AAAA,MACjB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,YAAY;AAClB,QAAM,iBAAiB;AAEvB,aAAW,UAAU,UAAU,UAAU,QAAQ,GAAG;AAClD,UAAM,UAAU,UAAU,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,QAAS;AAGd,UAAM,QAAQ,WAAW,OAAO;AAChC,eAAW,QAAQ,OAAO;AACxB,UAAI,KAAK,SAAS,aAAa;AAC7B,kBAAU,KAAK,EAAE,KAAK,QAAQ,OAAO,KAAK,MAAM,CAAC;AAAA,MACnD;AAAA,IACF;AAGA,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,aAAS,UAAU,GAAG,UAAU,MAAM,QAAQ,WAAW;AACvD,YAAM,OAAO,MAAM,OAAO;AAE1B,iBAAW,SAAS,CAAC,WAAW,cAAc,GAAG;AAC/C,cAAM,YAAY;AAClB,YAAI;AACJ,gBAAQ,QAAQ,MAAM,KAAK,IAAI,OAAO,MAAM;AAC1C,cAAI,MAAM,CAAC,MAAM,aAAa;AAC5B,kBAAM,YAAY,MAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,MAAM,CAAC,CAAC;AACzD,sBAAU,KAAK;AAAA,cACb,KAAK;AAAA,cACL,OAAO;AAAA,gBACL,OAAO,EAAE,MAAM,SAAS,WAAW,UAAU;AAAA,gBAC7C,KAAK,EAAE,MAAM,SAAS,WAAW,YAAY,MAAM,CAAC,EAAE,OAAO;AAAA,cAC/D;AAAA,YACF,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,uBACd,SACA,WACA,oBACqB;AACrB,QAAM,YAAiC,CAAC;AAGxC,MAAI,oBAAoB;AACtB,UAAM,OAAO,UAAU,UAAU,YAAY,EAAE,IAAI,OAAO;AAC1D,QAAI,MAAM,oBAAoB,KAAK,gBAAgB;AACjD,gBAAU,KAAK;AAAA,QACb,KAAK,KAAK;AAAA,QACV,OAAO,KAAK;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,SAAS,UAAU,UAAU,UAAU,OAAO;AACpD,aAAW,KAAK,QAAQ;AACtB,cAAU,KAAK,EAAE,KAAK,EAAE,KAAK,OAAO,EAAE,MAAM,CAAC;AAAA,EAC/C;AAEA,SAAO;AACT;AAKO,SAAS,qBACd,YACA,WACA,oBACqB;AACrB,QAAM,YAAiC,CAAC;AAGxC,MAAI,oBAAoB;AACtB,UAAM,SAAS,UAAU,QAAQ,UAAU,UAAU;AACrD,QAAI,QAAQ;AACV,gBAAU,KAAK,EAAE,KAAK,OAAO,KAAK,OAAO,OAAO,MAAM,CAAC;AAAA,IACzD;AAAA,EACF;AAGA,QAAM,wBAAwB;AAE9B,aAAW,UAAU,UAAU,UAAU,QAAQ,GAAG;AAClD,UAAM,UAAU,UAAU,UAAU,QAAQ,MAAM;AAClD,QAAI,CAAC,QAAS;AAEd,UAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,aAAS,UAAU,GAAG,UAAU,MAAM,QAAQ,WAAW;AACvD,YAAM,OAAO,MAAM,OAAO;AAG1B,UAAI,gBAAgB,KAAK,IAAI,EAAG;AAEhC,4BAAsB,YAAY;AAClC,UAAI;AACJ,cAAQ,QAAQ,sBAAsB,KAAK,IAAI,OAAO,MAAM;AAC1D,YAAI,MAAM,CAAC,MAAM,YAAY;AAC3B,gBAAM,YAAY,MAAM,QAAQ;AAChC,oBAAU,KAAK;AAAA,YACb,KAAK;AAAA,YACL,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,SAAS,WAAW,UAAU;AAAA,cAC7C,KAAK,EAAE,MAAM,SAAS,WAAW,YAAY,WAAW,OAAO;AAAA,YACjE;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AArQA,IAuQa;AAvQb;AAAA;AAAA;AAGA;AAoQO,IAAM,mBAAkC;AAAA,MAC7C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,oBAAoB;AAAA,MACtB;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,aAAa,CAAC,WAAW;AACtC,gBAAM,OAAO;AAAA,YACX,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,IAAI;AAAA,YACJ,OAAO,QAAQ;AAAA,UACjB;AACA,iBAAO,KAAK,IAAI,QAAM;AAAA,YACpB,KAAK,EAAE;AAAA,YACP,OAAOA,YAAW,EAAE,KAAK;AAAA,UAC3B,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AChQO,SAAS,cACd,KACA,UACA,WAC4B;AAC5B,QAAM,SAAS,sBAAsB,KAAK,UAAU,SAAS;AAC7D,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,EAAE,OAAO,OAAO,OAAO,aAAa,OAAO,KAAK;AACzD;AAMO,SAAS,cACd,KACA,UACA,SACA,WAC2B;AAC3B,QAAM,SAAS,sBAAsB,KAAK,UAAU,SAAS;AAC7D,MAAI,CAAC,OAAQ,QAAO,oBAAI,IAAI;AAE5B,QAAM,QAAQ,oBAAI,IAA0B;AAE5C,WAAS,QAAQ,SAAiB,OAAc,MAAc;AAC5D,UAAM,WAAW,MAAM,IAAI,OAAO,KAAK,CAAC;AACxC,aAAS,KAAK,EAAE,OAAO,SAAS,KAAK,CAAC;AACtC,UAAM,IAAI,SAAS,QAAQ;AAAA,EAC7B;AAEA,UAAQ,OAAO,MAAM;AAAA,IACnB,KAAK,WAAW;AACd,YAAM,OAAO,sBAAsB,OAAO,MAAM,WAAW,IAAI;AAC/D,iBAAW,OAAO,MAAM;AACtB,gBAAQ,IAAI,KAAK,IAAI,OAAO,OAAO;AAAA,MACrC;AACA;AAAA,IACF;AAAA,IAEA,KAAK,YAAY;AACf,YAAM,WAAW,QAAQ,WAAW,GAAG,IAAI,QAAQ,MAAM,CAAC,IAAI;AAC9D,YAAM,OAAO,uBAAuB,OAAO,MAAM,WAAW,IAAI;AAChE,iBAAW,OAAO,MAAM;AACtB,gBAAQ,IAAI,KAAK,IAAI,OAAO,QAAQ;AAAA,MACtC;AACA;AAAA,IACF;AAAA,IAEA,KAAK,UAAU;AAEb,YAAM,iBAAiB,qBAAqB,OAAO,MAAM,WAAW,KAAK;AACzE,iBAAW,OAAO,gBAAgB;AAChC,gBAAQ,IAAI,KAAK,IAAI,OAAO,OAAO;AAAA,MACrC;AAGA,YAAM,SAAS,UAAU,QAAQ,UAAU,OAAO,IAAI;AACtD,UAAI,QAAQ;AAGV,cAAM,UAAU,UAAU,UAAU,QAAQ,OAAO,GAAG;AACtD,YAAI,SAAS;AACX,gBAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,gBAAM,UAAU,MAAM,OAAO,MAAM,MAAM,IAAI;AAC7C,cAAI,SAAS;AACX,kBAAM,WAAW,QAAQ,MAAM,OAAO,MAAM,MAAM,SAAS;AAC3D,kBAAM,YAAY,uBAAuB,KAAK,QAAQ;AACtD,gBAAI,WAAW;AACb,oBAAM,oBAAoB,SAAS,QAAQ,UAAU,CAAC,CAAC;AACvD,oBAAM,YAAY,OAAO,MAAM,MAAM,YAAY;AACjD,sBAAQ,OAAO,KAAK;AAAA,gBAClB,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,UAAU;AAAA,gBAC7D,KAAK,EAAE,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,YAAY,OAAO,KAAK,OAAO;AAAA,cAClF,GAAG,OAAO;AAAA,YACZ;AAAA,UACF;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAYA,SAAS,sBACP,KACA,UACA,WACmB;AACnB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO;AAE/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,MAAI,SAAS,QAAQ,MAAM,OAAQ,QAAO;AAC1C,QAAM,OAAO,MAAM,SAAS,IAAI;AAGhC,QAAMC,sBAAqB;AAC3B,MAAI,KAAK,UAAU,EAAE,WAAW,IAAI,GAAG;AACrC,UAAM,cAAcA,oBAAmB,KAAK,IAAI;AAChD,QAAI,aAAa;AACf,YAAM,cAAc,YAAY,CAAC,EAAE,KAAK;AACxC,YAAM,YAAY,KAAK,QAAQ,WAAW;AAC1C,YAAM,UAAU,YAAY,YAAY;AACxC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,UAAU;AAAA,YACnD,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,QAAQ;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,WAAW;AACjB,QAAI;AACJ,YAAQ,QAAQ,SAAS,KAAK,IAAI,OAAO,MAAM;AAC7C,YAAM,QAAQ,MAAM;AACpB,YAAM,MAAM,QAAQ,MAAM,CAAC,EAAE;AAC7B,UAAI,SAAS,aAAa,SAAS,SAAS,aAAa,KAAK;AAC5D,eAAO;AAAA,UACL,MAAM;AAAA,UACN,MAAM,MAAM,CAAC;AAAA,UACb,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,MAAM;AAAA,YAC/C,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,IAAI;AAAA,UAC7C;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAMC,kBAAiB;AACvB,QAAI;AACJ,YAAQ,QAAQA,gBAAe,KAAK,IAAI,OAAO,MAAM;AACnD,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,YAAY,MAAM,QAAQ,MAAM,CAAC,EAAE,QAAQ,IAAI;AACrD,YAAM,UAAU,YAAY,KAAK;AACjC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,eAAO;AAAA,UACL,MAAM;AAAA,UACN;AAAA,UACA,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,UAAU;AAAA,YACnD,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,QAAQ;AAAA,UACjD;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAGA;AACE,UAAM,KAAK;AACX,QAAI;AACJ,YAAQ,QAAQ,GAAG,KAAK,IAAI,OAAO,MAAM;AACvC,YAAM,OAAO,MAAM,CAAC;AACpB,YAAM,YAAY,MAAM,QAAQ;AAChC,YAAM,UAAU,YAAY,KAAK;AACjC,UAAI,SAAS,aAAa,aAAa,SAAS,aAAa,SAAS;AACpE,YAAI,CAAC,UAAU,OAAO,SAAS,IAAI,KAAK,UAAU,QAAQ,UAAU,IAAI,GAAG;AACzE,iBAAO;AAAA,YACL,MAAM;AAAA,YACN;AAAA,YACA,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,SAAS,MAAM,WAAW,UAAU;AAAA,cACnD,KAAK,EAAE,MAAM,SAAS,MAAM,WAAW,QAAQ;AAAA,YACjD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AAvOA,IAyOa;AAzOb;AAAA;AAAA;AAGA;AAsOO,IAAM,eAA8B;AAAA,MACzC,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,gBAAgB;AAAA,UACd,iBAAiB;AAAA,QACnB;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,gBAAgB,CAAC,WAAW;AACzC,gBAAM,SAAS;AAAA,YACb,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,IAAI;AAAA,UACN;AACA,cAAI,CAAC,OAAQ,QAAO;AACpB,iBAAO;AAAA,YACL,OAAOA,YAAW,OAAO,KAAK;AAAA,YAC9B,aAAa,OAAO;AAAA,UACtB;AAAA,QACF,CAAC;AAED,YAAI,WAAW,gBAAgB,CAAC,WAAW;AACzC,gBAAM,WAAW;AAAA,YACf,OAAO,aAAa;AAAA,YACpB,EAAE,MAAM,OAAO,SAAS,MAAM,WAAW,OAAO,SAAS,UAAU;AAAA,YACnE,OAAO;AAAA,YACP,IAAI;AAAA,UACN;AAEA,gBAAM,UAAsE,CAAC;AAC7E,qBAAW,CAAC,SAAS,KAAK,KAAK,UAAU;AACvC,oBAAQ,OAAO,IAAI,MAAM,IAAI,QAAM;AAAA,cACjC,OAAOA,YAAW,EAAE,KAAK;AAAA,cACzB,SAAS,EAAE;AAAA,YACb,EAAE;AAAA,UACJ;AAEA,iBAAO,EAAE,QAAQ;AAAA,QACnB,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACrPO,SAAS,kBAAkB,KAAa,WAA2C;AACxF,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,SAAyB,CAAC;AAEhC,QAAM,mBAAmB,UAAU,SAAS,kBAAkB;AAC9D,QAAM,kBAAkB,oBAAoB,iBAAiB,QAAQ;AAErE,WAAS,UAAU,GAAG,UAAU,MAAM,QAAQ,WAAW;AACvD,UAAM,OAAO,MAAM,OAAO;AAG1B,UAAM,eAAe,KAAK,MAAM,mCAAmC;AACnE,QAAI,cAAc;AAChB,YAAM,cAAc,aAAa,CAAC,EAAE,KAAK;AACzC,UAAI,gBAAgB,YAAa;AAEjC,YAAM,OAAO,sBAAsB,aAAa,WAAW,IAAI;AAC/D,YAAM,WAAW,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;AAE5C,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,UACL,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE;AAAA,UACrC,KAAK,EAAE,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,QAC/C;AAAA,QACA,SAAS;AAAA,UACP,OAAO,GAAG,QAAQ,aAAa,aAAa,IAAI,MAAM,EAAE;AAAA,QAC1D;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAGA,UAAM,cAAc,KAAK,MAAM,sBAAsB;AACrD,QAAI,aAAa;AACf,YAAM,aAAa,YAAY,CAAC;AAChC,YAAM,OAAO,qBAAqB,YAAY,WAAW,IAAI;AAC7D,YAAM,aAAa,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;AAE9C,aAAO,KAAK;AAAA,QACV,OAAO;AAAA,UACL,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE;AAAA,UACrC,KAAK,EAAE,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,QAC/C;AAAA,QACA,SAAS;AAAA,UACP,OAAO,GAAG,UAAU,SAAS,eAAe,IAAI,MAAM,EAAE;AAAA,QAC1D;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,iBAAiB;AACnB,YAAM,eAAe,KAAK,MAAM,2BAA2B;AAC3D,UAAI,cAAc;AAChB,cAAM,UAAU,aAAa,CAAC;AAC9B,cAAM,OAAO,uBAAuB,SAAS,WAAW,IAAI;AAC5D,cAAM,aAAa,KAAK,IAAI,GAAG,KAAK,SAAS,CAAC;AAE9C,eAAO,KAAK;AAAA,UACV,OAAO;AAAA,YACL,OAAO,EAAE,MAAM,SAAS,WAAW,EAAE;AAAA,YACrC,KAAK,EAAE,MAAM,SAAS,WAAW,KAAK,OAAO;AAAA,UAC/C;AAAA,UACA,SAAS;AAAA,YACP,OAAO,GAAG,UAAU,SAAS,eAAe,IAAI,MAAM,EAAE;AAAA,UAC1D;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AAjHA,IAmHa;AAnHb;AAAA;AAAA;AAGA;AAgHO,IAAM,iBAAgC;AAAA,MAC3C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,kBAAkB;AAAA,UAChB,iBAAiB;AAAA,QACnB;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,WAAW,CAAC,WAAW;AACpC,gBAAM,SAAS,kBAAkB,OAAO,aAAa,KAAK,IAAI,SAAS;AACvE,iBAAO,OAAO,IAAI,QAAM;AAAA,YACtB,OAAOA,YAAW,EAAE,KAAK;AAAA,YACzB,SAAS;AAAA,cACP,OAAO,EAAE,QAAQ;AAAA,cACjB,SAAS;AAAA,YACX;AAAA,UACF,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC/GO,SAAS,kBACd,KACA,OACA,WACiB;AACjB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,QAAyB,CAAC;AAEhC,sBAAoB,MAAM,OAAO,WAAW,KAAK;AACjD,uBAAqB,KAAK,MAAM,OAAO,WAAW,KAAK;AAEvD,SAAO;AACT;AAMA,SAAS,oBACP,MACA,OACA,WACA,OACM;AACN,QAAM,aAAa,UAAU,QAAQ,cAAc;AACnD,MAAI,WAAW,WAAW,EAAG;AAE7B,QAAM,YAAY,IAAI,IAAI,WAAW,IAAI,OAAK,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC1D,QAAM,SAAS,YAAY,IAAI;AAE/B,aAAW,SAAS,QAAQ;AAC1B,QAAI,CAAC,MAAM,KAAM;AAEjB,QAAI,MAAM,MAAM,MAAM,OAAO,MAAM,MAAM,QAAQ,MAAM,MAAM,MAAM,OAAO,MAAM,IAAI,KAAM;AAE1F,UAAM,SAAS,UAAU,IAAI,MAAM,IAAI;AACvC,QAAI,CAAC,UAAU,OAAO,OAAO,WAAW,EAAG;AAE3C,QAAI,CAAC,MAAM,WAAW,MAAM,QAAQ,KAAK,MAAM,GAAI;AAEnD,UAAMC,QAAO,aAAa,MAAM,OAAO;AAGvC,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,YAAY,MAAM,MAAM,MAAM,MAAM,IAAI;AAC9C,QAAI,CAAC,UAAW;AAEhB,UAAM,YAAY,UAAU,UAAU,MAAM,MAAM,MAAM,WAAW,MAAM,MAAM,IAAI,SAAS;AAC5F,UAAM,UAAU,UAAU,QAAQ,MAAM,IAAI,IAAI,MAAM,KAAK;AAC3D,UAAM,WAAW,UAAU,UAAU,OAAO,EAAE,QAAQ,QAAQ,EAAE,EAAE,QAAQ,OAAO,EAAE;AACnF,QAAI,CAAC,SAAU;AAEf,aAAS,IAAI,GAAG,IAAI,KAAK,IAAIA,MAAK,QAAQ,OAAO,OAAO,MAAM,GAAG,KAAK;AACpE,YAAM,UAAUA,MAAK,CAAC,EAAE;AACxB,YAAM,MAAM,UAAU,QAAQ,SAAS,MAAM,MAAM,MAAM,YAAY,OAAO;AAC5E,UAAI,OAAO,GAAG;AACZ,cAAM,KAAK;AAAA,UACT,UAAU,EAAE,MAAM,MAAM,MAAM,MAAM,MAAM,WAAW,IAAI;AAAA,UACzD,OAAO,IAAI,OAAO,OAAO,CAAC,CAAC;AAAA,UAC3B,MAAM;AAAA,QACR,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACF;AAMA,SAAS,qBACP,KACA,MACA,OACA,WACA,OACM;AACN,QAAM,mBAAmB,UAAU,SAAS,kBAAkB;AAC9D,MAAI,CAAC,iBAAkB;AACvB,MAAI,iBAAiB,QAAQ,IAAK;AAElC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,YAAY,KAAK,IAAI,MAAM,MAAM,MAAM,CAAC;AAC9C,QAAM,UAAU,KAAK,IAAI,MAAM,IAAI,MAAM,MAAM,SAAS,CAAC;AAEzD,WAAS,UAAU,WAAW,WAAW,SAAS,WAAW;AAC3D,UAAM,OAAO,MAAM,OAAO;AAC1B,UAAM,YAAY,KAAK,MAAM,mCAAmC;AAChE,QAAI,CAAC,UAAW;AAEhB,UAAM,WAAW,UAAU,CAAC,EAAE,KAAK;AACnC,UAAM,eAAe,UAAU,QAAQ;AACvC,QAAI,CAAC,aAAc;AAEnB,UAAM,QAAQ,KAAK,QAAQ,GAAG;AAC9B,UAAM,KAAK;AAAA,MACT,UAAU,EAAE,MAAM,SAAS,WAAW,MAAM;AAAA,MAC5C,OAAO,KAAK,YAAY;AAAA,MACxB,MAAM;AAAA,IACR,CAAC;AAAA,EACH;AACF;AAEA,SAAS,UAAU,OAA8B;AAC/C,MAAI,gBAAgB,KAAK,KAAK,EAAG,QAAO;AACxC,MAAI,YAAY,KAAK,KAAK,KAAK,YAAY,KAAK,KAAK,EAAG,QAAO;AAC/D,MAAI,MAAM,KAAK,KAAK,EAAG,QAAO;AAC9B,MAAI,MAAM,KAAK,KAAK,EAAG,QAAO;AAC9B,MAAI,UAAU,UAAU,UAAU,QAAS,QAAO;AAClD,MAAI,UAAU,OAAQ,QAAO;AAC7B,MAAI,UAAU,YAAa,QAAO;AAClC,SAAO;AACT;AAzIA,IA+Ia;AA/Ib;AAAA;AAAA;AAGA;AACA;AA2IO,IAAM,mBAAkC;AAAA,MAC7C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,mBAAmB;AAAA,MACrB;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,UAAU,UAAU,GAAG,CAAC,WAAW;AAChD,gBAAM,QAAe;AAAA,YACnB,OAAO,EAAE,MAAM,OAAO,MAAM,MAAM,MAAM,WAAW,OAAO,MAAM,MAAM,UAAU;AAAA,YAChF,KAAK,EAAE,MAAM,OAAO,MAAM,IAAI,MAAM,WAAW,OAAO,MAAM,IAAI,UAAU;AAAA,UAC5E;AAEA,gBAAM,QAAQ,kBAAkB,OAAO,aAAa,KAAK,OAAO,IAAI,SAAS;AAE7E,iBAAO,MAAM,IAAI,QAAM;AAAA,YACrB,UAAU,EAAE,MAAM,EAAE,SAAS,MAAM,WAAW,EAAE,SAAS,UAAU;AAAA,YACnE,OAAO,EAAE;AAAA,YACT,MAAM,EAAE,SAAS,SAAS,IAAI;AAAA,YAC9B,cAAc,EAAE,SAAS;AAAA,YACzB,aAAa,EAAE,SAAS;AAAA,UAC1B,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC7IA,SAAS,WAAW,MAAsB;AACxC,SAAO,eAAe,IAAI,IAAI,KAAK;AACrC;AAEA,SAAS,gBAAgB,WAA6B;AACpD,MAAI,OAAO;AACX,aAAW,KAAK,WAAW;AACzB,UAAM,MAAM,mBAAmB,IAAI,CAAC;AACpC,QAAI,QAAQ,OAAW,SAAS,KAAK;AAAA,EACvC;AACA,SAAO;AACT;AA4BO,SAAS,8BACd,KACA,WACiB;AACjB,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,SAA0B,CAAC;AAGjC,QAAM,cAAc,oBAAI,IAAY;AACpC,QAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,aAAW,WAAW,UAAU;AAC9B,UAAM,aAAa,QAAQ,UAAU,MAAM;AAC3C,gBAAY,IAAI,UAAU;AAG1B,UAAM,UAAU,MAAM,UAAU,KAAK;AAErC,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,MACR,WAAW,WAAW,WAAW;AAAA,MACjC,gBAAgB;AAAA,IAClB,CAAC;AAGD,UAAM,YAAY,QAAQ,MAAM,mCAAmC;AACnE,QAAI,WAAW;AACb,YAAM,OAAO,UAAU,CAAC,EAAE,KAAK;AAC/B,YAAM,YAAY,QAAQ,QAAQ,IAAI;AACtC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW;AAAA,QACX,QAAQ,KAAK;AAAA,QACb,WAAW,WAAW,WAAW;AAAA,QACjC,gBAAgB,gBAAgB,CAAC,aAAa,CAAC;AAAA,MACjD,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,SAAS,YAAY,IAAI;AAC/B,aAAW,SAAS,QAAQ;AAC1B,UAAM,YAAY,MAAM,MAAM,MAAM;AACpC,UAAM,YAAY,MAAM,MAAM,MAAM;AACpC,QAAI,YAAY,IAAI,SAAS,EAAG;AAEhC,UAAM,YAAY,CAAC,CAAC,UAAU,OAAO,SAAS,MAAM,IAAI;AAExD,QAAI,aAAa;AACjB,QAAI,CAAC,MAAM,KAAM,eAAc;AAC/B,QAAI,MAAM,UAAW,eAAc,MAAM,UAAU,SAAS;AAE5D,WAAO,KAAK;AAAA,MACV,MAAM;AAAA,MACN,WAAW,YAAY;AAAA,MACvB,QAAQ,MAAM,KAAK;AAAA,MACnB,WAAW,WAAW,UAAU;AAAA,MAChC,gBAAgB,gBAAgB,YAAY,CAAC,gBAAgB,IAAI,CAAC,CAAC;AAAA,IACrE,CAAC;AAAA,EACH;AAGA,QAAM,gBAAgB;AACtB,QAAM,eAAe;AACrB,QAAM,gBAAgB;AACtB,QAAM,oBAAoB;AAE1B,WAAS,YAAY,GAAG,YAAY,MAAM,QAAQ,aAAa;AAC7D,QAAI,YAAY,IAAI,SAAS,EAAG;AAChC,UAAM,OAAO,MAAM,SAAS;AAG5B,kBAAc,YAAY;AAC1B,QAAI;AACJ,YAAQ,IAAI,cAAc,KAAK,IAAI,OAAO,MAAM;AAC9C,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE,CAAC,EAAE;AAAA,QACb,WAAW,WAAW,UAAU;AAAA,QAChC,gBAAgB,gBAAgB,CAAC,QAAQ,CAAC;AAAA,MAC5C,CAAC;AAAA,IACH;AAGA,iBAAa,YAAY;AACzB,YAAQ,IAAI,aAAa,KAAK,IAAI,OAAO,MAAM;AAC7C,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE,CAAC,EAAE;AAAA,QACb,WAAW,WAAW,UAAU;AAAA,QAChC,gBAAgB,gBAAgB,CAAC,OAAO,CAAC;AAAA,MAC3C,CAAC;AAAA,IACH;AAGA,kBAAc,YAAY;AAC1B,YAAQ,IAAI,cAAc,KAAK,IAAI,OAAO,MAAM;AAC9C,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE,CAAC,EAAE;AAAA,QACb,WAAW,WAAW,UAAU;AAAA,QAChC,gBAAgB,gBAAgB,CAAC,UAAU,CAAC;AAAA,MAC9C,CAAC;AAAA,IACH;AAGA,sBAAkB,YAAY;AAC9B,YAAQ,IAAI,kBAAkB,KAAK,IAAI,OAAO,MAAM;AAClD,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,EAAE;AAAA,QACb,QAAQ,EAAE,CAAC,EAAE;AAAA,QACb,WAAW,WAAW,SAAS;AAAA,QAC/B,gBAAgB;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,EACF;AAGA,SAAO,KAAK,CAAC,GAAG,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,SAAS;AAElE,SAAO;AACT;AAOO,SAAS,aAAa,gBAA2C;AACtE,QAAM,OAAiB,CAAC;AACxB,MAAI,WAAW;AACf,MAAI,WAAW;AAEf,aAAW,SAAS,gBAAgB;AAClC,UAAM,YAAY,MAAM,OAAO;AAC/B,UAAM,aAAa,cAAc,IAAI,MAAM,YAAY,WAAW,MAAM;AAExE,SAAK,KAAK,WAAW,YAAY,MAAM,QAAQ,MAAM,WAAW,MAAM,cAAc;AAEpF,eAAW,MAAM;AACjB,eAAW,MAAM;AAAA,EACnB;AAEA,SAAO;AACT;AAKO,SAAS,sBAAsB,KAAa,WAAqC;AACtF,QAAM,iBAAiB,8BAA8B,KAAK,SAAS;AACnE,SAAO,aAAa,cAAc;AACpC;AAhOA,IAQa,kBAMA,sBAIP,gBAGA,oBAiNO;AAtOb;AAAA;AAAA;AAEA;AAMO,IAAM,mBAA6B;AAAA,MACxC;AAAA,MAAY;AAAA,MAAY;AAAA,MAAa;AAAA,MAAY;AAAA,MACjD;AAAA,MAAU;AAAA,MAAU;AAAA,MAAW;AAAA,MAAa;AAAA,MAC5C;AAAA,MAAS;AAAA,IACX;AAEO,IAAM,uBAAiC;AAAA,MAC5C;AAAA,MAAe;AAAA,MAAkB;AAAA,MAAU;AAAA,MAAS;AAAA,IACtD;AAEA,IAAM,iBAAiB,IAAI;AAAA,MACzB,iBAAiB,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AAAA,IACvC;AACA,IAAM,qBAAqB,IAAI;AAAA,MAC7B,qBAAqB,IAAI,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;AAAA,IAC3C;AA+MO,IAAM,uBAAsC;AAAA,MACjD,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,wBAAwB;AAAA,UACtB,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,YAAY;AAAA,YACZ,gBAAgB;AAAA,UAClB;AAAA,QACF;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,UAAU,eAAe,GAAG,CAAC,WAAW;AACrD,gBAAM,OAAO,sBAAsB,OAAO,aAAa,KAAK,IAAI,SAAS;AACzE,iBAAO,EAAE,KAAK;AAAA,QAChB,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC3NO,SAAS,mBACd,KACA,aACA,WACc;AACd,QAAM,UAAwB,CAAC;AAE/B,aAAW,QAAQ,aAAa;AAC9B,YAAQ,KAAK,MAAM;AAAA,MACjB,KAAK,eAAe,gBAAgB;AAClC,cAAM,SAAS,kBAAkB,IAAI;AACrC,YAAI,OAAQ,SAAQ,KAAK,MAAM;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,eAAe,oBAAoB;AACtC,cAAM,SAAS,sBAAsB,MAAM,SAAS;AACpD,YAAI,OAAQ,SAAQ,KAAK,MAAM;AAC/B;AAAA,MACF;AAAA,MACA,KAAK,eAAe,kBAAkB;AACpC,cAAM,SAAS,oBAAoB,KAAK,SAAS;AACjD,YAAI,OAAQ,SAAQ,KAAK,MAAM;AAC/B;AAAA,MACF;AAAA,IAEF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,kBAAkB,MAAqC;AAE9D,QAAM,QAAQ,KAAK,QAAQ,MAAM,gBAAgB;AACjD,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,YAAY,MAAM,CAAC;AACzB,QAAM,YAAY;AAGlB,QAAM,cAAc;AAAA,IAAO,SAAS;AAAA;AAAA;AAEpC,SAAO;AAAA,IACL,OAAO,QAAQ,SAAS;AAAA,IACxB,MAAM;AAAA,IACN,iBAAiB,CAAC,eAAe,cAAc;AAAA,IAC/C,OAAO,CAAC;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,QACL,OAAO,EAAE,MAAM,OAAO,kBAAkB,WAAW,EAAE;AAAA,QACrD,KAAK,EAAE,MAAM,OAAO,kBAAkB,WAAW,EAAE;AAAA,MACrD;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAMA,SAAS,sBACP,MACA,WACmB;AAEnB,QAAM,QAAQ,KAAK,QAAQ,MAAM,WAAW;AAC5C,MAAI,CAAC,MAAO,QAAO;AAEnB,QAAM,UAAU,MAAM,CAAC;AAEvB,QAAM,YAAY,UAAU,SAAS,kBAAkB;AACvD,MAAI,CAAC,UAAW,QAAO;AAEvB,QAAM,eAAe,UAAU;AAC/B,QAAM,OAAO,UAAU,UAAU,QAAQ,YAAY;AACrD,MAAI,SAAS,OAAW,QAAO;AAG/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,eAAe,UAAU,UAAU,IAAI,OAAO;AACpD,MAAI,aAAa,MAAM;AACvB,WAAS,IAAI,cAAc,IAAI,MAAM,QAAQ,KAAK;AAChD,QAAI,SAAS,KAAK,MAAM,CAAC,CAAC,GAAG;AAC3B,mBAAa;AACb;AAAA,IACF;AAAA,EACF;AAGA,QAAM,aAAa;AAEnB,SAAO;AAAA,IACL,OAAO,aAAa,OAAO;AAAA,IAC3B,MAAM;AAAA,IACN,iBAAiB,CAAC,eAAe,kBAAkB;AAAA,IACnD,OAAO,CAAC;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,QACL,OAAO,EAAE,MAAM,YAAY,WAAW,EAAE;AAAA,QACxC,KAAK,EAAE,MAAM,YAAY,WAAW,EAAE;AAAA,MACxC;AAAA,MACA,SAAS,IAAI,OAAO;AAAA;AAAA,IACtB,CAAC;AAAA,EACH;AACF;AAMA,SAAS,oBACP,KACA,WACmB;AAEnB,QAAM,OAAO,UAAU,UAAU,QAAQ;AACzC,QAAM,YAAY,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI;AAE9C,QAAM,OAAO,UAAU,UAAU,QAAQ,SAAS;AAClD,MAAI,SAAS,OAAW,QAAO;AAE/B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,WAAW,MAAM;AAEvB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,iBAAiB,CAAC,eAAe,gBAAgB;AAAA,IACjD,OAAO,CAAC;AAAA,MACN,KAAK;AAAA,MACL,OAAO;AAAA,QACL,OAAO,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,QACtC,KAAK,EAAE,MAAM,UAAU,WAAW,EAAE;AAAA,MACtC;AAAA,MACA,SAAS;AAAA,IACX,CAAC;AAAA,EACH;AACF;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AArLA,IAuLa;AAvLb;AAAA;AAAA;AAGA;AAoLO,IAAM,oBAAmC;AAAA,MAC9C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,oBAAoB;AAAA,UAClB,iBAAiB,CAAC,UAAU;AAAA,QAC9B;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,aAAa,CAAC,WAAW;AAEtC,gBAAM,cAA4B,OAAO,QAAQ,YAC9C,OAAO,OAAK,EAAE,WAAW,SAAS,EAClC,IAAI,QAAM;AAAA,YACT,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,MAAM,WAAW,EAAE,MAAM,MAAM,UAAU;AAAA,cACtE,KAAK,EAAE,MAAM,EAAE,MAAM,IAAI,MAAM,WAAW,EAAE,MAAM,IAAI,UAAU;AAAA,YAClE;AAAA,YACA,SAAS,EAAE;AAAA,YACX,UAAU,EAAE,aAAa,IAAI,UACzB,EAAE,aAAa,IAAI,YACnB,EAAE,aAAa,IAAI,SACnB;AAAA,YACJ,MAAM,OAAO,EAAE,QAAQ,EAAE;AAAA,YACzB,QAAQ,EAAE,UAAU;AAAA,UACtB,EAAE;AAEJ,gBAAM,UAAU;AAAA,YACd,OAAO,aAAa;AAAA,YACpB;AAAA,YACA,IAAI;AAAA,UACN;AAEA,iBAAO,QAAQ,IAAI,QAAM;AAAA,YACvB,OAAO,EAAE;AAAA,YACT,MAAM,EAAE;AAAA,YACR,aAAa,OAAO,QAAQ,YAAY;AAAA,cAAO,OAC7C,EAAE,gBAAgB,SAAS,OAAO,EAAE,IAAI,CAAC;AAAA,YAC3C;AAAA,YACA,MAAM;AAAA,cACJ,SAAS,OAAO;AAAA,gBACd,EAAE,MAAM,IAAI,OAAK;AAAA,kBACf,EAAE;AAAA,kBACF,CAAC,EAAE,OAAOA,YAAW,EAAE,KAAK,GAAG,SAAS,EAAE,QAAQ,CAAC;AAAA,gBACrD,CAAC;AAAA,cACH;AAAA,YACF;AAAA,UACF,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACrOA,SAAS,kBAAkB;AAsBpB,SAAS,uBAAuB,KAAa,WAAwC;AAC1F,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,MAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AAEnC,QAAM,mBAAmB,UAAU,SAAS,kBAAkB;AAC9D,QAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,QAAM,UAAuB,CAAC;AAE9B,aAAW,WAAW,UAAU;AAC9B,UAAM,aAAa,QAAQ,MAAM,MAAM;AACvC,UAAM,iBAAwB;AAAA,MAC5B,OAAO,EAAE,MAAM,YAAY,WAAW,EAAE;AAAA,MACxC,KAAK,EAAE,MAAM,YAAY,WAAW,MAAM,UAAU,GAAG,UAAU,EAAE;AAAA,IACrE;AAEA,UAAM,gBAA2B;AAAA,MAC/B,MAAM,QAAQ;AAAA,MACd,MAAM,WAAW;AAAA,MACjB,OAAO,QAAQ;AAAA,MACf;AAAA,MACA,UAAU,CAAC;AAAA,IACb;AAGA,QAAI,QAAQ,MAAM,SAAS,QAAQ,GAAG;AACpC,YAAM,eAAe,QAAQ,MAAM,MAAM,OAAO;AAChD,YAAM,aAAa,QAAQ,MAAM,IAAI,OAAO;AAC5C,YAAMC,kBAAiB;AAEvB,eAAS,IAAI,cAAc,IAAI,cAAc,IAAI,MAAM,QAAQ,KAAK;AAClE,QAAAA,gBAAe,YAAY;AAC3B,YAAI;AACJ,gBAAQ,QAAQA,gBAAe,KAAK,MAAM,CAAC,CAAC,OAAO,MAAM;AACvD,gBAAM,YAAY,MAAM;AACxB,gBAAM,UAAU,YAAY,MAAM,CAAC,EAAE;AACrC,wBAAc,SAAU,KAAK;AAAA,YAC3B,MAAM,MAAM,CAAC;AAAA,YACb,MAAM,WAAW;AAAA,YACjB,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,GAAG,WAAW,UAAU;AAAA,cACvC,KAAK,EAAE,MAAM,GAAG,WAAW,QAAQ;AAAA,YACrC;AAAA,YACA,gBAAgB;AAAA,cACd,OAAO,EAAE,MAAM,GAAG,WAAW,UAAU;AAAA,cACvC,KAAK,EAAE,MAAM,GAAG,WAAW,QAAQ;AAAA,YACrC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAGA,QAAI,oBAAoB,iBAAiB,QAAQ,OAAO,QAAQ,SAAS,kBAAkB;AACzF,YAAM,eAAe,QAAQ,MAAM,MAAM,OAAO;AAChD,YAAM,aAAa,QAAQ,MAAM,IAAI,OAAO;AAE5C,eAAS,IAAI,cAAc,IAAI,cAAc,IAAI,MAAM,QAAQ,KAAK;AAClE,cAAM,WAAW,MAAM,CAAC,EAAE,MAAM,2BAA2B;AAC3D,YAAI,UAAU;AACZ,gBAAM,UAAU,SAAS,CAAC,EAAE;AAC5B,wBAAc,SAAU,KAAK;AAAA,YAC3B,MAAM,MAAM,SAAS,CAAC;AAAA,YACtB,MAAM,WAAW;AAAA,YACjB,OAAO;AAAA,cACL,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;AAAA,cAC/B,KAAK,EAAE,MAAM,GAAG,WAAW,MAAM,CAAC,EAAE,OAAO;AAAA,YAC7C;AAAA,YACA,gBAAgB;AAAA,cACd,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE;AAAA,cAC/B,KAAK,EAAE,MAAM,GAAG,WAAW,QAAQ;AAAA,YACrC;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF;AAEA,YAAQ,KAAK,aAAa;AAAA,EAC5B;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AAEA,SAAS,oBAAoB,KAAgE;AAC3F,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,OAAOA,YAAW,IAAI,KAAK;AAAA,IAC3B,gBAAgBA,YAAW,IAAI,cAAc;AAAA,IAC7C,UAAU,IAAI,UAAU,IAAI,mBAAmB;AAAA,EACjD;AACF;AAjIA,IAmIa;AAnIb;AAAA;AAAA;AAmIO,IAAM,uBAAsC;AAAA,MACjD,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,wBAAwB;AAAA,MAC1B;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,iBAAiB,CAAC,WAAW;AAC1C,gBAAM,UAAU,uBAAuB,OAAO,aAAa,KAAK,IAAI,SAAS;AAC7E,iBAAO,QAAQ,IAAI,mBAAmB;AAAA,QACxC,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC3IA,SAAS,cAAAC,mBAAkB;AAuBpB,SAAS,uBAAuB,OAAe,WAAkD;AACtG,QAAM,aAAa,MAAM,YAAY;AACrC,QAAM,UAAiC,CAAC;AAGxC,aAAW,WAAW,UAAU,SAAS,eAAe,GAAG;AACzD,QAAI,cAAc,CAAC,QAAQ,KAAK,YAAY,EAAE,SAAS,UAAU,EAAG;AACpE,YAAQ,KAAK;AAAA,MACX,MAAM,QAAQ;AAAA,MACd,MAAMA,YAAW;AAAA,MACjB,KAAK,QAAQ;AAAA,MACb,OAAO,QAAQ;AAAA,IACjB,CAAC;AAAA,EACH;AAGA,aAAW,UAAU,UAAU,QAAQ,cAAc,GAAG;AACtD,QAAI,cAAc,CAAC,OAAO,KAAK,YAAY,EAAE,SAAS,UAAU,EAAG;AACnE,YAAQ,KAAK;AAAA,MACX,MAAM,OAAO;AAAA,MACb,MAAMA,YAAW;AAAA,MACjB,KAAK,OAAO;AAAA,MACZ,OAAO,OAAO;AAAA,IAChB,CAAC;AAAA,EACH;AAGA,aAAW,CAAC,MAAM,IAAI,KAAK,UAAU,UAAU,YAAY,GAAG;AAC5D,UAAM,cAAc,MAAM;AAC1B,QAAI,cAAc,CAAC,YAAY,YAAY,EAAE,SAAS,UAAU,EAAG;AACnE,YAAQ,KAAK;AAAA,MACX,MAAM;AAAA,MACN,MAAMA,YAAW;AAAA,MACjB,KAAK,KAAK,kBAAkB;AAAA,MAC5B,OAAO,KAAK,oBAAoB,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,EAAE,GAAG,KAAK,EAAE,MAAM,GAAG,WAAW,EAAE,EAAE;AAAA,IACrG,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AA5EA,IA8Ea;AA9Eb;AAAA;AAAA;AA8EO,IAAM,wBAAuC;AAAA,MAClD,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,yBAAyB;AAAA,MAC3B;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,kBAAkB,CAAC,WAAW;AAC3C,gBAAM,UAAU,uBAAuB,OAAO,OAAO,IAAI,SAAS;AAClE,iBAAO,QAAQ,IAAI,QAAM;AAAA,YACvB,MAAM,EAAE;AAAA,YACR,MAAM,EAAE;AAAA,YACR,UAAU;AAAA,cACR,KAAK,EAAE;AAAA,cACP,OAAOA,YAAW,EAAE,KAAK;AAAA,YAC3B;AAAA,UACF,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC5FA,SAAS,wBAAwB;AAmB1B,SAAS,qBAAqB,KAAa,WAA+C;AAC/F,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,SAA6B,CAAC;AAGpC,QAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,aAAW,WAAW,UAAU;AAC9B,UAAM,YAAY,QAAQ,MAAM,MAAM;AACtC,UAAM,UAAU,QAAQ,MAAM,IAAI;AAClC,QAAI,UAAU,WAAW;AACvB,aAAO,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA,MAAM;AAAA,MACR,CAAC;AAAA,IACH;AAAA,EACF;AAGA,QAAM,SAAS,YAAY,IAAI;AAC/B,aAAW,QAAQ,CAAC,SAAS,UAAU,OAAO,QAAQ,IAAI,CAAC;AAE3D,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,QAAQ,MAAM,SAAS,IAAI;AACnC,YAAM,eAAe,OAAO,MAAM,IAAI;AACtC,YAAM,YAAY,MAAM,MAAM,MAAM;AACpC,YAAM,UAAU,aAAa,MAAM,MAAM;AACzC,UAAI,UAAU,WAAW;AACvB,eAAO,KAAK;AAAA,UACV;AAAA,UACA;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AA9DA,IAoEa;AApEb;AAAA;AAAA;AAGA;AAiEO,IAAM,qBAAoC;AAAA,MAC/C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,sBAAsB;AAAA,MACxB;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,gBAAgB,CAAC,WAAW;AACzC,gBAAM,SAAS,qBAAqB,OAAO,aAAa,KAAK,IAAI,SAAS;AAC1E,iBAAO,OAAO,IAAI,QAAM;AAAA,YACtB,WAAW,EAAE;AAAA,YACb,SAAS,EAAE;AAAA,YACX,MAAM,EAAE,SAAS,WAAW,iBAAiB,SAAS;AAAA,UACxD,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;AC3DO,SAAS,qBAAqB,KAAa,WAA+C;AAC/F,QAAM,OAAO,UAAU,UAAU,QAAQ,GAAG;AAC5C,MAAI,SAAS,OAAW,QAAO,CAAC;AAEhC,QAAM,WAAW,UAAU,SAAS,sBAAsB,GAAG;AAC7D,MAAI,SAAS,WAAW,EAAG,QAAO,CAAC;AAEnC,QAAM,QAA4B,CAAC;AAGnC,aAAW,WAAW,UAAU;AAC9B,UAAM,mBAAmB,QAAQ,MAAM,MAAM,OAAO;AACpD,UAAM,iBAAiB,QAAQ,MAAM,IAAI,OAAO;AAChD,UAAM,QAAQ,KAAK,MAAM,IAAI;AAC7B,UAAM,eAAe,MAAM,MAAM,kBAAkB,cAAc;AACjE,UAAM,UAAU,aAAa,KAAK,IAAI;AAEtC,UAAM,eAAe,WAAW,SAAS,gBAAgB;AAEzD,eAAW,OAAO,cAAc;AAC9B,YAAM,gBAAgB,UAAU,SAAS,WAAW,IAAI,IAAI;AAC5D,UAAI;AACJ,UAAI,eAAe;AACjB,iBAAS,GAAG,cAAc,GAAG,KAAK,cAAc,MAAM,MAAM,OAAO,CAAC;AAAA,MACtE;AAEA,YAAM,KAAK;AAAA,QACT,OAAO,IAAI;AAAA,QACX;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAASC,YAAW,GAAiD;AACnE,SAAO;AAAA,IACL,OAAO,EAAE,MAAM,EAAE,MAAM,MAAM,WAAW,EAAE,MAAM,UAAU;AAAA,IAC1D,KAAK,EAAE,MAAM,EAAE,IAAI,MAAM,WAAW,EAAE,IAAI,UAAU;AAAA,EACtD;AACF;AArEA,IAuEa;AAvEb;AAAA;AAAA;AAGA;AAoEO,IAAM,qBAAoC;AAAA,MAC/C,IAAI;AAAA,MACJ,cAAc;AAAA,QACZ,sBAAsB;AAAA,UACpB,iBAAiB;AAAA,QACnB;AAAA,MACF;AAAA,MACA,WAAW,KAAoB;AAC7B,YAAI,WAAW,gBAAgB,CAAC,WAAW;AACzC,gBAAM,QAAQ,qBAAqB,OAAO,aAAa,KAAK,IAAI,SAAS;AACzE,iBAAO,MAAM,IAAI,QAAM;AAAA,YACrB,OAAOA,YAAW,EAAE,KAAK;AAAA,YACzB,QAAQ,EAAE;AAAA,UACZ,EAAE;AAAA,QACJ,CAAC;AAAA,MACH;AAAA,IACF;AAAA;AAAA;;;ACvFA,IAqBa;AArBb;AAAA;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAKO,IAAM,aAA8B;AAAA,MACzC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA;AAAA;;;ACtCA;AAAA;AAAA;AAAA;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAoB;AAC7B,SAAS,iBAAAC,gBAAe,iBAAAC,sBAAqB;AAC7C,SAAS,gBAAAC,qBAAoB;AAC7B,SAAS,QAAAC,aAAY;AAarB,SAAS,YAAY,KAAqB;AACxC,MAAI;AACF,WAAOH,eAAc,GAAG;AAAA,EAC1B,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAKA,SAAS,YAAY,QAAwB;AAC3C,SAAOC,eAAc,MAAM,EAAE,SAAS;AACxC;AAOO,SAAS,YAAY,OAAuB;AACjD,QAAM,aAAa,iBAAiB,iBAAiB,GAAG;AACxD,QAAM,YAAY,oBAAI,IAA0B;AAChD,MAAI;AACJ,MAAI,gBAAiC,CAAC;AACtC,MAAI;AAEJ,aAAW,aAAa,CAAC,WAAW;AAClC,UAAM,cAAe,OAAO,yBAAyB,CAAC;AAGtD,oBACE,YAAY,kBACX,OAAO,mBAAmB,CAAC,GAAG,MAC3B,YAAY,OAAO,iBAAiB,CAAC,EAAE,GAAG,IAC1C;AAGN,UAAM,gBAAgB,gBAClB,mBAAmB,aAAa,IAChC,EAAE,QAAQ,CAAC,EAAE;AAEjB,UAAM,SAAwB;AAAA,MAC5B,iBAAiB,YAAY;AAAA,MAC7B,aAAa,YAAY;AAAA,MACzB;AAAA,IACF;AAGA,gBAAY,IAAI,eAAe;AAG/B,oBAAgB,YAAY,YAAY,MAAM;AAG9C,eAAW,UAAU,eAAe;AAClC,aAAO,WAAW,EAAE,YAAY,WAAW,OAAO,CAAC;AAAA,IACrD;AAGA,QAAI,OAAO,KAAK,cAAc,MAAM,EAAE,SAAS,GAAG;AAChD,gBAAU,OAAO,gBAAgB,cAAc,MAAM;AAAA,IACvD;AAEA,WAAO;AAAA,MACL,cAAc,kBAAkB,aAAa;AAAA,IAC/C;AAAA,EACF,CAAC;AAED,aAAW,cAAc,YAAY;AAEnC,eAAW,OAAO,SAAS,kCAAkC,MAAM;AAAA,MACjE,UAAU;AAAA,QACR,EAAE,aAAa,UAAU;AAAA,QACzB,EAAE,aAAa,YAAY;AAAA,QAC3B,EAAE,aAAa,UAAU;AAAA,QACzB,EAAE,aAAa,UAAU;AAAA,QACzB,EAAE,aAAa,sBAAsB;AAAA,MACvC;AAAA,IACF,CAAC;AAGD,QAAI,WAAW;AACb,YAAM,eAAe,MAAM,mBAAmB,aAAa;AAC3D,gBAAU,WAAW,YAAY;AAAA,IACnC;AAAA,EACF,CAAC;AAID,aAAW,sBAAsB,CAAC,EAAE,aAAa,MAAM;AACrD,UAAM,MAAM,aAAa;AAAA,MACvB,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,MACb,aAAa;AAAA,IACf;AACA,cAAU,IAAI,aAAa,KAAK,GAAG;AACnC,QAAI,WAAW;AACb,gBAAU,UAAU,KAAK,aAAa,KAAK,aAAa,IAAI;AAAA,IAC9D;AAAA,EACF,CAAC;AAED,aAAW,wBAAwB,CAAC,EAAE,cAAc,eAAe,MAAM;AACvE,UAAM,WAAW,UAAU,IAAI,aAAa,GAAG;AAC/C,QAAI,UAAU;AACZ,YAAM,UAAU,aAAa;AAAA,QAC3B;AAAA,QACA;AAAA,QACA,aAAa;AAAA,MACf;AACA,gBAAU,IAAI,aAAa,KAAK,OAAO;AACvC,UAAI,WAAW;AACb,kBAAU,UAAU,OAAO,aAAa,KAAK,QAAQ,QAAQ,CAAC;AAAA,MAChE;AAAA,IACF;AAAA,EACF,CAAC;AAED,aAAW,uBAAuB,CAAC,EAAE,aAAa,MAAM;AACtD,cAAU,OAAO,aAAa,GAAG;AACjC,QAAI,WAAW;AACb,gBAAU,UAAU,MAAM,aAAa,GAAG;AAAA,IAC5C;AAAA,EACF,CAAC;AAID,aAAW,wBAAwB,CAAC,EAAE,QAAQ,MAAM;AAClD,QAAI,CAAC,UAAW;AAEhB,eAAW,UAAU,SAAS;AAC5B,UAAI,OAAO,SAAS,eAAe,SAAS;AAC1C,kBAAU,UAAU,MAAM,OAAO,GAAG;AACpC,kBAAU,OAAO,OAAO,GAAG;AAAA,MAC7B,OAAO;AAEL,YAAI;AACF,gBAAM,SAAS,YAAY,OAAO,GAAG;AACrC,gBAAM,OAAOC,cAAa,QAAQ,OAAO;AACzC,cAAI,UAAU,UAAU,IAAI,OAAO,GAAG,GAAG;AACvC,sBAAU,UAAU,OAAO,OAAO,KAAK,IAAI;AAAA,UAC7C,OAAO;AACL,sBAAU,UAAU,KAAK,OAAO,KAAK,IAAI;AAAA,UAC3C;AAAA,QACF,QAAQ;AAAA,QAER;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAID,aAAW,WAAW,MAAM;AAC1B,eAAW,UAAU,eAAe;AAClC,aAAO,UAAU;AAAA,IACnB;AACA,eAAW,QAAQ;AAAA,EACrB,CAAC;AAED,aAAW,OAAO;AACpB;AAKA,eAAe,mBACb,MAC8B;AAC9B,QAAM,WAAW,oBAAI,IAAoB;AACzC,MAAI,CAAC,KAAM,QAAO;AAElB,MAAI;AACF,UAAM,QAAQ,MAAMC,MAAK,kBAAkB;AAAA,MACzC,KAAK;AAAA,MACL,UAAU;AAAA,MACV,OAAO;AAAA,IACT,CAAC;AACD,eAAW,YAAY,OAAO;AAC5B,UAAI;AACF,cAAM,OAAOD,cAAa,UAAU,OAAO;AAC3C,cAAM,MAAM,YAAY,QAAQ;AAChC,iBAAS,IAAI,KAAK,IAAI;AAAA,MACxB,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF,QAAQ;AAAA,EAER;AAEA,SAAO;AACT;AAtNA;AAAA;AAAA;AAWA;AACA;AACA;AACA;AAEA;AAAA;AAAA;;;ACdA,IAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,IAAI,KAAK,CAAC,MAAM,SAAS;AACvB,QAAM,EAAE,UAAAE,UAAS,IAAI,MAAM;AAC3B,QAAM,WAAW,MAAMA,UAAS,KAAK,MAAM,CAAC,CAAC;AAC7C,UAAQ,KAAK,QAAQ;AACvB,WAAW,KAAK,CAAC,MAAM,UAAU;AAC/B,QAAM,EAAE,WAAAC,WAAU,IAAI,MAAM;AAC5B,QAAM,WAAW,MAAMA,WAAU,KAAK,MAAM,CAAC,CAAC;AAC9C,UAAQ,KAAK,QAAQ;AACvB,OAAO;AAEL,QAAM,EAAE,aAAAC,aAAY,IAAI,MAAM;AAC9B,EAAAA,aAAY,IAAI;AAClB;",
|
|
4
|
+
"sourcesContent": ["import { EventEmitter } from 'node:events';\nimport { readFileSync } from 'node:fs';\nimport { pathToFileURL } from 'node:url';\n\ninterface DocumentEntry {\n text: string;\n version: number;\n}\n\n/**\n * In-memory store for open document contents.\n * Emits events when documents are opened, changed, or closed.\n */\nexport class DocumentStore extends EventEmitter {\n private docs = new Map<string, DocumentEntry>();\n\n /** Open a document (or replace if already open). */\n open(uri: string, text: string, version?: number): void {\n this.docs.set(uri, { text, version: version ?? 0 });\n this.emit('documentOpened', uri);\n }\n\n /** Update an already-open document's text. */\n update(uri: string, text: string, version?: number): void {\n const existing = this.docs.get(uri);\n const newVersion = version ?? (existing ? existing.version + 1 : 0);\n this.docs.set(uri, { text, version: newVersion });\n this.emit('documentChanged', uri);\n }\n\n /** Close a document and remove it from the store. */\n close(uri: string): void {\n this.docs.delete(uri);\n this.emit('documentClosed', uri);\n }\n\n /** Get the text of a document, or undefined if not open. */\n getText(uri: string): string | undefined {\n return this.docs.get(uri)?.text;\n }\n\n /** Get the version of a document (0 if unknown). */\n getVersion(uri: string): number {\n return this.docs.get(uri)?.version ?? 0;\n }\n\n /** Get all open document URIs. */\n getUris(): string[] {\n return Array.from(this.docs.keys());\n }\n\n /** Check whether a document is currently open. */\n has(uri: string): boolean {\n return this.docs.has(uri);\n }\n\n /** Load files from disk (CLI mode). Converts paths to file:// URIs. */\n loadFromDisk(paths: string[]): void {\n for (const filePath of paths) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = pathToFileURL(filePath).href;\n this.open(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n }\n}\n", "import type { Range } from '../types.js';\n\nexport interface ParsedPassageHeader {\n name: string;\n tags: string[];\n meta: Record<string, unknown> | undefined;\n headerRange: Range;\n nameRange: Range;\n}\n\n/**\n * Regex for matching passage headers.\n * Captures: (1) `:: ` prefix, (2) passage name, (3) optional `[tags]`, (4) optional `{meta}`\n *\n * Derived from the reference in twee3-language-tools/src/parse-text.ts:\n * /(^::\\s*)(.*?)(\\[.*?\\]\\s*)?(\\{.*?\\}\\s*)?\\r?$/\n */\nconst passageHeaderRegex = /^(::\\s+)(.*?)(\\[.*?\\]\\s*)?(\\{.*?\\}\\s*)?\\r?$/;\n\nconst SPECIAL_PASSAGES = new Set([\n 'StoryVariables',\n 'StoryInit',\n 'StoryData',\n 'StoryTitle',\n 'StoryBanner',\n 'StoryCaption',\n 'StoryMenu',\n 'StoryInterface',\n 'StoryAuthor',\n]);\n\n/**\n * Parse a single line as a passage header.\n * Returns null if the line is not a valid passage header.\n */\nexport function parsePassageHeader(line: string, lineNumber: number): ParsedPassageHeader | null {\n // Run regex against escaped version (neutralize backslash sequences for matching)\n const escaped = line.replace(/\\\\./g, 'ec');\n const match = passageHeaderRegex.exec(escaped);\n if (!match) return null;\n\n const prefix = match[1] ?? ''; // \":: \"\n const rawName = match[2] ?? ''; // everything between prefix and tags/meta\n const rawTags = match[3] ?? ''; // \"[tag1 tag2] \" or \"\"\n const rawMeta = match[4] ?? ''; // '{\"key\":\"val\"} ' or \"\"\n\n // Extract the actual name from the original line (not escaped)\n const nameStart = prefix.length;\n const nameEnd = nameStart + rawName.length;\n const name = line.substring(nameStart, nameEnd).trim();\n\n if (!name) return null;\n\n // Reject names with unescaped meta characters\n const escapedName = name.replace(/\\\\./g, 'ec');\n if (/[\\[\\]\\{\\}]/.test(escapedName)) return null;\n\n // Parse tags\n const tagsStr = rawTags.trim();\n let tags: string[] = [];\n if (tagsStr) {\n const inner = tagsStr.substring(1, tagsStr.length - 1).trim();\n // Reject unescaped meta characters inside tags\n if (/[\\[\\]\\{\\}]/.test(inner.replace(/\\\\./g, 'ec'))) return null;\n tags = inner ? inner.split(/\\s+/) : [];\n }\n\n // Parse meta JSON\n let meta: Record<string, unknown> | undefined;\n const metaStr = rawMeta.trim();\n if (metaStr) {\n try {\n meta = JSON.parse(line.substring(nameStart + rawName.length + rawTags.length, nameStart + rawName.length + rawTags.length + rawMeta.length).trim());\n } catch {\n // Invalid JSON \u2014 treat the entire line as not a valid passage header\n return null;\n }\n }\n\n const headerRange: Range = {\n start: { line: lineNumber, character: 0 },\n end: { line: lineNumber, character: line.length },\n };\n\n // nameRange: position of the trimmed name within the line\n // The name starts right after the prefix, but the prefix may include extra whitespace.\n // We need to find where the actual name text starts (after \":: \" which is the prefix).\n const nameCharStart = prefix.length;\n const nameCharEnd = nameCharStart + name.length;\n\n const nameRange: Range = {\n start: { line: lineNumber, character: nameCharStart },\n end: { line: lineNumber, character: nameCharEnd },\n };\n\n return {\n name: name.replace(/\\\\(.)/g, '$1'), // unescape\n tags,\n meta,\n headerRange,\n nameRange,\n };\n}\n\n/**\n * Check whether a passage name is one of the special/system passages.\n */\nexport function isSpecialPassage(name: string): boolean {\n return SPECIAL_PASSAGES.has(name);\n}\n", "import type { Passage, Range } from '../types.js';\nimport { parsePassageHeader } from '../parsing/passage-parser.js';\n\n/**\n * Maintains an index of all passages across all open documents.\n * Supports lookup by name, URI, line number, and detects duplicates.\n */\nexport class PassageIndex {\n /** Per-URI list of passages. */\n private byUri = new Map<string, Passage[]>();\n\n /**\n * Parse all passage headers in the given document text and\n * store them, replacing any previous entries for this URI.\n */\n rebuild(uri: string, text: string): void {\n // Remove old entries for this URI\n this.byUri.delete(uri);\n\n const lines = text.split('\\n');\n const passages: Passage[] = [];\n\n for (let i = 0; i < lines.length; i++) {\n const header = parsePassageHeader(lines[i], i);\n if (!header) continue;\n\n // Compute the end of the passage content:\n // it extends until the next passage header or end of file.\n // For now, headerEnd is just the header line range.\n const passage: Passage = {\n name: header.name,\n range: {\n start: { line: i, character: 0 },\n end: { line: i, character: lines[i].length }, // will be extended below\n },\n headerEnd: header.headerRange,\n uri,\n tags: header.tags.length > 0 ? header.tags : undefined,\n meta: header.meta,\n };\n passages.push(passage);\n }\n\n // Extend each passage range to cover content until the next header\n for (let i = 0; i < passages.length; i++) {\n const nextStart = i + 1 < passages.length\n ? passages[i + 1].range.start.line - 1\n : lines.length - 1;\n passages[i].range = {\n start: passages[i].range.start,\n end: { line: nextStart, character: lines[nextStart]?.length ?? 0 },\n };\n }\n\n if (passages.length > 0) {\n this.byUri.set(uri, passages);\n }\n }\n\n /** Remove all passages for a URI. */\n remove(uri: string): void {\n this.byUri.delete(uri);\n }\n\n /** Get a passage by name. Returns the first match found. */\n getPassage(name: string): Passage | undefined {\n for (const passages of this.byUri.values()) {\n for (const p of passages) {\n if (p.name === name) return p;\n }\n }\n return undefined;\n }\n\n /** Get the passage containing a specific line in a document. */\n getPassageAt(uri: string, line: number): Passage | undefined {\n const passages = this.byUri.get(uri);\n if (!passages) return undefined;\n\n // Find the passage whose range contains this line\n for (let i = passages.length - 1; i >= 0; i--) {\n if (passages[i].range.start.line <= line) {\n return passages[i];\n }\n }\n return undefined;\n }\n\n /** Get all passages in a specific document. */\n getPassagesInDocument(uri: string): Passage[] {\n return this.byUri.get(uri) ?? [];\n }\n\n /** Get all passages across all documents. */\n getAllPassages(): Passage[] {\n const result: Passage[] = [];\n for (const passages of this.byUri.values()) {\n result.push(...passages);\n }\n return result;\n }\n\n /** Get the StoryVariables passage, if any. */\n getStoryVariables(): Passage | undefined {\n return this.getPassage('StoryVariables');\n }\n\n /** Get the StoryInit passage, if any. */\n getStoryInit(): Passage | undefined {\n return this.getPassage('StoryInit');\n }\n\n /**\n * Find passage names that appear more than once across all documents.\n * Returns a map from name to the list of duplicate Passage objects.\n */\n getDuplicates(): Map<string, Passage[]> {\n const byName = new Map<string, Passage[]>();\n for (const passages of this.byUri.values()) {\n for (const p of passages) {\n const existing = byName.get(p.name);\n if (existing) {\n existing.push(p);\n } else {\n byName.set(p.name, [p]);\n }\n }\n }\n\n const duplicates = new Map<string, Passage[]>();\n for (const [name, passages] of byName) {\n if (passages.length > 1) {\n duplicates.set(name, passages);\n }\n }\n return duplicates;\n }\n}\n", "import { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join, parse as parsePath } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport type { MacroInfo, ChildConstraint } from '../types.js';\n\n/**\n * Supplement entry as found in macro-supplements.json or user config.\n * Uses `container` (boolean) which maps to `block` on MacroInfo.\n */\ninterface SupplementEntry {\n name?: string;\n description?: string;\n parameters?: string[];\n container?: boolean;\n children?: ChildConstraint[];\n parents?: string[];\n skipArgs?: boolean;\n}\n\n/** Shape of entries in @rohal12/spindle's macro-registry.json */\ninterface BuiltinMacroEntry {\n name: string;\n block: boolean;\n subMacros: string[];\n storeVar?: boolean;\n interpolate?: boolean;\n merged?: boolean;\n source: string;\n}\n\n/**\n * Registry of all known macros, merging data from three tiers:\n * 1. Builtins \u2014 from @rohal12/spindle/tooling getMacroRegistry()\n * 2. Supplements \u2014 macro-supplements.json (descriptions, parameters, children)\n * 3. User config \u2014 workspace-level overrides\n *\n * All lookups are case-insensitive.\n */\nexport class MacroRegistry {\n private macros = new Map<string, MacroInfo>();\n\n /**\n * Load built-in macro metadata from @rohal12/spindle's macro-registry.json.\n * This is the base layer that provides name, block, subMacros, flags, source.\n */\n /** Warnings collected during loadBuiltins for logging. */\n readonly warnings: string[] = [];\n\n loadBuiltins(): void {\n let builtinMacros: BuiltinMacroEntry[] = [];\n\n try {\n // Resolve the macro-registry.json from @rohal12/spindle package.\n // Walk up from this file's directory to find node_modules.\n const thisDir = dirname(fileURLToPath(import.meta.url));\n const registryPath = this.resolveRegistryPath(thisDir);\n if (registryPath) {\n const raw = readFileSync(registryPath, 'utf-8');\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) {\n this.warnings.push(\n `macro-registry.json: expected array, got ${typeof parsed}. Continuing with supplements only.`,\n );\n } else {\n builtinMacros = parsed;\n }\n }\n } catch (err: unknown) {\n // Package not available or malformed \u2014 log and continue with supplements only\n const message = err instanceof Error ? err.message : String(err);\n this.warnings.push(\n `Failed to load builtin macros: ${message}. Continuing with supplements only.`,\n );\n }\n\n for (const m of builtinMacros) {\n try {\n const key = m.name.toLowerCase();\n this.macros.set(key, {\n name: m.name,\n block: m.block,\n subMacros: m.subMacros ?? [],\n storeVar: m.storeVar,\n interpolate: m.interpolate,\n merged: m.merged,\n source: m.source === 'builtin' ? 'builtin' : 'user',\n });\n } catch {\n // Skip malformed entries\n this.warnings.push(`Skipped malformed builtin macro entry: ${JSON.stringify(m)}`);\n }\n }\n }\n\n /**\n * Overlay supplement data onto the registry.\n * Supplements provide descriptions, parameters, children, parents, skipArgs.\n * The `container` field maps to `block` on MacroInfo.\n */\n loadSupplements(supplements: Record<string, SupplementEntry>): void {\n this.mergeEntries(supplements);\n }\n\n /**\n * Overlay user config onto the registry.\n * Same format as supplements; applied last so it wins.\n */\n loadConfig(config: Record<string, SupplementEntry>): void {\n this.mergeEntries(config);\n }\n\n /** Add or replace a single macro entry. */\n addMacro(info: Partial<MacroInfo> & { name: string }): void {\n const key = info.name.toLowerCase();\n const existing = this.macros.get(key);\n this.macros.set(key, {\n name: info.name,\n block: info.block ?? existing?.block ?? false,\n subMacros: info.subMacros ?? existing?.subMacros ?? [],\n source: info.source ?? existing?.source ?? 'user',\n storeVar: info.storeVar ?? existing?.storeVar,\n interpolate: info.interpolate ?? existing?.interpolate,\n merged: info.merged ?? existing?.merged,\n description: info.description ?? existing?.description,\n parameters: info.parameters ?? existing?.parameters,\n children: info.children ?? existing?.children,\n parents: info.parents ?? existing?.parents,\n skipArgs: info.skipArgs ?? existing?.skipArgs,\n });\n }\n\n /** Get a macro by name (case-insensitive). */\n getMacro(name: string): MacroInfo | undefined {\n return this.macros.get(name.toLowerCase());\n }\n\n /** Check if a macro is a block (container) macro. */\n isBlock(name: string): boolean {\n return this.macros.get(name.toLowerCase())?.block ?? false;\n }\n\n /** Check if a macro is a sub-macro (has parents). */\n isSubMacro(name: string): boolean {\n const info = this.macros.get(name.toLowerCase());\n return (info?.parents != null && info.parents.length > 0);\n }\n\n /** Get all registered macros. */\n getAllMacros(): MacroInfo[] {\n return Array.from(this.macros.values());\n }\n\n /**\n * Walk up directory tree from `startDir` to find the\n * @rohal12/spindle/dist/pkg/macro-registry.json file.\n */\n private resolveRegistryPath(startDir: string): string | null {\n const target = join('node_modules', '@rohal12', 'spindle', 'dist', 'pkg', 'macro-registry.json');\n let dir = startDir;\n const { root } = parsePath(dir);\n while (dir !== root) {\n const candidate = join(dir, target);\n if (existsSync(candidate)) {\n return candidate;\n }\n dir = dirname(dir);\n }\n return null;\n }\n\n /** Merge a set of supplement/config entries into the registry. */\n private mergeEntries(entries: Record<string, SupplementEntry>): void {\n for (const [rawKey, entry] of Object.entries(entries)) {\n const key = rawKey.toLowerCase();\n const existing = this.macros.get(key);\n\n if (existing) {\n // Overlay fields \u2014 supplement fields win when present\n if (entry.description !== undefined) existing.description = entry.description;\n if (entry.parameters !== undefined) existing.parameters = entry.parameters;\n if (entry.children !== undefined) existing.children = entry.children;\n if (entry.parents !== undefined) existing.parents = entry.parents;\n if (entry.skipArgs !== undefined) existing.skipArgs = entry.skipArgs;\n if (entry.container !== undefined) existing.block = entry.container;\n } else {\n // Create a new entry from the supplement\n this.macros.set(key, {\n name: entry.name ?? rawKey,\n block: entry.container ?? false,\n subMacros: [],\n source: 'user',\n description: entry.description,\n parameters: entry.parameters,\n children: entry.children,\n parents: entry.parents,\n skipArgs: entry.skipArgs,\n });\n }\n }\n }\n}\n", "import type { DeclaredVariable, MacroNode, Range } from '../types.js';\nimport { parsePassageHeader } from '../parsing/passage-parser.js';\n\n/** Regex to match $variable references including dot notation. */\nconst varRefRegex = /\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n\n/** Passages excluded from variable scanning. */\nconst EXCLUDED_PASSAGES = new Set([\n 'StoryVariables', 'StoryInit', 'StoryData', 'StoryScript', 'StoryInterface',\n]);\n\n/** Patterns that should be stripped before scanning for variable references. */\nconst CLEAN_PATTERNS = [\n /<!--[\\s\\S]*?-->/g, // HTML comments\n /<script(?:\\s+[^>]*)?>[\\s\\S]*?<\\/script>/gi, // script tags\n /<style>[\\s\\S]*?<\\/style>/gi, // style tags\n /`(?:\\\\.|[^`\\\\])*`/g, // backtick strings\n /\"(?:\\\\.|[^\"\\\\])*\"/g, // double-quoted strings\n /'(?:\\\\.|[^'\\\\])*'/g, // single-quoted strings\n];\n\ninterface VariableUsage {\n uri: string;\n baseName: string;\n fullName: string;\n range: Range;\n}\n\n/**\n * Tracks declared variables (from StoryVariables) and variable usages across documents.\n */\nexport class VariableTracker {\n private declared = new Map<string, DeclaredVariable>();\n private _hasStoryVariables = false;\n\n /** Per-URI list of variable usages. */\n private usagesByUri = new Map<string, VariableUsage[]>();\n\n /**\n * Parse the StoryVariables passage content for declarations.\n * Each line like `$name = value` becomes a declaration.\n */\n parseStoryVariables(content: string): void {\n this.declared.clear();\n this._hasStoryVariables = true;\n\n const lines = content.split('\\n');\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('//') || trimmed.startsWith('<!--')) continue;\n\n const match = /^\\$([A-Za-z_$][\\w$]*)\\s*=\\s*(.*)$/.exec(trimmed);\n if (!match) continue;\n\n const name = match[1];\n const expr = match[2].trim();\n const decl: DeclaredVariable = { name, sigil: '$' };\n\n // Extract top-level object fields for dot-notation validation\n if (expr.startsWith('{')) {\n const fieldRegex = /(\\w+)\\s*:/g;\n let fieldMatch;\n const fields: string[] = [];\n while ((fieldMatch = fieldRegex.exec(expr)) !== null) {\n fields.push(fieldMatch[1]);\n }\n if (fields.length > 0) {\n decl.fields = fields;\n }\n }\n\n this.declared.set(name, decl);\n }\n }\n\n /**\n * Scan a document for variable usages.\n * Identifies passages in the document and scans non-special ones.\n */\n scanDocument(uri: string, text: string, _macros: MacroNode[]): void {\n // Clear previous usages for this URI\n this.usagesByUri.delete(uri);\n\n const lines = text.split('\\n');\n const usages: VariableUsage[] = [];\n\n // Find all passage boundaries in the document\n const passageBoundaries: Array<{ name: string; startLine: number }> = [];\n for (let i = 0; i < lines.length; i++) {\n const header = parsePassageHeader(lines[i], i);\n if (header) {\n passageBoundaries.push({ name: header.name, startLine: i });\n }\n }\n\n // Scan each passage's content\n for (let pi = 0; pi < passageBoundaries.length; pi++) {\n const passage = passageBoundaries[pi];\n if (EXCLUDED_PASSAGES.has(passage.name)) continue;\n\n const contentStartLine = passage.startLine + 1;\n const contentEndLine = pi + 1 < passageBoundaries.length\n ? passageBoundaries[pi + 1].startLine\n : lines.length;\n\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n const content = contentLines.join('\\n');\n\n // Clean the content to avoid scanning inside strings/comments\n let cleaned = content;\n for (const pattern of CLEAN_PATTERNS) {\n cleaned = cleaned.replace(pattern, (m) => ' '.repeat(m.length));\n }\n\n // Build line offsets for this content block\n const lineOffsets: number[] = [0];\n for (let i = 0; i < cleaned.length; i++) {\n if (cleaned[i] === '\\n') lineOffsets.push(i + 1);\n }\n\n // Find variable references\n const re = new RegExp(varRefRegex.source, 'g');\n let match;\n while ((match = re.exec(cleaned)) !== null) {\n const fullName = match[1];\n const baseName = fullName.split('.')[0];\n const charOffset = match.index;\n\n // Convert offset to line/character within content block\n let localLine = 0;\n for (let i = 0; i < lineOffsets.length; i++) {\n if (lineOffsets[i] > charOffset) break;\n localLine = i;\n }\n const character = charOffset - lineOffsets[localLine];\n const absoluteLine = contentStartLine + localLine;\n\n const range: Range = {\n start: { line: absoluteLine, character },\n end: { line: absoluteLine, character: character + match[0].length },\n };\n\n usages.push({ uri, baseName, fullName, range });\n }\n }\n\n if (usages.length > 0) {\n this.usagesByUri.set(uri, usages);\n }\n }\n\n /** Get all declared variables. */\n getDeclared(): Map<string, DeclaredVariable> {\n return this.declared;\n }\n\n /** Get all usages of a variable by base name. */\n getUsages(name: string): Array<{ uri: string; range: Range }> {\n const results: Array<{ uri: string; range: Range }> = [];\n for (const usages of this.usagesByUri.values()) {\n for (const u of usages) {\n if (u.baseName === name) {\n results.push({ uri: u.uri, range: u.range });\n }\n }\n }\n return results;\n }\n\n /** Get undeclared variable usages in a specific document. */\n getUndeclared(uri: string): Array<{ name: string; range: Range }> {\n const usages = this.usagesByUri.get(uri);\n if (!usages) return [];\n\n const results: Array<{ name: string; range: Range }> = [];\n const seen = new Set<string>();\n\n for (const u of usages) {\n if (!this.declared.has(u.baseName) && !seen.has(u.baseName)) {\n seen.add(u.baseName);\n results.push({ name: u.baseName, range: u.range });\n }\n }\n return results;\n }\n\n /** Whether a StoryVariables passage has been parsed. */\n hasStoryVariables(): boolean {\n return this._hasStoryVariables;\n }\n}\n", "import type { Passage, WidgetDef, Range } from '../types.js';\n\n/** Regex matching {widget \"name\" @param1 @param2} definitions. */\nconst widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"((?:\\s+@[A-Za-z_$][\\w$]*)*)\\s*\\}/gi;\n\n/** Regex extracting individual @param names from the parameter string. */\nconst paramRegex = /@([A-Za-z_$][\\w$]*)/g;\n\n/**\n * Registry of user-defined widgets.\n * Scans passages tagged [widget] for {widget \"name\" @params} definitions.\n */\nexport class WidgetRegistry {\n private widgets = new Map<string, WidgetDef>();\n\n /**\n * Scan all passages for widget definitions.\n * Only passages tagged `widget` are examined.\n *\n * @param passages - All known passages.\n * @param getContent - Function to retrieve document text by URI.\n */\n scan(passages: Passage[], getContent: (uri: string) => string | undefined): void {\n this.widgets.clear();\n\n for (const passage of passages) {\n if (!passage.tags?.includes('widget')) continue;\n\n const text = getContent(passage.uri);\n if (!text) continue;\n\n // Get the passage content (lines after the header)\n const lines = text.split('\\n');\n const contentStartLine = passage.range.start.line + 1;\n // Find the end of this passage (next header or EOF)\n let contentEndLine = lines.length;\n for (let i = contentStartLine; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEndLine = i;\n break;\n }\n }\n\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n\n for (let i = 0; i < contentLines.length; i++) {\n const line = contentLines[i];\n widgetDefRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = widgetDefRegex.exec(line)) !== null) {\n const widgetName = match[1];\n const paramString = match[2] || '';\n const params: string[] = [];\n let paramMatch: RegExpExecArray | null;\n paramRegex.lastIndex = 0;\n while ((paramMatch = paramRegex.exec(paramString)) !== null) {\n params.push(paramMatch[1]);\n }\n\n const lineNum = contentStartLine + i;\n const charStart = match.index;\n const charEnd = charStart + match[0].length;\n\n const range: Range = {\n start: { line: lineNum, character: charStart },\n end: { line: lineNum, character: charEnd },\n };\n\n this.widgets.set(widgetName, {\n name: widgetName,\n params,\n uri: passage.uri,\n range,\n });\n }\n }\n }\n }\n\n /** Get a widget definition by name. */\n getWidget(name: string): WidgetDef | undefined {\n return this.widgets.get(name);\n }\n\n /** Get all registered widget definitions. */\n getAllWidgets(): WidgetDef[] {\n return Array.from(this.widgets.values());\n }\n}\n", "import type { MacroNode, Range } from '../types.js';\n\n/**\n * Regex for variable interpolation: {$var}, {_var}, {@var}\n * These must be neutralized before macro parsing to avoid false matches.\n */\nconst variableInterpolationRegex = /(?<!\\\\)\\{([$_@][A-Za-z_$][\\w$.]*)\\}/g;\n\n/**\n * Spindle macro regex.\n * Groups:\n * 1 = closing slash (/) \u2014 present for closing macros\n * 2 = CSS prefix (e.g. \".red#alert \")\n * 3 = macro name\n * 4 = raw arguments\n */\nconst macroRegex = /(?<!\\\\)\\{(\\/)?(?:((?:[#.][a-zA-Z][\\w-]*\\s*)*)([A-Za-z][\\w-]*))(?:\\s+((?:(?:`(?:\\\\.|[^`\\\\])*?`)|(?:\"(?:\\\\.|[^\"\\\\])*?\")|(?:'(?:\\\\.|[^'\\\\])*?')|(?:\\[(?:[<>]?[Ii][Mm][Gg])?\\[[^\\r\\n]*?\\]\\]+)|[^}]|(?:}))*?))?\\}/gmi;\n\n/**\n * Build an array of line-start offsets from text.\n * lineStarts[i] is the character offset where line i begins.\n */\nfunction buildLineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) {\n if (text[i] === '\\n') {\n starts.push(i + 1);\n }\n }\n return starts;\n}\n\n/**\n * Convert a character offset to a line/character Position\n * using precomputed line-start offsets.\n */\nfunction offsetToPosition(offset: number, lineStarts: number[]): { line: number; character: number } {\n // Binary search for the line containing this offset\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const mid = (low + high + 1) >> 1;\n if (lineStarts[mid] <= offset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return { line: low, character: offset - lineStarts[low] };\n}\n\n/**\n * Parse all macros from the given text.\n *\n * Variable interpolation patterns ({$var}, {_var}, {@var}) are replaced with\n * same-length placeholder text before regex matching, preserving character offsets.\n */\nexport function parseMacros(text: string): MacroNode[] {\n // Replace variable interpolation with same-length spaces to preserve offsets\n const cleaned = text.replace(variableInterpolationRegex, (match) => {\n return ' '.repeat(match.length);\n });\n\n const lineStarts = buildLineStarts(text);\n const macros: MacroNode[] = [];\n let id = 0;\n\n // Reset regex state (global regex)\n macroRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = macroRegex.exec(cleaned)) !== null) {\n const closeSlash = match[1];\n const cssPrefix = (match[2] || '').trim();\n const macroName = match[3];\n const rawArgs = match[4];\n\n const open = closeSlash !== '/';\n\n const matchStart = match.index;\n const matchEnd = matchStart + match[0].length;\n\n const startPos = offsetToPosition(matchStart, lineStarts);\n const endPos = offsetToPosition(matchEnd, lineStarts);\n\n const range: Range = {\n start: startPos,\n end: endPos,\n };\n\n macros.push({\n id,\n pair: -1,\n name: macroName,\n open,\n range,\n cssPrefix: cssPrefix || undefined,\n rawArgs: rawArgs || undefined,\n });\n\n id++;\n }\n\n return macros;\n}\n\n/**\n * Pair opening and closing macros using a name-keyed stack algorithm.\n *\n * For each opening macro where isBlock(name) returns true, push onto a\n * per-name stack. For each closing macro, pop the matching opening macro\n * and set both their pair fields to each other's id.\n *\n * Unmatched macros keep pair = -1.\n */\nexport function pairMacros(macros: MacroNode[], isBlock: (name: string) => boolean): void {\n const stacks: Record<string, number[]> = {};\n\n for (const macro of macros) {\n const name = macro.name.toLowerCase();\n\n if (!isBlock(macro.name)) continue;\n\n if (macro.open) {\n if (!stacks[name]) stacks[name] = [];\n stacks[name].push(macro.id);\n } else {\n // Closing macro \u2014 pop the matching opening macro\n const stack = stacks[name];\n if (stack && stack.length > 0) {\n const openId = stack.pop()!;\n macros[openId].pair = macro.id;\n macro.pair = openId;\n }\n }\n }\n}\n", "{\n \"if\": {\n \"name\": \"if\",\n \"children\": [\n { \"name\": \"else\", \"max\": 1 },\n { \"name\": \"elseif\" }\n ],\n \"container\": true,\n \"description\": \"Conditionally displays its contents based on the given expression.\\n\\nUsage:\\n\\n```\\n{if condition}\\n ...\\n{elseif condition}\\n ...\\n{else}\\n ...\\n{/if}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"elseif\": {\n \"name\": \"elseif\",\n \"parents\": [\"if\"],\n \"description\": \"Used within `{if}` to provide an additional conditional branch.\\n\\nUsage: `{elseif condition}`\",\n \"parameters\": [\"...text\"]\n },\n \"else\": {\n \"name\": \"else\",\n \"parents\": [\"if\"],\n \"description\": \"Used within `{if}` to provide a fallback branch.\\n\\nUsage: `{else}`\",\n \"parameters\": []\n },\n \"for\": {\n \"name\": \"for\",\n \"children\": [\n { \"name\": \"next\" },\n { \"name\": \"stop\" }\n ],\n \"container\": true,\n \"description\": \"Loop block. Usage: `{for @item of $list}...{/for}` or `{for @item, @index of $list}...{/for}`\",\n \"skipArgs\": true\n },\n \"next\": {\n \"name\": \"next\",\n \"parents\": [\"for\"],\n \"description\": \"Continues to the next iteration of a `{for}` loop.\\n\\nUsage: `{next}`\",\n \"parameters\": []\n },\n \"stop\": {\n \"name\": \"stop\",\n \"parents\": [\"for\", \"repeat\"],\n \"description\": \"Breaks out of a `{for}` or `{repeat}` loop.\\n\\nUsage: `{stop}`\",\n \"parameters\": []\n },\n \"switch\": {\n \"name\": \"switch\",\n \"children\": [\n { \"name\": \"case\", \"min\": 1 },\n { \"name\": \"default\", \"max\": 1 }\n ],\n \"container\": true,\n \"description\": \"Evaluates an expression and executes the matching `{case}` branch.\\n\\nUsage:\\n\\n```\\n{switch expression}\\n {case value1}\\n ...\\n {case value2}\\n ...\\n {default}\\n ...\\n{/switch}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"case\": {\n \"name\": \"case\",\n \"parents\": [\"switch\"],\n \"description\": \"Defines a branch within a `{switch}` macro.\\n\\nUsage: `{case value}`\",\n \"parameters\": [\"...text\"]\n },\n \"default\": {\n \"name\": \"default\",\n \"parents\": [\"switch\"],\n \"description\": \"Defines the default branch within a `{switch}` macro.\\n\\nUsage: `{default}`\",\n \"parameters\": []\n },\n \"set\": {\n \"name\": \"set\",\n \"description\": \"Sets variables based on the given expression.\\n\\nUsage: `{set $var to value}`\\n\\nSupports `$var` (story), `_var` (temporary), and `@var` (local) variables.\",\n \"parameters\": [\"...text\"]\n },\n \"unset\": {\n \"name\": \"unset\",\n \"description\": \"Unsets one or more variables.\\n\\nUsage: `{unset $var}`\",\n \"parameters\": [\"...text\"]\n },\n \"computed\": {\n \"name\": \"computed\",\n \"description\": \"Evaluates an expression and outputs the result.\\n\\nUsage: `{computed expression}`\",\n \"parameters\": [\"...text\"]\n },\n \"print\": {\n \"name\": \"print\",\n \"description\": \"Outputs the result of the given expression.\\n\\nUsage: `{print expression}`\",\n \"parameters\": [\"...text\"]\n },\n \"do\": {\n \"name\": \"do\",\n \"container\": true,\n \"description\": \"Displays its contents. Can be updated dynamically.\\n\\nUsage:\\n\\n```\\n{do}\\n ...\\n{/do}\\n```\",\n \"parameters\": []\n },\n \"link\": {\n \"name\": \"link\",\n \"container\": true,\n \"description\": \"Creates a link that executes its contents when clicked.\\n\\nUsage:\\n\\n```\\n{link \\\"text\\\" \\\"passage\\\"}\\n ...\\n{/link}\\n```\",\n \"parameters\": [\"text |+ text\", \"\"]\n },\n \"button\": {\n \"name\": \"button\",\n \"container\": true,\n \"description\": \"Creates a button that executes its contents when clicked.\\n\\nUsage:\\n\\n```\\n{button \\\"text\\\" \\\"passage\\\"}\\n ...\\n{/button}\\n```\",\n \"parameters\": [\"text |+ text\", \"\"]\n },\n \"timed\": {\n \"name\": \"timed\",\n \"children\": [\n { \"name\": \"next\" }\n ],\n \"container\": true,\n \"description\": \"Displays its contents after a specified delay.\\n\\nUsage:\\n\\n```\\n{timed delay}\\n ...\\n {next delay}\\n ...\\n{/timed}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"repeat\": {\n \"name\": \"repeat\",\n \"children\": [\n { \"name\": \"stop\" }\n ],\n \"container\": true,\n \"description\": \"Repeatedly displays its contents at the specified interval.\\n\\nUsage:\\n\\n```\\n{repeat delay}\\n ...\\n{/repeat}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"type\": {\n \"name\": \"type\",\n \"container\": true,\n \"description\": \"Outputs its contents one character at a time, mimicking a typewriter effect.\\n\\nUsage:\\n\\n```\\n{type speed}\\n ...\\n{/type}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"listbox\": {\n \"name\": \"listbox\",\n \"children\": [\n { \"name\": \"option\", \"min\": 1 }\n ],\n \"container\": true,\n \"description\": \"Creates a dropdown listbox.\\n\\nUsage:\\n\\n```\\n{listbox \\\"$receiver\\\"}\\n {option \\\"label1\\\"}\\n {option \\\"label2\\\"}\\n{/listbox}\\n```\",\n \"parameters\": [\"receiver\"]\n },\n \"cycle\": {\n \"name\": \"cycle\",\n \"children\": [\n { \"name\": \"option\", \"min\": 1 }\n ],\n \"container\": true,\n \"description\": \"Creates a cycling link.\\n\\nUsage:\\n\\n```\\n{cycle \\\"$receiver\\\"}\\n {option \\\"label1\\\"}\\n {option \\\"label2\\\"}\\n{/cycle}\\n```\",\n \"parameters\": [\"receiver\"]\n },\n \"option\": {\n \"name\": \"option\",\n \"parents\": [\"listbox\", \"cycle\"],\n \"description\": \"Defines an option within a `{listbox}` or `{cycle}` macro.\\n\\nUsage: `{option label}`\",\n \"parameters\": [\"|+ text &+ text\", \"text\"]\n },\n \"widget\": {\n \"name\": \"widget\",\n \"container\": true,\n \"description\": \"Defines a custom widget (macro).\\n\\nUsage:\\n\\n```\\n{widget \\\"name\\\"}\\n ...\\n{/widget}\\n```\",\n \"parameters\": [\"...text\"]\n },\n \"meter\": {\n \"name\": \"meter\",\n \"description\": \"Displays a progress meter.\\n\\nUsage: `{meter $var min max}`\",\n \"parameters\": [\"...text\"]\n },\n \"goto\": {\n \"name\": \"goto\",\n \"description\": \"Navigates to the specified passage.\\n\\nUsage: `{goto \\\"passage\\\"}`\",\n \"parameters\": [\"text\"]\n },\n \"back\": {\n \"name\": \"back\",\n \"description\": \"Creates a link or navigates to the previous passage in history.\\n\\nUsage: `{back}`\",\n \"parameters\": []\n },\n \"forward\": {\n \"name\": \"forward\",\n \"description\": \"Creates a link or navigates to the next passage in history.\\n\\nUsage: `{forward}`\",\n \"parameters\": []\n },\n \"restart\": {\n \"name\": \"restart\",\n \"description\": \"Restarts the story.\\n\\nUsage: `{restart}`\",\n \"parameters\": []\n },\n \"include\": {\n \"name\": \"include\",\n \"description\": \"Outputs the contents of the specified passage.\\n\\nUsage: `{include \\\"passage\\\"}`\",\n \"parameters\": [\"text\"]\n },\n \"passage\": {\n \"name\": \"passage\",\n \"description\": \"Outputs the name of the current passage.\\n\\nUsage: `{passage}`\",\n \"parameters\": []\n },\n \"textbox\": {\n \"name\": \"textbox\",\n \"description\": \"Creates a text input box.\\n\\nUsage: `{textbox \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"numberbox\": {\n \"name\": \"numberbox\",\n \"description\": \"Creates a number input box.\\n\\nUsage: `{numberbox \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"textarea\": {\n \"name\": \"textarea\",\n \"description\": \"Creates a multi-line text input area.\\n\\nUsage: `{textarea \\\"$receiver\\\" defaultValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"checkbox\": {\n \"name\": \"checkbox\",\n \"description\": \"Creates a checkbox input.\\n\\nUsage: `{checkbox \\\"$receiver\\\" uncheckedValue checkedValue}`\",\n \"parameters\": [\"receiver &+ text\"]\n },\n \"radiobutton\": {\n \"name\": \"radiobutton\",\n \"description\": \"Creates a radio button input.\\n\\nUsage: `{radiobutton \\\"$receiver\\\" value}`\",\n \"parameters\": [\"receiver &+ text &+ text\"]\n },\n \"quicksave\": {\n \"name\": \"quicksave\",\n \"description\": \"Performs a quick save of the current story state.\\n\\nUsage: `{quicksave}`\",\n \"parameters\": []\n },\n \"quickload\": {\n \"name\": \"quickload\",\n \"description\": \"Loads the most recent quick save.\\n\\nUsage: `{quickload}`\",\n \"parameters\": []\n },\n \"saves\": {\n \"name\": \"saves\",\n \"description\": \"Opens the saves dialog.\\n\\nUsage: `{saves}`\",\n \"parameters\": []\n },\n \"settings\": {\n \"name\": \"settings\",\n \"description\": \"Opens the settings dialog.\\n\\nUsage: `{settings}`\",\n \"parameters\": []\n },\n \"story-title\": {\n \"name\": \"story-title\",\n \"description\": \"Outputs the story title.\\n\\nUsage: `{story-title}`\",\n \"parameters\": []\n },\n \"dialog\": {\n \"name\": \"dialog\",\n \"container\": true,\n \"description\": \"Opens a dialog with its contents.\\n\\nUsage:\\n\\n```\\n{dialog \\\"title\\\"}\\n ...\\n{/dialog}\\n```\",\n \"parameters\": [\"text\"]\n },\n \"nobr\": {\n \"name\": \"nobr\",\n \"container\": true,\n \"description\": \"Removes line breaks from its contents.\\n\\nUsage:\\n\\n```\\n{nobr}\\n ...\\n{/nobr}\\n```\",\n \"parameters\": []\n },\n \"span\": {\n \"name\": \"span\",\n \"container\": true,\n \"description\": \"Wraps its contents in a `<span>` element.\\n\\nUsage:\\n\\n```\\n{span}\\n ...\\n{/span}\\n```\",\n \"parameters\": []\n },\n \"save-manager\": {\n \"name\": \"save-manager\",\n \"description\": \"Renders the save/load UI.\\n\\nUsage: `{save-manager}`\",\n \"parameters\": []\n },\n \"settings-controls\": {\n \"name\": \"settings-controls\",\n \"description\": \"Renders the settings controls UI.\\n\\nUsage: `{settings-controls}`\",\n \"parameters\": []\n },\n \"watch\": {\n \"name\": \"watch\",\n \"description\": \"Watches a variable for changes and triggers a re-render.\\n\\nUsage: `{watch $var}`\",\n \"parameters\": [\"...text\"]\n },\n \"unwatch\": {\n \"name\": \"unwatch\",\n \"description\": \"Stops watching a variable.\\n\\nUsage: `{unwatch $var}`\",\n \"parameters\": [\"...text\"]\n }\n}\n", "import { EventEmitter } from 'node:events';\nimport { DocumentStore } from './document-store.js';\nimport { PassageIndex } from './passage-index.js';\nimport { MacroRegistry } from './macro-registry.js';\nimport { VariableTracker } from './variable-tracker.js';\nimport { WidgetRegistry } from './widget-registry.js';\nimport { parseMacros } from '../parsing/macro-parser.js';\nimport supplements from '../../macro-supplements.json' with { type: 'json' };\n\nexport interface WorkspaceModelConfig {\n disabledPlugins?: string[];\n}\n\n/**\n * Orchestrates all workspace-level data structures.\n *\n * Event cascade on document change:\n * document change \u2192 passage rebuild \u2192 widget/variable rescan \u2192 emit 'modelReady'\n *\n * Changes are debounced at 200ms for rapid edits.\n */\nexport class WorkspaceModel extends EventEmitter {\n readonly documents: DocumentStore;\n readonly passages: PassageIndex;\n readonly macros: MacroRegistry;\n readonly variables: VariableTracker;\n readonly widgets: WidgetRegistry;\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null;\n private readonly DEBOUNCE_MS = 200;\n\n /** Bound listeners for cleanup in dispose(). */\n private onDocumentChanged: (uri: string) => void;\n private onDocumentOpened: (uri: string) => void;\n private onDocumentClosed: (uri: string) => void;\n\n constructor(config?: WorkspaceModelConfig) {\n super();\n this.documents = new DocumentStore();\n this.passages = new PassageIndex();\n this.macros = new MacroRegistry();\n this.variables = new VariableTracker();\n this.widgets = new WidgetRegistry();\n\n // Bind event handlers\n this.onDocumentChanged = (uri: string) => this.handleDocumentChange(uri);\n this.onDocumentOpened = (uri: string) => this.handleDocumentChange(uri);\n this.onDocumentClosed = (uri: string) => this.handleDocumentClose(uri);\n\n // Wire up the event cascade\n this.documents.on('documentChanged', this.onDocumentChanged);\n this.documents.on('documentOpened', this.onDocumentOpened);\n this.documents.on('documentClosed', this.onDocumentClosed);\n }\n\n /**\n * Initialize the workspace in CLI/batch mode.\n * Loads all file contents, builds indices, and emits 'modelReady'.\n */\n initialize(fileContents: Map<string, string>): void {\n // Load macros first (builtins + supplements)\n this.macros.loadBuiltins();\n this.macros.loadSupplements(supplements as Record<string, any>);\n\n // Load all documents (this triggers documentOpened for each, which\n // will rebuild passages, but we do a bulk rebuild below anyway)\n // Temporarily detach listeners to avoid per-document cascading\n this.documents.removeListener('documentOpened', this.onDocumentOpened);\n this.documents.removeListener('documentChanged', this.onDocumentChanged);\n\n for (const [uri, text] of fileContents) {\n this.documents.open(uri, text);\n }\n\n // Reattach listeners\n this.documents.on('documentOpened', this.onDocumentOpened);\n this.documents.on('documentChanged', this.onDocumentChanged);\n\n // Bulk rebuild\n this.rebuildAll();\n\n // Schedule modelReady emission\n this.scheduleModelReady();\n }\n\n /** Clean up listeners and timers. */\n dispose(): void {\n this.documents.removeListener('documentChanged', this.onDocumentChanged);\n this.documents.removeListener('documentOpened', this.onDocumentOpened);\n this.documents.removeListener('documentClosed', this.onDocumentClosed);\n\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n this.debounceTimer = null;\n }\n\n this.removeAllListeners();\n }\n\n /** Handle a document change: rebuild passages for that document, then cascade. */\n private handleDocumentChange(uri: string): void {\n const text = this.documents.getText(uri);\n if (text !== undefined) {\n this.passages.rebuild(uri, text);\n }\n this.cascade();\n this.emit('documentChanged', uri);\n this.emit('passagesUpdated', uri);\n this.scheduleModelReady();\n }\n\n /** Handle a document close: remove its passages and cascade. */\n private handleDocumentClose(uri: string): void {\n this.passages.remove(uri);\n this.cascade();\n this.emit('documentClosed', uri);\n this.emit('passagesUpdated', uri);\n this.scheduleModelReady();\n }\n\n /** Rebuild all indices from scratch. */\n private rebuildAll(): void {\n for (const uri of this.documents.getUris()) {\n const text = this.documents.getText(uri);\n if (text !== undefined) {\n this.passages.rebuild(uri, text);\n }\n }\n this.cascade();\n }\n\n /**\n * Cascade: rescan variables and widgets based on current passages.\n * Called after any passage index update.\n */\n private cascade(): void {\n // Rescan StoryVariables\n const storyVars = this.passages.getStoryVariables();\n if (storyVars) {\n const text = this.documents.getText(storyVars.uri);\n if (text) {\n const lines = text.split('\\n');\n const contentStart = storyVars.headerEnd.end.line + 1;\n // Find end of this passage\n let contentEnd = lines.length;\n for (let i = contentStart; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEnd = i;\n break;\n }\n }\n const content = lines.slice(contentStart, contentEnd).join('\\n');\n this.variables.parseStoryVariables(content);\n }\n }\n\n // Rescan variable usages across all documents\n for (const uri of this.documents.getUris()) {\n const text = this.documents.getText(uri);\n if (text) {\n const macros = parseMacros(text);\n this.variables.scanDocument(uri, text, macros);\n }\n }\n\n // Rescan widgets\n const allPassages = this.passages.getAllPassages();\n this.widgets.scan(allPassages, (uri) => this.documents.getText(uri));\n }\n\n /** Debounce modelReady emission. */\n private scheduleModelReady(): void {\n if (this.debounceTimer) {\n clearTimeout(this.debounceTimer);\n }\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null;\n this.emit('modelReady');\n }, this.DEBOUNCE_MS);\n }\n}\n", "export const DiagnosticCode = {\n UndefinedMacro: 'SP100',\n MalformedContainer: 'SP101',\n IllegalClosingTag: 'SP104',\n InvalidChildren: 'SP107',\n ExpectedNoArguments: 'SP108',\n ParameterTypeError: 'SP109',\n ParameterWarning: 'SP110',\n TooManyArguments: 'SP111',\n ArgumentParsingWarning: 'SP112',\n ChildMaxExceeded: 'SP114',\n ChildMinNotMet: 'SP115',\n UndeclaredVariable: 'SP200',\n UndeclaredField: 'SP201',\n NoStoryVariables: 'SP202',\n BrokenPassageLink: 'SP300',\n WidgetArgCountMismatch: 'SP301',\n DeadEndPassage: 'SP400',\n UnreachablePassage: 'SP401',\n} as const;\n\nexport type DiagnosticCodeValue = (typeof DiagnosticCode)[keyof typeof DiagnosticCode];\n\ntype Severity = 'error' | 'warning' | 'info' | 'hint';\n\nconst severityMap: Record<DiagnosticCodeValue, Severity> = {\n SP100: 'warning',\n SP101: 'error',\n SP104: 'error',\n SP107: 'error',\n SP108: 'error',\n SP109: 'error',\n SP110: 'warning',\n SP111: 'error',\n SP112: 'warning',\n SP114: 'error',\n SP115: 'error',\n SP200: 'warning',\n SP201: 'warning',\n SP202: 'info',\n SP300: 'warning',\n SP301: 'warning',\n SP400: 'hint',\n SP401: 'hint',\n};\n\nexport function getSeverity(code: DiagnosticCodeValue): Severity {\n return severityMap[code];\n}\n", "/**\n * Argument lexer for Spindle macro arguments.\n *\n * Tokenizes the raw argument string from a macro invocation into typed Arg tokens.\n * Ported from twee3-language-tools/src/spindle-0/arguments.ts with simplifications:\n * - No dependency on vscode.Range (uses plain start/end offsets)\n * - Unified Boolean type (instead of separate True/False)\n * - Dot-path extraction for variables ($player.health -> path=[\"player\",\"health\"])\n */\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport enum ArgType {\n String,\n Number,\n Boolean,\n Null,\n Variable,\n Link,\n Image,\n Expression,\n Bareword,\n NaN,\n Undefined,\n}\n\nexport interface Arg {\n type: ArgType;\n text: string;\n start: number;\n end: number;\n /** Variable sigil: $, _, or @ */\n sigil?: '$' | '_' | '@';\n /** Dot-access path segments, e.g. $player.health -> [\"player\", \"health\"] */\n path?: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Lex a raw argument string into an array of typed Arg tokens.\n */\nexport function lexArguments(source: string): Arg[] {\n const lexer = new Lexer(source, lexSpace);\n const rawItems = lexer.run();\n\n const args: Arg[] = [];\n for (const item of rawItems) {\n if (item.type === RawItem.Error) {\n // Stop on first error \u2014 mirrors the reference implementation\n break;\n }\n args.push(classifyToken(item));\n }\n return args;\n}\n\n/**\n * Count the number of arguments in a raw argument string.\n */\nexport function countArguments(source: string): number {\n return lexArguments(source).length;\n}\n\n// ---------------------------------------------------------------------------\n// Token classification\n// ---------------------------------------------------------------------------\n\nconst varTestRegexp = /^[$_@][$A-Z_a-z][$0-9A-Z_.a-z]*/;\n\nfunction classifyToken(item: LexerItem<RawItem>): Arg {\n const text = item.text;\n const base = { text, start: item.start, end: item.position };\n\n switch (item.type) {\n case RawItem.String:\n return { ...base, type: ArgType.String };\n\n case RawItem.Expression:\n return { ...base, type: ArgType.Expression };\n\n case RawItem.SquareBracket: {\n // Determine if it's a link or image based on the opening characters.\n // Images start with [img[, [<img[, [>img[ (case-insensitive)\n // Links start with [[\n const inner = text.slice(1); // skip first [\n if (/^[<>]?[Ii][Mm][Gg]\\[/.test(inner)) {\n return { ...base, type: ArgType.Image };\n }\n return { ...base, type: ArgType.Link };\n }\n\n case RawItem.Bareword: {\n // Variable?\n if (varTestRegexp.test(text)) {\n const sigil = text[0] as '$' | '_' | '@';\n const pathParts = text.slice(1).split('.');\n return {\n ...base,\n type: ArgType.Variable,\n sigil,\n path: pathParts,\n };\n }\n\n // Keywords\n if (text === 'null') return { ...base, type: ArgType.Null };\n if (text === 'undefined') return { ...base, type: ArgType.Undefined };\n if (text === 'true') return { ...base, type: ArgType.Boolean };\n if (text === 'false') return { ...base, type: ArgType.Boolean };\n if (text === 'NaN') return { ...base, type: ArgType.NaN };\n\n // Number? (including negative numbers like -5, floats like 3.14)\n const asNum = Number(text);\n if (!Number.isNaN(asNum)) {\n return { ...base, type: ArgType.Number };\n }\n\n // Fallback: bareword\n return { ...base, type: ArgType.Bareword };\n }\n\n default:\n return { ...base, type: ArgType.Bareword };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generic lexer engine (ported from reference)\n// ---------------------------------------------------------------------------\n\ntype LexerState<T> = (lexer: Lexer<T>) => LexerState<T> | null;\n\ninterface LexerItem<T> {\n type: T;\n text: string;\n start: number;\n position: number;\n message?: string;\n}\n\nconst EOF = -1 as const;\ntype EOFT = -1;\n\nclass Lexer<T> {\n readonly source: string;\n state: LexerState<T> | null;\n start = 0;\n pos = 0;\n depth = 0;\n items: LexerItem<T>[] = [];\n\n constructor(source: string, initial: LexerState<T>) {\n this.source = source;\n this.state = initial;\n }\n\n run(): LexerItem<T>[] {\n while (this.state !== null) {\n this.state = this.state(this);\n }\n return this.items;\n }\n\n next(): EOFT | string {\n const ch = this.peek();\n this.pos++;\n return ch;\n }\n\n peek(): EOFT | string {\n if (this.pos >= this.source.length) return EOF;\n return this.source[this.pos];\n }\n\n backup(num = 1) {\n this.pos -= num;\n }\n\n forward(num = 1) {\n this.pos += num;\n }\n\n ignore() {\n this.start = this.pos;\n }\n\n accept(valid: string): boolean {\n const ch = this.next();\n if (ch === EOF) return false;\n if (valid.includes(ch as string)) return true;\n this.backup();\n return false;\n }\n\n acceptRun(valid: string) {\n for (;;) {\n const ch = this.next();\n if (ch === EOF) return;\n if (!valid.includes(ch as string)) {\n break;\n }\n }\n this.backup();\n }\n\n emit(type: T) {\n this.items.push({\n type,\n text: this.source.slice(this.start, this.pos),\n start: this.start,\n position: this.pos,\n });\n this.start = this.pos;\n }\n\n error(type: T, message: string): null {\n this.items.push({\n type,\n message,\n text: this.source.slice(this.start, this.pos),\n start: this.start,\n position: this.pos,\n });\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Macro-argument lexer states\n// ---------------------------------------------------------------------------\n\nenum RawItem {\n Error,\n Bareword,\n Expression,\n String,\n SquareBracket,\n}\n\nconst notSpaceRegex = /\\S/;\nconst spaceRegex = /\\s/;\n\nfunction slurpQuote(lexer: Lexer<RawItem>, endQuote: string): EOFT | number {\n for (;;) {\n const next = lexer.next();\n if (next === '\\\\') {\n const ch = lexer.next();\n if (ch !== EOF && ch !== '\\n') continue;\n } else if (next === EOF) {\n return EOF;\n } else if (next === '\\n' && endQuote !== '`') {\n return EOF;\n } else if (next === endQuote) {\n break;\n }\n }\n return lexer.pos;\n}\n\nfunction lexSpace(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const offset = lexer.source.slice(lexer.pos).search(notSpaceRegex);\n\n if (offset === -1) return null;\n if (offset !== 0) {\n lexer.pos += offset;\n lexer.ignore();\n }\n\n // Skip commas as argument separators\n if (lexer.peek() === ',') {\n lexer.next();\n lexer.ignore();\n return lexSpace;\n }\n\n switch (lexer.next()) {\n case '`':\n return lexExpression;\n case '\"':\n return lexDoubleQuote;\n case \"'\":\n return lexSingleQuote;\n case '[':\n return lexSquareBracket;\n default:\n return lexBareword;\n }\n}\n\nfunction lexExpression(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, '`') === EOF) {\n return lexer.error(RawItem.Error, 'unterminated backquote expression');\n }\n lexer.emit(RawItem.Expression);\n return lexSpace;\n}\n\nfunction lexDoubleQuote(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, '\"') === EOF) {\n return lexer.error(RawItem.Error, 'unterminated double quoted string');\n }\n lexer.emit(RawItem.String);\n return lexSpace;\n}\n\nfunction lexSingleQuote(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n if (slurpQuote(lexer, \"'\") === EOF) {\n return lexer.error(RawItem.Error, 'unterminated single quoted string');\n }\n lexer.emit(RawItem.String);\n return lexSpace;\n}\n\nfunction lexSquareBracket(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const imgMeta = '<>IiMmGg';\n let what: string;\n\n if (lexer.accept(imgMeta)) {\n what = 'image';\n lexer.acceptRun(imgMeta);\n } else {\n what = 'link';\n }\n\n if (!lexer.accept('[')) {\n return lexer.error(RawItem.Error, `malformed ${what} markup`);\n }\n\n lexer.depth = 2;\n\n for (;;) {\n switch (lexer.next()) {\n case '\\\\': {\n const ch = lexer.next();\n if (ch !== EOF && ch !== '\\n') break;\n }\n /* falls through */\n case EOF:\n case '\\n':\n return lexer.error(RawItem.Error, `unterminated ${what} markup`);\n case '[':\n ++lexer.depth;\n break;\n case ']':\n --lexer.depth;\n if (lexer.depth < 0) {\n return lexer.error(RawItem.Error, \"unexpected right square bracket ']'\");\n }\n if (lexer.depth === 1) {\n if (lexer.next() === ']') {\n --lexer.depth;\n // break out of the for loop\n lexer.emit(RawItem.SquareBracket);\n return lexSpace;\n }\n lexer.backup();\n }\n break;\n }\n }\n}\n\nfunction lexBareword(lexer: Lexer<RawItem>): LexerState<RawItem> | null {\n const offset = lexer.source.slice(lexer.pos).search(spaceRegex);\n if (offset === -1) {\n // Rest of string is bareword; check for comma at end\n let end = lexer.source.length;\n // Trim trailing commas from bareword\n while (end > lexer.pos && lexer.source[end - 1] === ',') {\n end--;\n }\n lexer.pos = end;\n lexer.emit(RawItem.Bareword);\n // If there was a comma, continue lexing\n if (end < lexer.source.length) {\n lexer.pos = end + 1; // skip the comma\n lexer.ignore();\n return lexSpace;\n }\n return null;\n }\n\n // Check if comma comes before space\n const commaOffset = lexer.source.slice(lexer.pos).indexOf(',');\n if (commaOffset !== -1 && commaOffset < offset) {\n lexer.pos += commaOffset;\n lexer.emit(RawItem.Bareword);\n lexer.pos++; // skip comma\n lexer.ignore();\n return lexSpace;\n }\n\n lexer.pos += offset;\n lexer.emit(RawItem.Bareword);\n return lexSpace;\n}\n", "/**\n * Variant-based parameter validation for Spindle macros.\n *\n * Ported from twee3-language-tools/src/spindle-0/parameters.ts with simplifications:\n * - No dependency on vscode types\n * - Uses the simplified ArgType enum from argument-lexer.ts\n * - Pratt-parser format string parser preserved for correct operator precedence\n *\n * Format syntax:\n * type \u2014 single required parameter (e.g. \"text\", \"number\", \"var\")\n * ...type \u2014 variadic (zero or more)\n * type |+ type \u2014 optional next (left required, right optional)\n * type &+ type \u2014 required chain (both required)\n * type | type \u2014 or (either left or right)\n * 'literal' \u2014 literal value match\n * (group) \u2014 grouping\n */\n\nimport { ArgType, type Arg } from './argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\nexport interface ValidationResult {\n variantIndex: number | null;\n errors: ArgumentError[];\n warnings: ArgumentWarning[];\n}\n\nexport interface ArgumentError {\n message: string;\n argIndex: number;\n}\n\nexport interface ArgumentWarning {\n message: string;\n argIndex: number;\n}\n\nexport interface StateInfo {\n passages: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Parameter type system\n// ---------------------------------------------------------------------------\n\ninterface ParameterType {\n name: string[];\n validate(arg: Arg, args: Arg[], index: number, state?: StateInfo): TypeError | TypeWarning | null;\n}\n\nclass TypeError {\n constructor(public message: string) {}\n}\n\nclass TypeWarning {\n constructor(public message: string) {}\n}\n\n/**\n * \"Always\" arguments \u2014 variables and expressions pass any type check because\n * we cannot determine their runtime value statically.\n */\nfunction isAlwaysArg(arg: Arg): boolean {\n return arg.type === ArgType.Variable || arg.type === ArgType.Expression;\n}\n\n// Type definitions\nconst parameterTypes: ParameterType[] = [\n {\n name: ['bool', 'boolean'],\n validate(arg) {\n return arg.type === ArgType.Boolean ? null : new TypeError('Argument is not a boolean');\n },\n },\n {\n name: ['null'],\n validate(arg) {\n return arg.type === ArgType.Null ? null : new TypeError(\"Argument is not 'null'\");\n },\n },\n {\n name: ['undefined'],\n validate(arg) {\n return arg.type === ArgType.Undefined ? null : new TypeError(\"Argument is not 'undefined'\");\n },\n },\n {\n name: ['number'],\n validate(arg) {\n return arg.type === ArgType.Number ? null : new TypeError('Argument is not a number');\n },\n },\n {\n name: ['NaN'],\n validate(arg) {\n return arg.type === ArgType.NaN ? null : new TypeError(\"Argument is not 'NaN'\");\n },\n },\n {\n name: ['link'],\n validate(arg) {\n return arg.type === ArgType.Link ? null : new TypeError('Argument is not a link');\n },\n },\n {\n name: ['image'],\n validate(arg) {\n return arg.type === ArgType.Image ? null : new TypeError('Argument is not an image');\n },\n },\n {\n name: ['bareword'],\n validate(arg) {\n return arg.type === ArgType.Bareword ? null : new TypeError('Argument is not a bareword');\n },\n },\n {\n name: ['string'],\n validate(arg) {\n return arg.type === ArgType.String ? null : new TypeError('Argument is not a quoted string');\n },\n },\n {\n name: ['text'],\n validate(arg) {\n const t = arg.type;\n if (\n t === ArgType.Bareword ||\n t === ArgType.String ||\n t === ArgType.Boolean ||\n t === ArgType.Null ||\n t === ArgType.NaN ||\n t === ArgType.Number\n ) {\n return null;\n }\n return new TypeError('Argument is not text');\n },\n },\n {\n name: ['var'],\n validate(arg) {\n return arg.type === ArgType.Variable ? null : new TypeError('Argument is not a variable');\n },\n },\n {\n name: ['passage'],\n validate(arg, _args, _index, state) {\n // Extract passage name from the argument\n let passageName: string | undefined;\n if (arg.type === ArgType.String) {\n // Strip quotes\n passageName = arg.text.slice(1, -1);\n } else if (arg.type === ArgType.Bareword) {\n passageName = arg.text;\n } else if (arg.type === ArgType.Number) {\n passageName = arg.text;\n } else if (arg.type === ArgType.NaN) {\n passageName = 'NaN';\n }\n\n if (passageName !== undefined) {\n passageName = passageName.replace(/\\\\/g, '');\n if (state && state.passages.length > 0) {\n if (!state.passages.includes(passageName)) {\n return new TypeWarning(`Nonexistent passage: \"${passageName}\"`);\n }\n }\n return null;\n }\n\n return new TypeError('Argument is not an acceptable passage');\n },\n },\n];\n\nfunction findParameterType(name: string): ParameterType | null {\n for (const pt of parameterTypes) {\n if (pt.name.includes(name)) return pt;\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Format tree types\n// ---------------------------------------------------------------------------\n\nenum FormatKind {\n Type,\n Literal,\n Group,\n AndNext,\n MaybeNext,\n Or,\n Repeat,\n}\n\ntype Format =\n | FormatType\n | FormatLiteral\n | FormatAndNext\n | FormatMaybeNext\n | FormatOr\n | FormatRepeat;\n\ninterface FormatType {\n kind: FormatKind.Type;\n type: ParameterType;\n}\ninterface FormatLiteral {\n kind: FormatKind.Literal;\n value: string;\n}\ninterface FormatAndNext {\n kind: FormatKind.AndNext;\n left: Format;\n right: Format;\n}\ninterface FormatMaybeNext {\n kind: FormatKind.MaybeNext;\n left?: Format;\n right: Format;\n}\ninterface FormatOr {\n kind: FormatKind.Or;\n left: Format;\n right: Format;\n}\ninterface FormatRepeat {\n kind: FormatKind.Repeat;\n right: Format;\n}\n\n// Lex tokens (superset of Format for groups)\ntype FormatLex =\n | FormatType\n | FormatLiteral\n | { kind: FormatKind.Group; open: boolean }\n | { kind: FormatKind.AndNext }\n | { kind: FormatKind.MaybeNext }\n | { kind: FormatKind.Or }\n | { kind: FormatKind.Repeat };\n\n// ---------------------------------------------------------------------------\n// Format string lexer\n// ---------------------------------------------------------------------------\n\nconst LEX_LIMIT = 1000;\nconst wsRe = /\\s/;\nconst identStartRe = /[a-zA-Z]/;\nconst identStopRe = /[|&+\\-\\s)(]/;\nconst quoteRe = /['\"]/;\nconst digitRe = /[0-9]/;\n\nfunction lexFormat(formatString: string): FormatLex[] {\n let pos = 0;\n const lexed: FormatLex[] = [];\n let iter = 0;\n\n for (;;) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex iteration limit exceeded');\n if (pos >= formatString.length) break;\n\n const ch = formatString[pos];\n\n if (wsRe.test(ch)) {\n pos++;\n } else if (ch === '&') {\n pos++;\n const next = formatString[pos];\n if (next === '+') {\n pos++;\n lexed.push({ kind: FormatKind.AndNext });\n } else {\n throw new Error(`Lex: Expected '+' after '&', found '${next ?? 'EOF'}'`);\n }\n } else if (ch === '|') {\n pos++;\n const next = formatString[pos];\n if (next === '+') {\n pos++;\n lexed.push({ kind: FormatKind.MaybeNext });\n } else if (next === undefined) {\n throw new Error(\"Lex: Expected content after '|'\");\n } else if (wsRe.test(next)) {\n pos++;\n lexed.push({ kind: FormatKind.Or });\n } else if (identStartRe.test(next) || quoteRe.test(next)) {\n lexed.push({ kind: FormatKind.Or });\n } else {\n throw new Error(`Lex: Invalid character after '|': '${next}'`);\n }\n } else if (quoteRe.test(ch)) {\n const openQuote = ch;\n const start = pos;\n pos++;\n while (pos < formatString.length && formatString[pos] !== openQuote) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex string iteration limit exceeded');\n pos++;\n }\n if (pos >= formatString.length) throw new Error('Lex: Unterminated string literal');\n const value = formatString.slice(start + 1, pos);\n pos++; // skip closing quote\n lexed.push({ kind: FormatKind.Literal, value });\n } else if (ch === '(' || ch === ')') {\n pos++;\n lexed.push({ kind: FormatKind.Group, open: ch === '(' });\n } else if (identStartRe.test(ch)) {\n const start = pos;\n pos++;\n while (pos < formatString.length) {\n if (++iter > LEX_LIMIT) throw new Error('Format lex identifier iteration limit exceeded');\n const c = formatString[pos];\n if (identStopRe.test(c) || c === undefined) break;\n if (identStartRe.test(c)) {\n pos++;\n } else if (digitRe.test(c)) {\n throw new Error(`Lex: Digit '${c}' not allowed in parameter type name`);\n } else {\n throw new Error(`Lex: Invalid character '${c}' in parameter type name`);\n }\n }\n const ident = formatString.slice(start, pos);\n const pt = findParameterType(ident);\n if (pt === null) throw new Error(`Lex: Unknown parameter type '${ident}'`);\n lexed.push({ kind: FormatKind.Type, type: pt });\n } else if (ch === '.' && formatString[pos + 1] === '.' && formatString[pos + 2] === '.') {\n pos += 3;\n lexed.push({ kind: FormatKind.Repeat });\n } else {\n throw new Error(`Lex: Unexpected character '${ch}'`);\n }\n }\n\n return lexed;\n}\n\n// ---------------------------------------------------------------------------\n// Format string parser (Pratt parser)\n// ---------------------------------------------------------------------------\n\nconst PARSE_LIMIT = 2000;\n\nfunction parseFormat(formatString: string): Format | null {\n const tokens = lexFormat(formatString);\n if (tokens.length === 0) return null;\n\n let index = 0;\n let iter = 0;\n\n function infixBp(kind: FormatKind): [number, number] | null {\n switch (kind) {\n case FormatKind.Or: return [9, 10];\n case FormatKind.AndNext: return [4, 5];\n case FormatKind.MaybeNext: return [2, 3];\n default: return null;\n }\n }\n\n function prefixBp(kind: FormatKind): number {\n switch (kind) {\n case FormatKind.MaybeNext: return 3;\n case FormatKind.Repeat: return 8;\n default: throw new Error(`Parse: Unexpected prefix operator kind ${kind}`);\n }\n }\n\n function isPrefixOp(t: FormatLex): boolean {\n return t.kind === FormatKind.MaybeNext || t.kind === FormatKind.Repeat;\n }\n\n function isValue(t: FormatLex): t is FormatType | FormatLiteral {\n return t.kind === FormatKind.Type || t.kind === FormatKind.Literal;\n }\n\n function exprBp(minBp: number): Format {\n if (++iter > PARSE_LIMIT) throw new Error('Format parse iteration limit exceeded');\n const cur = tokens[index];\n if (!cur) throw new Error('Parse: Unexpected end of format string');\n index++;\n\n let lhs: Format;\n\n if (isPrefixOp(cur)) {\n const rBp = prefixBp(cur.kind);\n const rhs = exprBp(rBp);\n lhs = { kind: cur.kind, right: rhs } as Format;\n } else if (cur.kind === FormatKind.Group) {\n const g = cur as { kind: FormatKind.Group; open: boolean };\n if (!g.open) throw new Error('Parse: Unexpected closing parenthesis');\n lhs = exprBp(0);\n const closing = tokens[index];\n if (!closing || closing.kind !== FormatKind.Group || (closing as { open: boolean }).open) {\n throw new Error('Parse: Expected closing parenthesis');\n }\n index++;\n } else if (isValue(cur)) {\n lhs = cur;\n } else {\n throw new Error('Parse: Expected value or prefix operator');\n }\n\n for (;;) {\n if (++iter > PARSE_LIMIT) throw new Error('Format parse operator iteration limit exceeded');\n const op = tokens[index];\n if (!op) break;\n const bp = infixBp(op.kind);\n if (bp === null) break;\n const [lBp, rBp] = bp;\n if (lBp < minBp) break;\n index++;\n const rhs = exprBp(rBp);\n lhs = { kind: op.kind, left: lhs, right: rhs } as Format;\n }\n\n return lhs;\n }\n\n return exprBp(0);\n}\n\n// ---------------------------------------------------------------------------\n// Format tree utilities\n// ---------------------------------------------------------------------------\n\nfunction formatArgCountRange(format: Format): { min: number; max: number } {\n switch (format.kind) {\n case FormatKind.Type:\n case FormatKind.Literal:\n return { min: 1, max: 1 };\n case FormatKind.AndNext: {\n const l = formatArgCountRange(format.left);\n const r = formatArgCountRange(format.right);\n return { min: l.min + r.min, max: l.max + r.max };\n }\n case FormatKind.MaybeNext: {\n const l = format.left ? formatArgCountRange(format.left) : { min: 0, max: 0 };\n const r = formatArgCountRange(format.right);\n return { min: l.min, max: l.max + r.max };\n }\n case FormatKind.Or: {\n const l = formatArgCountRange(format.left);\n const r = formatArgCountRange(format.right);\n return { min: Math.min(l.min, r.min), max: Math.max(l.max, r.max) };\n }\n case FormatKind.Repeat:\n return { min: 0, max: Infinity };\n }\n}\n\n// ---------------------------------------------------------------------------\n// Validator (tree-crawl)\n// ---------------------------------------------------------------------------\n\nenum CrawlStatus {\n NotFound,\n Failure,\n Success,\n}\n\ninterface CrawlResult {\n status: CrawlStatus;\n rank: number;\n argIndex: number;\n errors: ArgumentError[];\n warnings: ArgumentWarning[];\n}\n\nfunction makeError(status: CrawlStatus, message: string, argIndex: number, rank = 0): CrawlResult {\n return {\n status,\n rank,\n argIndex,\n errors: [{ message, argIndex }],\n warnings: [],\n };\n}\n\nfunction makeSuccess(argIndex: number, rank: number, warnings: ArgumentWarning[] = []): CrawlResult {\n return { status: CrawlStatus.Success, rank, argIndex, errors: [], warnings };\n}\n\nfunction isFail(s: CrawlStatus): boolean {\n return s === CrawlStatus.Failure || s === CrawlStatus.NotFound;\n}\n\nconst VALIDATE_LIMIT = 2000;\nconst CORRECT_TYPE_RANK = 1;\nconst CORRECT_RANK = 2;\n\nfunction crawlValidate(\n format: Format,\n args: Arg[],\n startIndex: number,\n state?: StateInfo,\n): CrawlResult {\n let iter = 0;\n\n function crawl(fmt: Format, argIdx: number): CrawlResult {\n if (++iter > VALIDATE_LIMIT) {\n throw new Error(`Validation iteration limit exceeded at argument ${argIdx}`);\n }\n\n switch (fmt.kind) {\n case FormatKind.MaybeNext: {\n let rank = 0;\n let warnings: ArgumentWarning[] = [];\n let idx = argIdx;\n\n if (fmt.left) {\n const left = crawl(fmt.left, idx);\n if (isFail(left.status)) return left;\n rank += left.rank;\n idx = left.argIndex;\n warnings = left.warnings;\n }\n\n const right = crawl(fmt.right, idx);\n if (right.status === CrawlStatus.NotFound) {\n return makeSuccess(idx, rank, warnings);\n }\n if (isFail(right.status)) {\n right.status = CrawlStatus.Failure;\n return right;\n }\n\n return makeSuccess(right.argIndex, rank + right.rank, warnings.concat(right.warnings));\n }\n\n case FormatKind.AndNext: {\n const left = crawl(fmt.left, argIdx);\n if (isFail(left.status)) return left;\n\n const right = crawl(fmt.right, left.argIndex);\n if (isFail(right.status)) return right;\n\n return makeSuccess(\n right.argIndex,\n left.rank + right.rank,\n left.warnings.concat(right.warnings),\n );\n }\n\n case FormatKind.Or: {\n const left = crawl(fmt.left, argIdx);\n if (!isFail(left.status)) return left;\n\n const right = crawl(fmt.right, argIdx);\n if (!isFail(right.status)) return right;\n\n // Both failed \u2014 return left's error\n return left;\n }\n\n case FormatKind.Repeat: {\n let rank = 0;\n let warnings: ArgumentWarning[] = [];\n let idx = argIdx;\n\n for (;;) {\n const r = crawl(fmt.right, idx);\n if (isFail(r.status)) break;\n idx = r.argIndex;\n rank += r.rank;\n warnings = warnings.concat(r.warnings);\n }\n\n return makeSuccess(idx, rank, warnings);\n }\n\n case FormatKind.Literal: {\n const arg = args[argIdx];\n if (arg === undefined) {\n return makeError(CrawlStatus.NotFound, `Expected literal '${fmt.value}' but no argument found`, argIdx);\n }\n if (isAlwaysArg(arg)) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n // Check literal match\n const argText = arg.type === ArgType.String ? arg.text.slice(1, -1) : arg.text;\n if (argText === fmt.value) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n // Special keyword matches\n if (\n (fmt.value === 'null' && arg.type === ArgType.Null) ||\n (fmt.value === 'undefined' && arg.type === ArgType.Undefined) ||\n (fmt.value === 'true' && arg.type === ArgType.Boolean && arg.text === 'true') ||\n (fmt.value === 'false' && arg.type === ArgType.Boolean && arg.text === 'false') ||\n (fmt.value === 'NaN' && arg.type === ArgType.NaN)\n ) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n return makeError(CrawlStatus.Failure, `Expected literal '${fmt.value}'`, argIdx, CORRECT_TYPE_RANK);\n }\n\n case FormatKind.Type: {\n const arg = args[argIdx];\n const typeDef = fmt.type;\n\n if (arg === undefined) {\n return makeError(\n CrawlStatus.NotFound,\n `Expected type '${typeDef.name[0]}' but no argument found`,\n argIdx,\n );\n }\n\n if (isAlwaysArg(arg)) {\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n\n const result = typeDef.validate(arg, args, argIdx, state);\n if (result instanceof TypeError) {\n return {\n status: CrawlStatus.Failure,\n rank: 0,\n argIndex: argIdx,\n errors: [{ message: result.message, argIndex: argIdx }],\n warnings: [],\n };\n }\n if (result instanceof TypeWarning) {\n return makeSuccess(argIdx + 1, CORRECT_RANK, [\n { message: result.message, argIndex: argIdx },\n ]);\n }\n\n return makeSuccess(argIdx + 1, CORRECT_RANK);\n }\n }\n }\n\n return crawl(format, startIndex);\n}\n\n// ---------------------------------------------------------------------------\n// Parameters class (public API)\n// ---------------------------------------------------------------------------\n\ninterface ParsedVariant {\n formatString: string;\n format: Format | null;\n}\n\nexport class Parameters {\n private variants: ParsedVariant[];\n\n constructor(variants: string[]) {\n this.variants = variants.map((s) => ({\n formatString: s,\n format: parseFormat(s),\n }));\n }\n\n /**\n * Validate an array of Arg tokens against these parameter variants.\n * Selects the best-matching variant by rank.\n */\n validate(args: Arg[], stateInfo?: StateInfo): ValidationResult {\n // Handle case where no variants exist\n if (this.variants.length === 0) {\n if (args.length === 0) {\n return { variantIndex: null, errors: [], warnings: [] };\n }\n return {\n variantIndex: null,\n errors: [{ message: 'Expected no arguments', argIndex: 0 }],\n warnings: [],\n };\n }\n\n let bestIndex: number | null = null;\n let bestRank = -Infinity;\n let bestErrors: ArgumentError[] = [];\n let bestWarnings: ArgumentWarning[] = [];\n let bestIsClean = false; // tracks whether the best has zero errors\n\n for (let i = 0; i < this.variants.length; i++) {\n const variant = this.variants[i];\n\n if (variant.format === null) {\n // Empty variant: accepts zero arguments\n if (args.length === 0) {\n // Perfect match \u2014 no errors\n if (!bestIsClean || 0 > bestRank) {\n bestIndex = i;\n bestRank = 0;\n bestErrors = [];\n bestWarnings = [];\n bestIsClean = true;\n }\n } else {\n // Args provided but variant expects none\n if (!bestIsClean && bestIndex === null) {\n bestIndex = i;\n bestRank = -1;\n bestErrors = [{ message: 'Expected no arguments', argIndex: 0 }];\n bestWarnings = [];\n }\n }\n continue;\n }\n\n const result = crawlValidate(variant.format, args, 0, stateInfo);\n\n // Check for unconsumed arguments\n let errors = result.errors;\n if (result.errors.length === 0 && result.argIndex < args.length) {\n errors = [\n {\n message: `Too many arguments: expected ${result.argIndex}, got ${args.length}`,\n argIndex: result.argIndex,\n },\n ];\n }\n\n const rank = result.rank;\n const isClean = errors.length === 0;\n\n if (isClean && (!bestIsClean || rank > bestRank)) {\n // Clean result beats any errored result, or a better clean result\n bestIndex = i;\n bestRank = rank;\n bestErrors = [];\n bestWarnings = result.warnings;\n bestIsClean = true;\n } else if (!isClean && !bestIsClean && rank > bestRank) {\n // Both errored \u2014 pick the higher-ranked error\n bestIndex = i;\n bestRank = rank;\n bestErrors = errors;\n bestWarnings = result.warnings;\n } else if (bestIndex === null) {\n // First variant tried \u2014 store as default\n bestIndex = i;\n bestRank = rank;\n bestErrors = errors;\n bestWarnings = result.warnings;\n bestIsClean = isClean;\n }\n }\n\n return {\n variantIndex: bestIndex,\n errors: bestErrors,\n warnings: bestWarnings,\n };\n }\n\n /**\n * Compute the min/max argument count across all variants.\n */\n argCountRange(): { min: number; max: number } {\n let min = Infinity;\n let max = 0;\n\n for (const variant of this.variants) {\n if (variant.format === null) {\n min = 0;\n } else {\n const range = formatArgCountRange(variant.format);\n min = Math.min(min, range.min);\n max = Math.max(max, range.max);\n }\n }\n\n if (min === Infinity) min = 0;\n return { min, max };\n }\n\n /**\n * Whether all variants are empty (accept no arguments).\n */\n isEmpty(): boolean {\n if (this.variants.length === 0) return true;\n return !this.variants.some((v) => v.format !== null);\n }\n}\n", "import type { Range } from '../types.js';\n\nexport interface PassageRef {\n name: string;\n range: Range;\n source: 'link' | 'macro';\n}\n\n/**\n * Regex for [[display|target]] and [[target]] link syntax.\n * Group 1: optional display text followed by pipe\n * Group 2: passage name (target)\n */\nconst linkRegex = /\\[\\[([^\\]]*?\\|)?([^\\]]+?)\\]\\]/g;\n\n/**\n * Build an array of line-start offsets from text.\n * lineStarts[i] is the character offset where line i begins.\n */\nfunction buildLineStarts(text: string): number[] {\n const starts = [0];\n for (let i = 0; i < text.length; i++) {\n if (text[i] === '\\n') {\n starts.push(i + 1);\n }\n }\n return starts;\n}\n\n/**\n * Convert a character offset to a line/character Position\n * using precomputed line-start offsets.\n */\nfunction offsetToPosition(offset: number, lineStarts: number[]): { line: number; character: number } {\n let low = 0;\n let high = lineStarts.length - 1;\n while (low < high) {\n const mid = (low + high + 1) >> 1;\n if (lineStarts[mid] <= offset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n return { line: low, character: offset - lineStarts[low] };\n}\n\n/**\n * Parse all passage references from bracket links in the given text.\n *\n * Supports:\n * [[PassageName]]\n * [[Display Text|Target]]\n *\n * @param text - the text to parse\n * @param lineOffset - optional line offset added to all line numbers (default 0)\n */\nexport function parseLinks(text: string, lineOffset: number = 0): PassageRef[] {\n const lineStarts = buildLineStarts(text);\n const refs: PassageRef[] = [];\n\n linkRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n\n while ((match = linkRegex.exec(text)) !== null) {\n const passageName = match[2].trim();\n if (!passageName) continue;\n\n // Calculate position of the passage name within the match\n const nameStartInMatch = match[0].indexOf(passageName);\n const nameStart = match.index + nameStartInMatch;\n const nameEnd = nameStart + passageName.length;\n\n const startPos = offsetToPosition(nameStart, lineStarts);\n const endPos = offsetToPosition(nameEnd, lineStarts);\n\n const range: Range = {\n start: { line: startPos.line + lineOffset, character: startPos.character },\n end: { line: endPos.line + lineOffset, character: endPos.character },\n };\n\n refs.push({\n name: passageName,\n range,\n source: 'link',\n });\n }\n\n return refs;\n}\n", "import type { Diagnostic, MacroNode } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { DiagnosticCode, getSeverity } from '../core/diagnostic-codes.js';\nimport type { DiagnosticCodeValue } from '../core/diagnostic-codes.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\nimport { Parameters } from '../core/parsing/parameter-validator.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core diagnostic function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute all diagnostics for a single document within the workspace context.\n *\n * Checks:\n * - Macro validation (SP100, SP101, SP104, SP107, SP114, SP115)\n * - Argument/parameter validation (SP108, SP109, SP110, SP111, SP112)\n * - Variable validation (SP200, SP202)\n * - Link/widget validation (SP300, SP301)\n */\nexport function computeDiagnostics(uri: string, workspace: WorkspaceModel): Diagnostic[] {\n try {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const diagnostics: Diagnostic[] = [];\n\n // Parse macros for the whole document\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n // Collect all passage names across workspace for link validation\n const allPassages = workspace.passages.getAllPassages();\n const passageNames = new Set(allPassages.map(p => p.name));\n\n // Each validation step is wrapped individually so that a failure\n // in one category still allows the others to produce diagnostics.\n\n try {\n validateMacros(macros, workspace, diagnostics);\n } catch {\n // Macro validation failed \u2014 continue with other checks\n }\n\n try {\n validateArguments(macros, workspace, passageNames, diagnostics);\n } catch {\n // Argument validation failed \u2014 continue\n }\n\n try {\n validateVariables(uri, workspace, diagnostics);\n } catch {\n // Variable validation failed \u2014 continue\n }\n\n try {\n validateLinks(text, passages, passageNames, diagnostics);\n } catch {\n // Link validation failed \u2014 continue\n }\n\n try {\n validateWidgetInvocations(macros, workspace, diagnostics);\n } catch {\n // Widget validation failed \u2014 continue\n }\n\n return diagnostics;\n } catch {\n // Catastrophic failure \u2014 return empty diagnostics rather than crashing\n return [];\n }\n}\n\n// ---------------------------------------------------------------------------\n// Macro validation (SP100, SP101, SP104, SP107, SP114, SP115)\n// ---------------------------------------------------------------------------\n\nfunction validateMacros(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n for (let curIndex = 0; curIndex < macros.length; curIndex++) {\n const macro = macros[curIndex];\n const info = workspace.macros.getMacro(macro.name);\n\n if (info) {\n // Known macro\n if (info.block) {\n // SP101: unmatched container\n if (macro.open && macro.pair === -1) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.MalformedContainer,\n `Malformed container: no matching {/${macro.name}}`,\n ));\n } else if (!macro.open && macro.pair === -1) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.MalformedContainer,\n `Malformed container: no matching {${macro.name}}`,\n ));\n }\n\n // SP114/SP115: children constraints\n if (info.children && info.children.length > 0 && macro.open && macro.pair !== -1) {\n validateChildren(macros, curIndex, macro, info.children, workspace, diagnostics);\n }\n } else {\n // SP104: closing tag on non-container\n if (!macro.open) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.IllegalClosingTag,\n `Illegal closing tag: {${macro.name}} is not a container`,\n ));\n }\n }\n\n // SP107: parents constraint\n if (info.parents && info.parents.length > 0 && macro.open) {\n if (!isInsideParent(macros, curIndex, info.parents, workspace)) {\n const parentList = info.parents.join(', ');\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.InvalidChildren,\n `Invalid: {${macro.name}} can only be inside {${parentList}}`,\n ));\n }\n }\n } else {\n // Check if it's a user-defined widget before flagging SP100\n const widget = workspace.widgets.getWidget(macro.name);\n if (!widget && macro.open) {\n // SP100: unrecognized macro\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.UndefinedMacro,\n `Unrecognized macro: {${macro.name}}`,\n ));\n }\n }\n }\n}\n\n/**\n * Check whether the macro at `index` is inside one of the allowed parent containers.\n */\nfunction isInsideParent(\n macros: MacroNode[],\n index: number,\n parents: string[],\n workspace: WorkspaceModel,\n): boolean {\n const parentSet = new Set(parents.map(p => p.toLowerCase()));\n\n // Walk backwards to find an enclosing container\n for (let i = index - 1; i >= 0; i--) {\n const candidate = macros[i];\n if (!candidate.open) continue;\n\n const candidateInfo = workspace.macros.getMacro(candidate.name);\n if (!candidateInfo?.block) continue;\n\n // Check if the candidate's pair extends past our macro\n if (candidate.pair !== -1 && candidate.pair > index) {\n // We are inside this container\n if (parentSet.has(candidate.name.toLowerCase())) {\n return true;\n }\n // We're inside a different container \u2014 keep looking for allowed parents\n }\n }\n\n return false;\n}\n\n/**\n * Validate children constraints for a paired container macro.\n */\nfunction validateChildren(\n macros: MacroNode[],\n curIndex: number,\n parentMacro: MacroNode,\n childConstraints: Array<{ name: string; min?: number; max?: number }>,\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n const children: Record<string, number> = Object.create(null);\n const startIndex = curIndex + 1;\n const endIndex = parentMacro.pair;\n\n for (let i = startIndex; i < endIndex; i++) {\n const child = macros[i];\n const childInfo = workspace.macros.getMacro(child.name);\n\n if (!childInfo) continue;\n\n // Skip contents of nested containers\n if (childInfo.block && child.open && child.pair !== -1) {\n i = child.pair;\n continue;\n }\n\n // Count direct children that match constraints\n for (const constraint of childConstraints) {\n if (constraint.name === child.name) {\n children[child.name] = (children[child.name] ?? 0) + 1;\n }\n }\n }\n\n // Check constraints\n for (const constraint of childConstraints) {\n const count = children[constraint.name] ?? 0;\n\n if (constraint.max !== undefined && count > constraint.max) {\n diagnostics.push(makeDiag(\n parentMacro.range,\n DiagnosticCode.ChildMaxExceeded,\n `Too many {${constraint.name}} in {${parentMacro.name}} (max ${constraint.max}, found ${count})`,\n ));\n }\n\n if (constraint.min !== undefined && count < constraint.min) {\n diagnostics.push(makeDiag(\n parentMacro.range,\n DiagnosticCode.ChildMinNotMet,\n `Too few {${constraint.name}} in {${parentMacro.name}} (min ${constraint.min}, found ${count})`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Argument / parameter validation (SP108, SP109, SP110, SP111, SP112)\n// ---------------------------------------------------------------------------\n\nfunction validateArguments(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n passageNames: Set<string>,\n diagnostics: Diagnostic[],\n): void {\n for (const macro of macros) {\n if (!macro.open) continue;\n\n const info = workspace.macros.getMacro(macro.name);\n if (!info) continue;\n if (info.skipArgs) continue;\n if (!info.parameters) continue;\n\n const rawArgs = macro.rawArgs ?? '';\n const args = lexArguments(rawArgs);\n\n const params = new Parameters(info.parameters);\n\n // SP108: empty parameters but received args\n if (params.isEmpty()) {\n if (args.length > 0) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ExpectedNoArguments,\n `Expected no arguments for {${macro.name}}, got ${args.length}`,\n ));\n }\n continue;\n }\n\n const stateInfo = { passages: Array.from(passageNames) };\n const result = params.validate(args, stateInfo);\n\n if (result.variantIndex === null) {\n // No variant matched at all \u2014 covered by isEmpty check above\n continue;\n }\n\n // SP109: parameter type errors\n for (const error of result.errors) {\n // Determine if it's a \"too many\" error or a type error\n if (error.message.startsWith('Too many arguments')) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.TooManyArguments,\n `{${macro.name}}: ${error.message}`,\n ));\n } else {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ParameterTypeError,\n `{${macro.name}}: ${error.message}`,\n ));\n }\n }\n\n // SP110: parameter warnings\n for (const warning of result.warnings) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.ParameterWarning,\n `{${macro.name}}: ${warning.message}`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Variable validation (SP200, SP202)\n// ---------------------------------------------------------------------------\n\nfunction validateVariables(\n uri: string,\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n if (!workspace.variables.hasStoryVariables()) {\n // SP202: no StoryVariables passage\n // Only emit once per document, and only if there are variable usages\n const undeclared = workspace.variables.getUndeclared(uri);\n // Even with no StoryVariables, getUndeclared returns all usages since nothing is declared\n // Check if there are any variable usages at all\n const text = workspace.documents.getText(uri);\n if (text && /\\$[A-Za-z_$]/.test(text)) {\n // Check if there are non-special passages with variable usages\n const passages = workspace.passages.getPassagesInDocument(uri);\n const hasVarUsage = passages.some(p => {\n const excluded = new Set(['StoryVariables', 'StoryInit', 'StoryData', 'StoryScript', 'StoryInterface']);\n return !excluded.has(p.name) && !p.tags?.includes('script') && !p.tags?.includes('stylesheet');\n });\n if (hasVarUsage) {\n diagnostics.push(makeDiag(\n passages[0].range,\n DiagnosticCode.NoStoryVariables,\n 'No StoryVariables passage found. Declare all story variables with default values in a StoryVariables passage.',\n ));\n }\n }\n return;\n }\n\n // SP200: undeclared variable\n const undeclared = workspace.variables.getUndeclared(uri);\n for (const u of undeclared) {\n diagnostics.push(makeDiag(\n u.range,\n DiagnosticCode.UndeclaredVariable,\n `Variable '$${u.name}' is not declared in StoryVariables`,\n ));\n }\n}\n\n// ---------------------------------------------------------------------------\n// Link validation (SP300)\n// ---------------------------------------------------------------------------\n\nfunction validateLinks(\n text: string,\n passages: Array<{ name: string; range: import('../core/types.js').Range }>,\n passageNames: Set<string>,\n diagnostics: Diagnostic[],\n): void {\n const links = parseLinks(text);\n for (const link of links) {\n if (!passageNames.has(link.name)) {\n diagnostics.push(makeDiag(\n link.range,\n DiagnosticCode.BrokenPassageLink,\n `Passage \"${link.name}\" not found in workspace`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Widget invocation validation (SP301)\n// ---------------------------------------------------------------------------\n\nfunction validateWidgetInvocations(\n macros: MacroNode[],\n workspace: WorkspaceModel,\n diagnostics: Diagnostic[],\n): void {\n for (const macro of macros) {\n if (!macro.open) continue;\n\n // Skip if it's a known macro (not a widget)\n const info = workspace.macros.getMacro(macro.name);\n if (info) continue;\n\n const widget = workspace.widgets.getWidget(macro.name);\n if (!widget) continue;\n\n // Count arguments provided\n const rawArgs = macro.rawArgs ?? '';\n const argCount = rawArgs.trim() === '' ? 0 : lexArguments(rawArgs).length;\n const expectedCount = widget.params.length;\n\n if (argCount !== expectedCount) {\n diagnostics.push(makeDiag(\n macro.range,\n DiagnosticCode.WidgetArgCountMismatch,\n `Widget {${macro.name}} expects ${expectedCount} argument(s), got ${argCount}`,\n ));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction makeDiag(\n range: import('../core/types.js').Range,\n code: DiagnosticCodeValue,\n message: string,\n): Diagnostic {\n return {\n range,\n message,\n severity: getSeverity(code),\n code,\n source: 'spindle',\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspDiagnostic(d: Diagnostic): import('vscode-languageserver').Diagnostic {\n const severityMap = {\n error: 1,\n warning: 2,\n info: 3,\n hint: 4,\n } as const;\n\n return {\n range: {\n start: { line: d.range.start.line, character: d.range.start.character },\n end: { line: d.range.end.line, character: d.range.end.character },\n },\n severity: severityMap[d.severity],\n code: d.code,\n source: d.source,\n message: d.message,\n };\n}\n\nexport const diagnosticsPlugin: SpindlePlugin = {\n id: 'diagnostics',\n capabilities: {},\n initialize(ctx: PluginContext) {\n const publishDiagnostics = () => {\n for (const uri of ctx.workspace.documents.getUris()) {\n const diags = computeDiagnostics(uri, ctx.workspace);\n ctx.connection.sendDiagnostics({\n uri,\n diagnostics: diags.map(d => toLspDiagnostic(d)),\n });\n }\n };\n\n ctx.workspace.on('modelReady', publishDiagnostics);\n ctx.workspace.on('documentChanged', (uri: string) => {\n const diags = computeDiagnostics(uri, ctx.workspace);\n ctx.connection.sendDiagnostics({\n uri,\n diagnostics: diags.map(d => toLspDiagnostic(d)),\n });\n });\n },\n};\n", "import { readFileSync, existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { parse as parseYaml } from 'yaml';\n\n/**\n * Spindle project config as loaded from config files.\n */\nexport interface SpindleProjectConfig {\n macros: Record<string, any>;\n enums?: Record<string, string>;\n}\n\n/**\n * Config files searched in order of priority.\n * Supports both the new `spindle.config.*` format and the legacy\n * `t3lt.twee-config.*` format (used by twee3-language-tools).\n */\nconst CONFIG_FILENAMES = [\n 'spindle.config.yaml',\n 'spindle.config.yml',\n 'spindle.config.json',\n 't3lt.twee-config.yaml',\n 't3lt.twee-config.yml',\n 't3lt.twee-config.json',\n];\n\nconst EMPTY_CONFIG: SpindleProjectConfig = { macros: {} };\n\n/**\n * Parse a config file's content in the given format.\n * Returns a SpindleProjectConfig with at least an empty `macros` record.\n */\nexport function parseConfig(\n content: string,\n format: 'yaml' | 'json',\n): SpindleProjectConfig {\n if (!content.trim()) {\n return { macros: {} };\n }\n\n let raw: unknown;\n if (format === 'json') {\n raw = JSON.parse(content);\n } else {\n raw = parseYaml(content);\n }\n\n if (typeof raw !== 'object' || raw === null) {\n return { macros: {} };\n }\n\n const obj = raw as Record<string, unknown>;\n\n // Support legacy t3lt.twee-config format: { \"spindle-0\": { macros: {...}, enums: {...} } }\n const spindle0 = obj['spindle-0'] as Record<string, unknown> | undefined;\n const source = (spindle0 && typeof spindle0 === 'object') ? spindle0 : obj;\n\n return {\n macros: (typeof source.macros === 'object' && source.macros !== null)\n ? source.macros as Record<string, any>\n : {},\n enums: (typeof source.enums === 'object' && source.enums !== null)\n ? source.enums as Record<string, string>\n : undefined,\n };\n}\n\n/**\n * Search for a config file in the workspace root directory.\n * Checks for spindle.config.yaml, spindle.config.yml, and spindle.config.json\n * in that order. Returns the full path of the first match, or null.\n */\nexport function findConfigFile(workspaceRoot: string): string | null {\n for (const name of CONFIG_FILENAMES) {\n const fullPath = join(workspaceRoot, name);\n if (existsSync(fullPath)) {\n return fullPath;\n }\n }\n return null;\n}\n\n/**\n * Load and parse the project config from the workspace root.\n * Returns a default empty config if no config file is found.\n */\nexport function loadConfigFromDisk(workspaceRoot: string): SpindleProjectConfig {\n const configPath = findConfigFile(workspaceRoot);\n if (!configPath) {\n return { ...EMPTY_CONFIG };\n }\n\n const content = readFileSync(configPath, 'utf-8');\n const format = configPath.endsWith('.json') ? 'json' : 'yaml';\n return parseConfig(content, format);\n}\n", "import { fileURLToPath } from 'node:url';\nimport type { Diagnostic } from '../../core/types.js';\n\n/**\n * ANSI color codes for terminal output.\n */\nconst colors = {\n red: '\\x1b[31m',\n yellow: '\\x1b[33m',\n blue: '\\x1b[34m',\n cyan: '\\x1b[36m',\n gray: '\\x1b[90m',\n reset: '\\x1b[0m',\n bold: '\\x1b[1m',\n};\n\nconst severityColors: Record<string, string> = {\n error: colors.red,\n warning: colors.yellow,\n info: colors.blue,\n hint: colors.cyan,\n};\n\n/**\n * Format diagnostics in a human-readable, colored terminal format.\n *\n * Example:\n * src/story.tw:5:1 error SP101 Malformed container: no matching {/if}\n * src/story.tw:7:1 warning SP100 Unrecognized macro: unknownMacro\n *\n * Found 2 problems (1 error, 1 warning)\n */\nexport function formatPretty(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n if (results.length === 0) {\n return `${colors.bold}No problems found${colors.reset}`;\n }\n\n const lines: string[] = [];\n let errorCount = 0;\n let warningCount = 0;\n let infoCount = 0;\n let hintCount = 0;\n\n for (const { uri, diagnostics } of results) {\n let filePath: string;\n try {\n filePath = fileURLToPath(uri);\n } catch {\n filePath = uri;\n }\n\n for (const diag of diagnostics) {\n const line = diag.range.start.line + 1;\n const col = diag.range.start.character + 1;\n const color = severityColors[diag.severity] ?? colors.gray;\n\n lines.push(\n `${colors.bold}${filePath}:${line}:${col}${colors.reset} ` +\n `${color}${diag.severity}${colors.reset} ` +\n `${colors.gray}${diag.code}${colors.reset} ` +\n `${diag.message}`,\n );\n\n switch (diag.severity) {\n case 'error': errorCount++; break;\n case 'warning': warningCount++; break;\n case 'info': infoCount++; break;\n case 'hint': hintCount++; break;\n }\n }\n }\n\n const total = errorCount + warningCount + infoCount + hintCount;\n const parts: string[] = [];\n if (errorCount > 0) parts.push(`${errorCount} error${errorCount !== 1 ? 's' : ''}`);\n if (warningCount > 0) parts.push(`${warningCount} warning${warningCount !== 1 ? 's' : ''}`);\n if (infoCount > 0) parts.push(`${infoCount} info`);\n if (hintCount > 0) parts.push(`${hintCount} hint${hintCount !== 1 ? 's' : ''}`);\n\n lines.push('');\n lines.push(\n `${colors.bold}Found ${total} problem${total !== 1 ? 's' : ''} (${parts.join(', ')})${colors.reset}`,\n );\n\n return lines.join('\\n');\n}\n", "import type { Diagnostic } from '../../core/types.js';\n\n/**\n * Format diagnostics as a JSON structure.\n *\n * Output shape:\n * ```json\n * {\n * \"files\": [\n * {\n * \"uri\": \"file:///path/to/story.tw\",\n * \"diagnostics\": [\n * {\n * \"range\": { \"start\": { \"line\": 4, \"character\": 0 }, \"end\": { \"line\": 4, \"character\": 10 } },\n * \"message\": \"...\",\n * \"severity\": \"error\",\n * \"code\": \"SP101\",\n * \"source\": \"spindle\"\n * }\n * ]\n * }\n * ]\n * }\n * ```\n */\nexport function formatJson(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n const output = {\n files: results.map(({ uri, diagnostics }) => ({\n uri,\n diagnostics: diagnostics.map(d => ({\n range: d.range,\n message: d.message,\n severity: d.severity,\n code: d.code,\n source: d.source,\n })),\n })),\n };\n\n return JSON.stringify(output, null, 2);\n}\n", "import type { Diagnostic } from '../../core/types.js';\n\n/**\n * SARIF 2.1.0 severity mapping.\n */\nconst sarifLevelMap: Record<string, string> = {\n error: 'error',\n warning: 'warning',\n info: 'note',\n hint: 'note',\n};\n\n/**\n * Format diagnostics in SARIF 2.1.0 format.\n *\n * @see https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html\n */\nexport function formatSarif(\n results: Array<{ uri: string; diagnostics: Diagnostic[] }>,\n): string {\n // Collect unique rule IDs\n const ruleIds = new Set<string>();\n for (const { diagnostics } of results) {\n for (const d of diagnostics) {\n ruleIds.add(d.code);\n }\n }\n\n // Build SARIF results\n const sarifResults = [];\n for (const { uri, diagnostics } of results) {\n for (const d of diagnostics) {\n sarifResults.push({\n ruleId: d.code,\n level: sarifLevelMap[d.severity] ?? 'note',\n message: { text: d.message },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri },\n region: {\n startLine: d.range.start.line + 1,\n startColumn: d.range.start.character + 1,\n endLine: d.range.end.line + 1,\n endColumn: d.range.end.character + 1,\n },\n },\n },\n ],\n });\n }\n }\n\n const sarif = {\n $schema: 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/master/Schemata/sarif-schema-2.1.0.json',\n version: '2.1.0' as const,\n runs: [\n {\n tool: {\n driver: {\n name: 'spindle-lsp',\n version: '0.1.0',\n rules: Array.from(ruleIds).map(id => ({\n id,\n shortDescription: { text: `Spindle diagnostic ${id}` },\n })),\n },\n },\n results: sarifResults,\n },\n ],\n };\n\n return JSON.stringify(sarif, null, 2);\n}\n", "import { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { glob } from 'glob';\n\nimport { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport { computeDiagnostics } from '../plugins/diagnostics.js';\nimport { loadConfigFromDisk, findConfigFile } from '../core/workspace/config-loader.js';\nimport type { Diagnostic } from '../core/types.js';\nimport { formatPretty } from './reporters/pretty.js';\nimport { formatJson } from './reporters/json.js';\nimport { formatSarif } from './reporters/sarif.js';\n\n// ---------------------------------------------------------------------------\n// Argument parsing\n// ---------------------------------------------------------------------------\n\ninterface CheckOptions {\n format: 'pretty' | 'json' | 'sarif';\n severity: 'error' | 'warning' | 'info' | 'hint' | null;\n configPath: string | null;\n patterns: string[];\n}\n\nfunction parseArgs(args: string[]): CheckOptions {\n const options: CheckOptions = {\n format: 'pretty',\n severity: null,\n configPath: null,\n patterns: [],\n };\n\n let i = 0;\n while (i < args.length) {\n const arg = args[i];\n\n if (arg === '--format' && i + 1 < args.length) {\n const fmt = args[i + 1];\n if (fmt === 'pretty' || fmt === 'json' || fmt === 'sarif') {\n options.format = fmt;\n }\n i += 2;\n } else if (arg.startsWith('--format=')) {\n const fmt = arg.slice('--format='.length);\n if (fmt === 'pretty' || fmt === 'json' || fmt === 'sarif') {\n options.format = fmt;\n }\n i++;\n } else if (arg === '--severity' && i + 1 < args.length) {\n const sev = args[i + 1];\n if (sev === 'error' || sev === 'warning' || sev === 'info' || sev === 'hint') {\n options.severity = sev;\n }\n i += 2;\n } else if (arg.startsWith('--severity=')) {\n const sev = arg.slice('--severity='.length);\n if (sev === 'error' || sev === 'warning' || sev === 'info' || sev === 'hint') {\n options.severity = sev;\n }\n i++;\n } else if (arg === '--config' && i + 1 < args.length) {\n options.configPath = args[i + 1];\n i += 2;\n } else if (arg.startsWith('--config=')) {\n options.configPath = arg.slice('--config='.length);\n i++;\n } else if (!arg.startsWith('--')) {\n options.patterns.push(arg);\n i++;\n } else {\n // Skip unknown flags\n i++;\n }\n }\n\n if (options.patterns.length === 0) {\n options.patterns = ['**/*.{tw,twee}'];\n }\n\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Severity filtering\n// ---------------------------------------------------------------------------\n\nconst SEVERITY_ORDER = ['hint', 'info', 'warning', 'error'] as const;\n\nfunction filterBySeverity(\n diagnostics: Diagnostic[],\n minSeverity: 'error' | 'warning' | 'info' | 'hint',\n): Diagnostic[] {\n const minIdx = SEVERITY_ORDER.indexOf(minSeverity);\n return diagnostics.filter(d => {\n const idx = SEVERITY_ORDER.indexOf(d.severity);\n return idx >= minIdx;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\nexport async function runCheck(args: string[]): Promise<number> {\n const options = parseArgs(args);\n\n // Determine workspace root (cwd)\n const cwd = process.cwd();\n\n // Resolve files via glob\n const files: string[] = [];\n for (const pattern of options.patterns) {\n const matches = await glob(pattern, {\n cwd,\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n // Deduplicate\n const uniqueFiles = [...new Set(files)];\n\n if (uniqueFiles.length === 0) {\n if (options.format === 'pretty') {\n console.log('No files found');\n } else if (options.format === 'json') {\n console.log(JSON.stringify({ files: [] }, null, 2));\n } else {\n console.log(formatSarif([]));\n }\n return 0;\n }\n\n // Load project config \u2014 search from the common ancestor of matched files,\n // walking up to find the config file (covers running from a different cwd)\n let configRoot: string;\n if (options.configPath) {\n configRoot = resolve(cwd, options.configPath, '..');\n } else {\n // Find the common directory of all matched files\n const dirs = uniqueFiles.map(f => resolve(f, '..'));\n configRoot = dirs.reduce((a, b) => {\n while (!b.startsWith(a)) a = resolve(a, '..');\n return a;\n });\n // Walk up from common dir to find config (max 10 levels)\n let search = configRoot;\n for (let i = 0; i < 10; i++) {\n if (findConfigFile(search)) { configRoot = search; break; }\n const parent = resolve(search, '..');\n if (parent === search) break;\n search = parent;\n }\n }\n const projectConfig = loadConfigFromDisk(configRoot);\n\n // Create workspace and load files\n const workspace = new WorkspaceModel();\n const fileContents = new Map<string, string>();\n for (const filePath of uniqueFiles) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = pathToFileURL(filePath).toString();\n fileContents.set(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n workspace.initialize(fileContents);\n\n // Load user macros from config\n if (Object.keys(projectConfig.macros).length > 0) {\n workspace.macros.loadSupplements(projectConfig.macros);\n }\n\n // Compute diagnostics for each file\n const allResults: Array<{ uri: string; diagnostics: Diagnostic[] }> = [];\n let hasErrors = false;\n\n for (const uri of fileContents.keys()) {\n let diags = computeDiagnostics(uri, workspace);\n\n // Filter by severity if specified\n if (options.severity) {\n diags = filterBySeverity(diags, options.severity);\n }\n\n if (diags.length > 0) {\n allResults.push({ uri, diagnostics: diags });\n if (diags.some(d => d.severity === 'error')) {\n hasErrors = true;\n }\n }\n }\n\n // Format output\n switch (options.format) {\n case 'pretty':\n console.log(formatPretty(allResults));\n break;\n case 'json':\n console.log(formatJson(allResults));\n break;\n case 'sarif':\n console.log(formatSarif(allResults));\n break;\n }\n\n // Cleanup\n workspace.dispose();\n\n return hasErrors ? 1 : 0;\n}\n", "import type { Range } from '../core/types.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\n\n// ---------------------------------------------------------------------------\n// Block macro patterns for indentation\n// ---------------------------------------------------------------------------\n\n/**\n * Matches opening block macros: {if ...}, {for ...}, {switch ...}, {unless ...}\n * Also handles custom block macros via generic pattern.\n */\nconst BLOCK_OPEN_REGEX = /^\\s*\\{(if|for|switch|unless|widget)\\b/i;\n\n/**\n * Matches closing block macros: {/if}, {/for}, {/switch}, {/unless}\n */\nconst BLOCK_CLOSE_REGEX = /^\\s*\\{\\/(if|for|switch|unless|widget)\\b/i;\n\n/**\n * Passage header pattern.\n */\nconst PASSAGE_HEADER_REGEX = /^(::)\\s+/;\n\n// ---------------------------------------------------------------------------\n// Core format functions (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Format an entire document.\n *\n * Rules:\n * 1. Indent content inside block macros by 2 spaces per nesting level\n * 2. Remove trailing whitespace from each line\n * 3. Ensure file ends with a single newline\n * 4. Normalize passage headers: `:: Name [tag]` -> `:: Name [tag]`\n */\nexport function formatDocument(text: string): string {\n const lines = text.split('\\n');\n const result: string[] = [];\n let indentLevel = 0;\n\n for (let i = 0; i < lines.length; i++) {\n let line = lines[i];\n\n // Remove trailing whitespace\n line = line.replace(/\\s+$/, '');\n\n // Normalize passage headers\n if (PASSAGE_HEADER_REGEX.test(line)) {\n line = normalizePassageHeader(line);\n // Reset indent at passage boundaries\n indentLevel = 0;\n result.push(line);\n continue;\n }\n\n const trimmed = line.trim();\n\n // Empty lines: keep them but without extra whitespace\n if (trimmed === '') {\n result.push('');\n continue;\n }\n\n // Check if this line closes a block (reduce indent before writing)\n if (BLOCK_CLOSE_REGEX.test(trimmed)) {\n indentLevel = Math.max(0, indentLevel - 1);\n }\n\n // Apply indentation\n const indented = indentLevel > 0\n ? ' '.repeat(indentLevel) + trimmed\n : trimmed;\n result.push(indented);\n\n // Check if this line opens a block (increase indent for subsequent lines)\n if (BLOCK_OPEN_REGEX.test(trimmed)) {\n indentLevel++;\n }\n }\n\n // Ensure file ends with a single newline\n let output = result.join('\\n');\n output = output.replace(/\\n*$/, '\\n');\n\n return output;\n}\n\n/**\n * Format a specific range within a document.\n * Extracts the range, formats it, and replaces back.\n */\nexport function formatRange(text: string, range: Range): string {\n const lines = text.split('\\n');\n const startLine = Math.max(0, range.start.line);\n const endLine = Math.min(lines.length - 1, range.end.line);\n\n // Extract the range\n const rangeLines = lines.slice(startLine, endLine + 1);\n const rangeText = rangeLines.join('\\n');\n\n // Format just that section\n const formatted = formatDocument(rangeText);\n const formattedLines = formatted.replace(/\\n$/, '').split('\\n');\n\n // Reconstruct the full document\n const before = lines.slice(0, startLine);\n const after = lines.slice(endLine + 1);\n const result = [...before, ...formattedLines, ...after].join('\\n');\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Normalize a passage header line.\n * Collapses whitespace: `:: Name [tag]` -> `:: Name [tag]`\n */\nfunction normalizePassageHeader(line: string): string {\n // Split into parts: \"::\", name, optional tags/metadata\n const headerMatch = line.match(/^::\\s+(.*)/);\n if (!headerMatch) return line;\n\n const rest = headerMatch[1];\n\n // Check for tags in brackets\n const bracketIdx = rest.indexOf('[');\n const braceIdx = rest.indexOf('{');\n\n let name: string;\n let suffix = '';\n\n if (bracketIdx !== -1 && (braceIdx === -1 || bracketIdx < braceIdx)) {\n name = rest.substring(0, bracketIdx).trim();\n suffix = ' ' + rest.substring(bracketIdx).trim();\n } else if (braceIdx !== -1) {\n name = rest.substring(0, braceIdx).trim();\n suffix = ' ' + rest.substring(braceIdx).trim();\n } else {\n name = rest.trim();\n }\n\n return `:: ${name}${suffix}`;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const formatPlugin: SpindlePlugin = {\n id: 'format',\n capabilities: {\n documentFormattingProvider: true,\n documentRangeFormattingProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentFormatting((params) => {\n const text = ctx.workspace.documents.getText(params.textDocument.uri);\n if (text === undefined) return [];\n\n const formatted = formatDocument(text);\n if (formatted === text) return [];\n\n const lines = text.split('\\n');\n return [{\n range: {\n start: { line: 0, character: 0 },\n end: { line: lines.length - 1, character: lines[lines.length - 1].length },\n },\n newText: formatted,\n }];\n });\n\n ctx.connection.onDocumentRangeFormatting((params) => {\n const text = ctx.workspace.documents.getText(params.textDocument.uri);\n if (text === undefined) return [];\n\n const range: Range = {\n start: { line: params.range.start.line, character: params.range.start.character },\n end: { line: params.range.end.line, character: params.range.end.character },\n };\n\n const formatted = formatRange(text, range);\n if (formatted === text) return [];\n\n const lines = text.split('\\n');\n return [{\n range: {\n start: { line: 0, character: 0 },\n end: { line: lines.length - 1, character: lines[lines.length - 1].length },\n },\n newText: formatted,\n }];\n });\n },\n};\n", "import { readFileSync, writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { glob } from 'glob';\n\nimport { formatDocument } from '../plugins/format.js';\n\n// ---------------------------------------------------------------------------\n// Argument parsing\n// ---------------------------------------------------------------------------\n\ninterface FormatOptions {\n check: boolean;\n patterns: string[];\n}\n\nfunction parseArgs(args: string[]): FormatOptions {\n const options: FormatOptions = {\n check: false,\n patterns: [],\n };\n\n for (const arg of args) {\n if (arg === '--check') {\n options.check = true;\n } else if (!arg.startsWith('--')) {\n options.patterns.push(arg);\n }\n }\n\n if (options.patterns.length === 0) {\n options.patterns = ['**/*.{tw,twee}'];\n }\n\n return options;\n}\n\n// ---------------------------------------------------------------------------\n// Main entry point\n// ---------------------------------------------------------------------------\n\nexport async function runFormat(args: string[]): Promise<number> {\n const options = parseArgs(args);\n const cwd = process.cwd();\n\n // Resolve files via glob\n const files: string[] = [];\n for (const pattern of options.patterns) {\n const matches = await glob(pattern, {\n cwd,\n absolute: true,\n nodir: true,\n });\n files.push(...matches);\n }\n\n const uniqueFiles = [...new Set(files)];\n\n if (uniqueFiles.length === 0) {\n console.log('No files found');\n return 0;\n }\n\n const unformatted: string[] = [];\n\n for (const filePath of uniqueFiles) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const formatted = formatDocument(text);\n\n if (formatted !== text) {\n if (options.check) {\n const relative = filePath.startsWith(cwd)\n ? filePath.slice(cwd.length + 1)\n : filePath;\n unformatted.push(relative);\n } else {\n writeFileSync(filePath, formatted, 'utf-8');\n }\n }\n } catch {\n // Skip unreadable/unwritable files\n }\n }\n\n if (options.check) {\n if (unformatted.length > 0) {\n for (const file of unformatted) {\n console.log(file);\n }\n console.log(`\\n${unformatted.length} file${unformatted.length !== 1 ? 's' : ''} would be reformatted`);\n return 1;\n }\n return 0;\n }\n\n return 0;\n}\n", "import type { ServerCapabilities } from 'vscode-languageserver';\nimport type { SpindlePlugin, SpindleConfig } from './plugin-api.js';\n\n/**\n * Filter plugins based on the disabled list in config.\n * Returns only plugins whose id is NOT in `config.disabledPlugins`.\n */\nexport function loadPlugins(\n allPlugins: SpindlePlugin[],\n config: SpindleConfig,\n): SpindlePlugin[] {\n const disabled = new Set(config.disabledPlugins ?? []);\n return allPlugins.filter((p) => !disabled.has(p.id));\n}\n\n/**\n * Deep-merge capabilities from all plugins into a single ServerCapabilities object.\n *\n * For boolean capabilities, any plugin providing `true` wins.\n * For object capabilities, properties are merged (later plugins override on collision).\n */\nexport function mergeCapabilities(\n plugins: SpindlePlugin[],\n): Partial<ServerCapabilities> {\n const merged: Record<string, unknown> = {};\n\n for (const plugin of plugins) {\n for (const [key, value] of Object.entries(plugin.capabilities)) {\n const existing = merged[key];\n if (existing === undefined) {\n merged[key] = value;\n } else if (\n typeof existing === 'object' &&\n existing !== null &&\n typeof value === 'object' &&\n value !== null &&\n !Array.isArray(existing) &&\n !Array.isArray(value)\n ) {\n // Deep merge plain objects one level\n merged[key] = { ...(existing as Record<string, unknown>), ...(value as Record<string, unknown>) };\n } else {\n // Primitives / booleans: later value wins (true wins over false)\n merged[key] = value;\n }\n }\n }\n\n return merged as Partial<ServerCapabilities>;\n}\n", "import { TextDocumentSyncKind } from 'vscode-languageserver';\nimport type { ServerCapabilities } from 'vscode-languageserver';\nimport type { SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { mergeCapabilities } from '../core/plugin/plugin-loader.js';\n\n/**\n * Build the full ServerCapabilities object by combining the base capabilities\n * (text document sync) with all plugin-contributed capabilities.\n */\nexport function buildCapabilities(\n plugins: SpindlePlugin[],\n): ServerCapabilities {\n const pluginCaps = mergeCapabilities(plugins);\n return {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n ...pluginCaps,\n };\n}\n", "import type { CompletionItem } from 'vscode-languageserver';\nimport type { Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core completion function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute completion items for a given position within a document.\n *\n * Contexts:\n * - After `{/` -> closing macro names (open block macros above cursor)\n * - After `{` -> macro names + widget names\n * - After `$` -> story variable names\n * - After `_` -> temp variable names from current document\n * - After `@` -> local variable names from current document\n * - After `$var.` -> declared object fields\n * - After `[[` -> passage names\n */\nexport function getCompletions(\n uri: string,\n position: Position,\n triggerChar: string | undefined,\n workspace: WorkspaceModel,\n): CompletionItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return [];\n const lineText = lines[position.line].substring(0, position.character);\n\n // --- Context: closing macro `{/` ---\n if (/\\{\\/[A-Za-z\\w-]*$/.test(lineText)) {\n return getClosingMacroCompletions(text, position, workspace);\n }\n\n // --- Context: dot-path field `$var.` ---\n const dotPathMatch = /\\$([A-Za-z_$][\\w$]*)\\.([A-Za-z_$][\\w$]*)?$/.exec(lineText);\n if (dotPathMatch) {\n return getDotPathCompletions(dotPathMatch[1], workspace);\n }\n\n // --- Context: story variable `$` ---\n if (/\\$[A-Za-z_$]?[\\w$]*$/.test(lineText) && !/\\$[A-Za-z_$][\\w$]*\\./.test(lineText)) {\n return getStoryVariableCompletions(workspace);\n }\n\n // --- Context: temporary variable `_` ---\n if (/_[A-Za-z_$]?[\\w$]*$/.test(lineText)) {\n return getTempVariableCompletions(text);\n }\n\n // --- Context: local variable `@` ---\n if (/@[A-Za-z_$]?[\\w$]*$/.test(lineText)) {\n return getLocalVariableCompletions(text);\n }\n\n // --- Context: passage link `[[` ---\n if (/\\[\\[[^\\]]*$/.test(lineText)) {\n return getPassageNameCompletions(workspace);\n }\n\n // --- Context: macro invocation `{` or `{partial` ---\n if (/(?:^|[^\\\\])\\{[A-Za-z\\w-]*$/.test(lineText)) {\n return getMacroCompletions(workspace);\n }\n\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getClosingMacroCompletions(\n text: string,\n position: Position,\n workspace: WorkspaceModel,\n): CompletionItem[] {\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n const openStack: string[] = [];\n for (const macro of macros) {\n if (macro.range.start.line > position.line ||\n (macro.range.start.line === position.line && macro.range.start.character >= position.character)) {\n break;\n }\n if (!macro.open) continue;\n if (!workspace.macros.isBlock(macro.name)) continue;\n\n if (macro.pair === -1) {\n openStack.push(macro.name);\n } else {\n const pairMacro = macros[macro.pair];\n if (pairMacro && (pairMacro.range.start.line > position.line ||\n (pairMacro.range.start.line === position.line && pairMacro.range.start.character > position.character))) {\n openStack.push(macro.name);\n }\n }\n }\n\n if (openStack.length === 0) return [];\n\n const seen = new Set<string>();\n const suggestions: string[] = [];\n for (let i = openStack.length - 1; i >= 0; i--) {\n const name = openStack[i];\n if (!seen.has(name)) {\n seen.add(name);\n suggestions.push(name);\n }\n }\n\n return suggestions.map((name, idx) => ({\n label: `{/${name}}`,\n kind: 14, // CompletionItemKind.Keyword\n detail: `Close {${name}}`,\n sortText: String(idx).padStart(3, '0'),\n insertText: `{/${name}}`,\n }));\n}\n\nfunction getMacroCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const items: CompletionItem[] = [];\n\n for (const macro of workspace.macros.getAllMacros()) {\n items.push({\n label: macro.name,\n kind: 3, // CompletionItemKind.Function\n detail: macro.block ? `(container macro) ${macro.name}` : `(macro) ${macro.name}`,\n documentation: macro.description ?? undefined,\n });\n }\n\n for (const widget of workspace.widgets.getAllWidgets()) {\n items.push({\n label: widget.name,\n kind: 3, // CompletionItemKind.Function\n detail: `(widget) ${widget.name}`,\n documentation: widget.params.length > 0\n ? `Parameters: ${widget.params.map(p => `@${p}`).join(', ')}`\n : undefined,\n });\n }\n\n return items;\n}\n\nfunction getStoryVariableCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const declared = workspace.variables.getDeclared();\n if (declared.size === 0) return [];\n\n const items: CompletionItem[] = [];\n for (const [name, decl] of declared) {\n items.push({\n label: `$${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'story variable',\n insertText: name,\n documentation: decl.fields && decl.fields.length > 0\n ? `Fields: ${decl.fields.join(', ')}`\n : undefined,\n });\n }\n return items;\n}\n\nfunction getTempVariableCompletions(text: string): CompletionItem[] {\n const tempVarRegex = /_([A-Za-z_$][\\w$]*)/g;\n const names = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = tempVarRegex.exec(text)) !== null) {\n names.add(m[1]);\n }\n if (names.size === 0) return [];\n\n return Array.from(names).map(name => ({\n label: `_${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'temporary variable',\n insertText: name,\n }));\n}\n\nfunction getLocalVariableCompletions(text: string): CompletionItem[] {\n const atVarRegex = /@([A-Za-z_$][\\w$]*)/g;\n const names = new Set<string>();\n let m: RegExpExecArray | null;\n while ((m = atVarRegex.exec(text)) !== null) {\n names.add(m[1]);\n }\n if (names.size === 0) return [];\n\n return Array.from(names).map(name => ({\n label: `@${name}`,\n kind: 6, // CompletionItemKind.Variable\n detail: 'local/parameter variable',\n insertText: name,\n }));\n}\n\nfunction getDotPathCompletions(varName: string, workspace: WorkspaceModel): CompletionItem[] {\n const declared = workspace.variables.getDeclared();\n const decl = declared.get(varName);\n if (!decl || !decl.fields || decl.fields.length === 0) return [];\n\n return decl.fields.map(field => ({\n label: field,\n kind: 5, // CompletionItemKind.Field\n detail: `field of $${varName}`,\n }));\n}\n\nfunction getPassageNameCompletions(workspace: WorkspaceModel): CompletionItem[] {\n const passages = workspace.passages.getAllPassages();\n if (passages.length === 0) return [];\n\n return passages.map(p => ({\n label: p.name,\n kind: 18, // CompletionItemKind.Reference\n detail: p.uri,\n }));\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const completionsPlugin: SpindlePlugin = {\n id: 'completions',\n capabilities: {\n completionProvider: {\n triggerCharacters: ['{', '$', '_', '@', '[', '.'],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCompletion((params) => {\n const uri = params.textDocument.uri;\n const position: Position = {\n line: params.position.line,\n character: params.position.character,\n };\n const triggerChar = params.context?.triggerCharacter;\n return getCompletions(uri, position, triggerChar, ctx.workspace);\n });\n },\n};\n", "import type { Hover, Range as LspRange } from 'vscode-languageserver';\nimport type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\n\n// ---------------------------------------------------------------------------\n// Core hover function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface HoverResult {\n contents: string;\n range: Range;\n}\n\n/**\n * Compute hover information for the symbol at the given position.\n *\n * Provides information for:\n * - Macro names -> description, parameters, block/inline\n * - Variables -> \"Story variable\" / \"Temp variable\" / \"Local variable\" + type info\n * - Widget names -> widget info with params\n */\nexport function getHoverInfo(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Macro name hover ---\n // Check if cursor is on a macro name inside {macroName ...} or {/macroName}\n const macroResult = getMacroHover(line, position, workspace);\n if (macroResult) return macroResult;\n\n // --- Variable hover ---\n const varResult = getVariableHover(line, position, workspace);\n if (varResult) return varResult;\n\n // --- Widget invocation hover ---\n const widgetResult = getWidgetHover(line, position, workspace);\n if (widgetResult) return widgetResult;\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getMacroHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Match macro patterns: {macroName ...} or {/macroName}\n const macroRegex = /\\{(\\/)?(?:(?:[#.][a-zA-Z][\\w-]*\\s*)*)([A-Za-z][\\w-]*)/g;\n let match: RegExpExecArray | null;\n\n while ((match = macroRegex.exec(line)) !== null) {\n const name = match[2];\n const nameStart = match.index + match[0].indexOf(name);\n const nameEnd = nameStart + name.length;\n\n if (position.character >= nameStart && position.character <= nameEnd) {\n const info = workspace.macros.getMacro(name);\n if (info) {\n const parts: string[] = [];\n parts.push(`**${info.name}** _(${info.block ? 'container' : 'inline'} macro)_`);\n if (info.description) {\n parts.push('', info.description);\n }\n if (info.parameters && info.parameters.length > 0) {\n parts.push('', `Parameters: \\`${info.parameters.join(' ')}\\``);\n }\n\n return {\n contents: parts.join('\\n'),\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n\n // Check widgets\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return buildWidgetHover(widget, position.line, nameStart, nameEnd);\n }\n }\n }\n\n return null;\n}\n\nfunction getVariableHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Story variables: $name\n {\n const re = /\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const baseName = match[1].split('.')[0];\n const decl = workspace.variables.getDeclared().get(baseName);\n const typeInfo = decl?.fields && decl.fields.length > 0\n ? `\\n\\nFields: ${decl.fields.map(f => `\\`${f}\\``).join(', ')}`\n : '';\n return {\n contents: `**Story variable** \\`$${match[1]}\\`${typeInfo}`,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // Temp variables: _name\n {\n const re = /(?<!\\w)_([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n contents: `**Temp variable** \\`_${match[1]}\\``,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // Local variables: @name\n {\n const re = /(?<!\\w)@([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n contents: `**Local variable** \\`@${match[1]}\\``,\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n return null;\n}\n\nfunction getWidgetHover(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): HoverResult | null {\n // Widget invocation: {widgetName ...}\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1; // skip '{'\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return buildWidgetHover(widget, position.line, nameStart, nameEnd);\n }\n }\n }\n return null;\n}\n\nfunction buildWidgetHover(\n widget: import('../core/types.js').WidgetDef,\n line: number,\n nameStart: number,\n nameEnd: number,\n): HoverResult {\n const sig = widget.params.length > 0\n ? widget.params.map(p => `@${p}`).join(', ')\n : 'no parameters';\n return {\n contents: `**Widget** \\`${widget.name}\\`\\n\\nParameters: ${sig}\\n\\nDefined in: \\`${widget.uri}\\``,\n range: {\n start: { line, character: nameStart },\n end: { line, character: nameEnd },\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): LspRange {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const hoverPlugin: SpindlePlugin = {\n id: 'hover',\n capabilities: {\n hoverProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onHover((params): Hover | null => {\n const result = getHoverInfo(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n contents: { kind: 'markdown', value: result.contents },\n range: toLspRange(result.range),\n };\n });\n },\n};\n", "import type { SignatureHelp, SignatureInformation, ParameterInformation } from 'vscode-languageserver';\nimport type { Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Core signature help function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface SignatureHelpResult {\n signatures: Array<{\n label: string;\n documentation?: string;\n parameters: Array<{ label: string }>;\n }>;\n activeSignature: number;\n activeParameter: number;\n}\n\n/**\n * Compute signature help for the macro at the given position.\n *\n * When the cursor is inside macro arguments, shows parameter information\n * and highlights the active parameter based on argument count before cursor.\n */\nexport function getSignatureHelp(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): SignatureHelpResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const lineText = lines[position.line];\n const textBefore = lineText.substring(0, position.character);\n\n // Find the enclosing macro: {macroName args...\n const macroMatch = textBefore.match(/\\{(?:[#.][a-zA-Z][\\w-]*\\s*)*([A-Za-z][\\w-]*)\\s+([^}]*)$/);\n if (!macroMatch) return null;\n\n const macroName = macroMatch[1];\n const argsBefore = macroMatch[2];\n\n // Count arguments before cursor to determine active parameter\n const activeParameter = argsBefore.trim() === '' ? 0 : lexArguments(argsBefore).length;\n\n // Check builtin macros\n const macroInfo = workspace.macros.getMacro(macroName);\n if (macroInfo && macroInfo.parameters && macroInfo.parameters.length > 0) {\n const paramLabels = macroInfo.parameters;\n return {\n signatures: [{\n label: `{${macroName} ${paramLabels.join(' ')}}`,\n documentation: macroInfo.description ?? undefined,\n parameters: paramLabels.map(p => ({ label: p })),\n }],\n activeSignature: 0,\n activeParameter,\n };\n }\n\n // Check widgets\n const widget = workspace.widgets.getWidget(macroName);\n if (widget && widget.params.length > 0) {\n const paramLabels = widget.params.map(p => `@${p}`);\n return {\n signatures: [{\n label: `{${macroName} ${paramLabels.join(', ')}}`,\n documentation: `Widget defined in: ${widget.uri}`,\n parameters: paramLabels.map(p => ({ label: p })),\n }],\n activeSignature: 0,\n activeParameter,\n };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const signaturePlugin: SpindlePlugin = {\n id: 'signature',\n capabilities: {\n signatureHelpProvider: {\n triggerCharacters: [' ', '\"', \"'\"],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onSignatureHelp((params): SignatureHelp | null => {\n const result = getSignatureHelp(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n\n const signatures: SignatureInformation[] = result.signatures.map(sig => ({\n label: sig.label,\n documentation: sig.documentation,\n parameters: sig.parameters.map(p => ({ label: p.label }) as ParameterInformation),\n }));\n\n return {\n signatures,\n activeSignature: result.activeSignature,\n activeParameter: result.activeParameter,\n };\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core definition function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DefinitionResult {\n uri: string;\n range: Range;\n}\n\n/**\n * Compute go-to-definition for the symbol at the given position.\n *\n * Supports:\n * - Passage name in [[link]] -> jump to passage header\n * - Passage name in macro args (goto, include, link, button) -> jump to passage\n * - Widget name in {widgetName} -> jump to widget definition\n */\nexport function getDefinition(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Passage ref in [[link]] ---\n const linkResult = getPassageLinkDefinition(text, position, workspace);\n if (linkResult) return linkResult;\n\n // --- Passage ref in macro args (goto, include, link, button) ---\n const macroPassageResult = getMacroPassageDefinition(line, position, workspace);\n if (macroPassageResult) return macroPassageResult;\n\n // --- Widget name -> definition ---\n const widgetResult = getWidgetDefinition(line, position, workspace);\n if (widgetResult) return widgetResult;\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Sub-functions\n// ---------------------------------------------------------------------------\n\nfunction getPassageLinkDefinition(\n text: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n const links = parseLinks(text);\n for (const link of links) {\n if (link.range.start.line === position.line &&\n position.character >= link.range.start.character &&\n position.character <= link.range.end.character) {\n const passage = workspace.passages.getPassage(link.name);\n if (passage) {\n return {\n uri: passage.uri,\n range: passage.headerEnd,\n };\n }\n }\n }\n return null;\n}\n\nfunction getMacroPassageDefinition(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n // Match {goto \"passage\"}, {include \"passage\"}, {link \"text\" \"passage\"}, {button \"text\" \"passage\"}\n const patterns = [\n /\\{(?:goto|include)\\s+\"([^\"]+)\"\\s*\\}/gi,\n /\\{(?:link|button)\\s+\"[^\"]*\"\\s+\"([^\"]+)\"\\s*\\}/gi,\n ];\n\n for (const pattern of patterns) {\n pattern.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = pattern.exec(line)) !== null) {\n const passageName = match[1];\n const nameStart = match.index + match[0].indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n const passage = workspace.passages.getPassage(passageName);\n if (passage) {\n return {\n uri: passage.uri,\n range: passage.headerEnd,\n };\n }\n }\n }\n }\n return null;\n}\n\nfunction getWidgetDefinition(\n line: string,\n position: Position,\n workspace: WorkspaceModel,\n): DefinitionResult | null {\n // Match {widgetName ...} invocations\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1; // skip '{'\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n // Only if it's not a known macro\n if (workspace.macros.getMacro(name)) continue;\n\n const widget = workspace.widgets.getWidget(name);\n if (widget) {\n return {\n uri: widget.uri,\n range: widget.range,\n };\n }\n }\n }\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const definitionPlugin: SpindlePlugin = {\n id: 'definition',\n capabilities: {\n definitionProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDefinition((params) => {\n const result = getDefinition(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n uri: result.uri,\n range: toLspRange(result.range),\n };\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core references function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface ReferenceLocation {\n uri: string;\n range: Range;\n}\n\n/**\n * Find all references to the symbol at the given position.\n *\n * Supports:\n * - Passage header -> all [[links]] + macro refs to that passage\n * - Variable -> all usages across workspace\n * - Widget -> all invocations\n */\nexport function findReferences(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return [];\n const line = lines[position.line];\n\n // --- Passage header ---\n const passageHeaderRegex = /^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/;\n if (line.trimStart().startsWith('::')) {\n const headerMatch = passageHeaderRegex.exec(line);\n if (headerMatch) {\n const passageName = headerMatch[1].trim();\n const nameStart = line.indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return findPassageReferences(passageName, workspace, includeDeclaration);\n }\n }\n }\n\n // --- $variable ---\n {\n const varRegex = /\\$([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = varRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const varName = match[1];\n return findVariableReferences(varName, workspace, includeDeclaration);\n }\n }\n }\n\n // --- Widget ---\n {\n const widgetRegex = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = widgetRegex.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1;\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n if (!workspace.macros.getMacro(name) && workspace.widgets.getWidget(name)) {\n return findWidgetReferences(name, workspace, includeDeclaration);\n }\n }\n }\n }\n\n // --- Passage name in link (also check passage names) ---\n {\n const allPassages = workspace.passages.getAllPassages();\n const passageNames = new Set(allPassages.map(p => p.name));\n // Try to extract a word at cursor and see if it's a passage name\n const wordRegex = /[A-Za-z_$][\\w$\\s]*/g;\n let match: RegExpExecArray | null;\n while ((match = wordRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n const word = match[0].trim();\n if (passageNames.has(word)) {\n return findPassageReferences(word, workspace, includeDeclaration);\n }\n }\n }\n }\n\n return [];\n}\n\n// ---------------------------------------------------------------------------\n// Reference finders\n// ---------------------------------------------------------------------------\n\n/**\n * Find all references to a passage across the workspace.\n */\nexport function findPassageReferences(\n passageName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration (passage header)\n if (includeDeclaration) {\n const passage = workspace.passages.getPassage(passageName);\n if (passage) {\n locations.push({\n uri: passage.uri,\n range: passage.headerEnd,\n });\n }\n }\n\n // Scan all documents for passage references\n const gotoRegex = /\\{(?:goto|include)\\s+\"([^\"]+)\"\\s*\\}/gi;\n const linkMacroRegex = /\\{(?:link|button)\\s+\"[^\"]*\"\\s+\"([^\"]+)\"\\s*\\}/gi;\n\n for (const docUri of workspace.documents.getUris()) {\n const docText = workspace.documents.getText(docUri);\n if (!docText) continue;\n\n // Find [[passage]] links\n const links = parseLinks(docText);\n for (const link of links) {\n if (link.name === passageName) {\n locations.push({ uri: docUri, range: link.range });\n }\n }\n\n // Find {goto \"passage\"} and {include \"passage\"}\n const lines = docText.split('\\n');\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n for (const regex of [gotoRegex, linkMacroRegex]) {\n regex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = regex.exec(line)) !== null) {\n if (match[1] === passageName) {\n const nameStart = match.index + match[0].indexOf(match[1]);\n locations.push({\n uri: docUri,\n range: {\n start: { line: lineNum, character: nameStart },\n end: { line: lineNum, character: nameStart + match[1].length },\n },\n });\n }\n }\n }\n }\n }\n\n return locations;\n}\n\n/**\n * Find all references to a variable across the workspace.\n */\nexport function findVariableReferences(\n varName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration from StoryVariables\n if (includeDeclaration) {\n const decl = workspace.variables.getDeclared().get(varName);\n if (decl?.declarationRange && decl.declarationUri) {\n locations.push({\n uri: decl.declarationUri,\n range: decl.declarationRange,\n });\n }\n }\n\n // Get all usages from the variable tracker\n const usages = workspace.variables.getUsages(varName);\n for (const u of usages) {\n locations.push({ uri: u.uri, range: u.range });\n }\n\n return locations;\n}\n\n/**\n * Find all references to a widget across the workspace.\n */\nexport function findWidgetReferences(\n widgetName: string,\n workspace: WorkspaceModel,\n includeDeclaration: boolean,\n): ReferenceLocation[] {\n const locations: ReferenceLocation[] = [];\n\n // Include declaration\n if (includeDeclaration) {\n const widget = workspace.widgets.getWidget(widgetName);\n if (widget) {\n locations.push({ uri: widget.uri, range: widget.range });\n }\n }\n\n // Scan all documents for {widgetName ...} invocations\n const widgetInvocationRegex = /\\{([A-Za-z_$][\\w$]*)\\b/g;\n\n for (const docUri of workspace.documents.getUris()) {\n const docText = workspace.documents.getText(docUri);\n if (!docText) continue;\n\n const lines = docText.split('\\n');\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // Skip widget definition lines\n if (/\\{widget\\s+\"/i.test(line)) continue;\n\n widgetInvocationRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = widgetInvocationRegex.exec(line)) !== null) {\n if (match[1] === widgetName) {\n const nameStart = match.index + 1; // skip '{'\n locations.push({\n uri: docUri,\n range: {\n start: { line: lineNum, character: nameStart },\n end: { line: lineNum, character: nameStart + widgetName.length },\n },\n });\n }\n }\n }\n }\n\n return locations;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const referencesPlugin: SpindlePlugin = {\n id: 'references',\n capabilities: {\n referencesProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onReferences((params) => {\n const refs = findReferences(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n params.context.includeDeclaration,\n );\n return refs.map(r => ({\n uri: r.uri,\n range: toLspRange(r.range),\n }));\n });\n },\n};\n", "import type { Position, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport {\n findPassageReferences,\n findVariableReferences,\n findWidgetReferences,\n} from './references.js';\n\n// ---------------------------------------------------------------------------\n// Core rename functions (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface PrepareRenameResult {\n range: Range;\n placeholder: string;\n}\n\nexport interface RenameEdit {\n range: Range;\n newText: string;\n}\n\n/**\n * Determine if the symbol at the cursor is renameable, and return its range + placeholder.\n */\nexport function prepareRename(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): PrepareRenameResult | null {\n const symbol = resolveSymbolAtCursor(uri, position, workspace);\n if (!symbol) return null;\n return { range: symbol.range, placeholder: symbol.name };\n}\n\n/**\n * Compute all text edits for a rename operation.\n * Returns a map of URI -> list of edits.\n */\nexport function computeRename(\n uri: string,\n position: Position,\n newName: string,\n workspace: WorkspaceModel,\n): Map<string, RenameEdit[]> {\n const symbol = resolveSymbolAtCursor(uri, position, workspace);\n if (!symbol) return new Map();\n\n const edits = new Map<string, RenameEdit[]>();\n\n function addEdit(editUri: string, range: Range, text: string) {\n const existing = edits.get(editUri) ?? [];\n existing.push({ range, newText: text });\n edits.set(editUri, existing);\n }\n\n switch (symbol.kind) {\n case 'passage': {\n const refs = findPassageReferences(symbol.name, workspace, true);\n for (const ref of refs) {\n addEdit(ref.uri, ref.range, newName);\n }\n break;\n }\n\n case 'variable': {\n const bareName = newName.startsWith('$') ? newName.slice(1) : newName;\n const refs = findVariableReferences(symbol.name, workspace, true);\n for (const ref of refs) {\n addEdit(ref.uri, ref.range, bareName);\n }\n break;\n }\n\n case 'widget': {\n // Rename invocations\n const invocationRefs = findWidgetReferences(symbol.name, workspace, false);\n for (const ref of invocationRefs) {\n addEdit(ref.uri, ref.range, newName);\n }\n\n // Rename definition\n const widget = workspace.widgets.getWidget(symbol.name);\n if (widget) {\n // The widget definition is {widget \"name\" ...}\n // We need to find and replace just the name inside the quotes\n const docText = workspace.documents.getText(widget.uri);\n if (docText) {\n const lines = docText.split('\\n');\n const defLine = lines[widget.range.start.line];\n if (defLine) {\n const defSlice = defLine.slice(widget.range.start.character);\n const nameMatch = /\\{widget\\s+\"([^\"]+)\"/.exec(defSlice);\n if (nameMatch) {\n const nameOffsetInSlice = defSlice.indexOf(nameMatch[1]);\n const nameStart = widget.range.start.character + nameOffsetInSlice;\n addEdit(widget.uri, {\n start: { line: widget.range.start.line, character: nameStart },\n end: { line: widget.range.start.line, character: nameStart + symbol.name.length },\n }, newName);\n }\n }\n }\n }\n break;\n }\n }\n\n return edits;\n}\n\n// ---------------------------------------------------------------------------\n// Symbol resolution\n// ---------------------------------------------------------------------------\n\ninterface SymbolInfo {\n kind: 'passage' | 'variable' | 'widget';\n name: string;\n range: Range;\n}\n\nfunction resolveSymbolAtCursor(\n uri: string,\n position: Position,\n workspace: WorkspaceModel,\n): SymbolInfo | null {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n if (position.line >= lines.length) return null;\n const line = lines[position.line];\n\n // --- Passage header ---\n const passageHeaderRegex = /^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/;\n if (line.trimStart().startsWith('::')) {\n const headerMatch = passageHeaderRegex.exec(line);\n if (headerMatch) {\n const passageName = headerMatch[1].trim();\n const nameStart = line.indexOf(passageName);\n const nameEnd = nameStart + passageName.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return {\n kind: 'passage',\n name: passageName,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n\n // --- $variable ---\n {\n const varRegex = /\\$([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = varRegex.exec(line)) !== null) {\n const start = match.index;\n const end = start + match[0].length;\n if (position.character >= start && position.character <= end) {\n return {\n kind: 'variable',\n name: match[1],\n range: {\n start: { line: position.line, character: start },\n end: { line: position.line, character: end },\n },\n };\n }\n }\n }\n\n // --- Widget definition: {widget \"name\" ...} ---\n {\n const widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"/gi;\n let match: RegExpExecArray | null;\n while ((match = widgetDefRegex.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + match[0].indexOf(name);\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n return {\n kind: 'widget',\n name,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n\n // --- Widget invocation: {widgetName ...} ---\n {\n const re = /\\{([A-Za-z_$][\\w$]*)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(line)) !== null) {\n const name = match[1];\n const nameStart = match.index + 1;\n const nameEnd = nameStart + name.length;\n if (position.character >= nameStart && position.character <= nameEnd) {\n if (!workspace.macros.getMacro(name) && workspace.widgets.getWidget(name)) {\n return {\n kind: 'widget',\n name,\n range: {\n start: { line: position.line, character: nameStart },\n end: { line: position.line, character: nameEnd },\n },\n };\n }\n }\n }\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const renamePlugin: SpindlePlugin = {\n id: 'rename',\n capabilities: {\n renameProvider: {\n prepareProvider: true,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onPrepareRename((params) => {\n const result = prepareRename(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n ctx.workspace,\n );\n if (!result) return null;\n return {\n range: toLspRange(result.range),\n placeholder: result.placeholder,\n };\n });\n\n ctx.connection.onRenameRequest((params) => {\n const editsMap = computeRename(\n params.textDocument.uri,\n { line: params.position.line, character: params.position.character },\n params.newName,\n ctx.workspace,\n );\n\n const changes: Record<string, import('vscode-languageserver').TextEdit[]> = {};\n for (const [editUri, edits] of editsMap) {\n changes[editUri] = edits.map(e => ({\n range: toLspRange(e.range),\n newText: e.newText,\n }));\n }\n\n return { changes };\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport {\n findPassageReferences,\n findVariableReferences,\n findWidgetReferences,\n} from './references.js';\n\n// ---------------------------------------------------------------------------\n// Core code lens function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface CodeLensItem {\n range: Range;\n command: {\n title: string;\n };\n}\n\n/**\n * Compute code lenses for a document.\n *\n * Shows:\n * - Above passage headers: \"N references\"\n * - Above widget definitions: \"N usages\"\n * - Above StoryVariables declarations: \"N usages\"\n */\nexport function computeCodeLenses(uri: string, workspace: WorkspaceModel): CodeLensItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n const lenses: CodeLensItem[] = [];\n\n const storyVarsPassage = workspace.passages.getStoryVariables();\n const isStoryVarsFile = storyVarsPassage && storyVarsPassage.uri === uri;\n\n for (let lineNum = 0; lineNum < lines.length; lineNum++) {\n const line = lines[lineNum];\n\n // --- Passage headers ---\n const passageMatch = line.match(/^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/);\n if (passageMatch) {\n const passageName = passageMatch[1].trim();\n if (passageName === 'StoryData') continue;\n\n const refs = findPassageReferences(passageName, workspace, true);\n const refCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${refCount} reference${refCount !== 1 ? 's' : ''}`,\n },\n });\n continue;\n }\n\n // --- Widget definitions ---\n const widgetMatch = line.match(/\\{widget\\s+\"([^\"]+)\"/);\n if (widgetMatch) {\n const widgetName = widgetMatch[1];\n const refs = findWidgetReferences(widgetName, workspace, true);\n const usageCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${usageCount} usage${usageCount !== 1 ? 's' : ''}`,\n },\n });\n }\n\n // --- StoryVariables declarations ---\n if (isStoryVarsFile) {\n const varDeclMatch = line.match(/^\\$([A-Za-z_$][\\w$]*)\\s*=/);\n if (varDeclMatch) {\n const varName = varDeclMatch[1];\n const refs = findVariableReferences(varName, workspace, true);\n const usageCount = Math.max(0, refs.length - 1);\n\n lenses.push({\n range: {\n start: { line: lineNum, character: 0 },\n end: { line: lineNum, character: line.length },\n },\n command: {\n title: `${usageCount} usage${usageCount !== 1 ? 's' : ''}`,\n },\n });\n }\n }\n }\n\n return lenses;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const codeLensPlugin: SpindlePlugin = {\n id: 'code-lens',\n capabilities: {\n codeLensProvider: {\n resolveProvider: false,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCodeLens((params) => {\n const lenses = computeCodeLenses(params.textDocument.uri, ctx.workspace);\n return lenses.map(l => ({\n range: toLspRange(l.range),\n command: {\n title: l.command.title,\n command: 'spindle.findReferences',\n },\n }));\n });\n },\n};\n", "import type { Range, Position } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\nimport { lexArguments } from '../core/parsing/argument-lexer.js';\n\n// ---------------------------------------------------------------------------\n// Core inlay hints function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface InlayHintItem {\n position: Position;\n label: string;\n kind: 'type' | 'parameter';\n}\n\n/**\n * Compute inlay hints for a document within a range.\n *\n * Provides:\n * - Widget invocation args -> parameter name hints\n * - Variable type hints in StoryVariables\n */\nexport function computeInlayHints(\n uri: string,\n range: Range,\n workspace: WorkspaceModel,\n): InlayHintItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const hints: InlayHintItem[] = [];\n\n addWidgetParamHints(text, range, workspace, hints);\n addVariableTypeHints(uri, text, range, workspace, hints);\n\n return hints;\n}\n\n// ---------------------------------------------------------------------------\n// Widget parameter hints\n// ---------------------------------------------------------------------------\n\nfunction addWidgetParamHints(\n text: string,\n range: Range,\n workspace: WorkspaceModel,\n hints: InlayHintItem[],\n): void {\n const allWidgets = workspace.widgets.getAllWidgets();\n if (allWidgets.length === 0) return;\n\n const widgetMap = new Map(allWidgets.map(w => [w.name, w]));\n const macros = parseMacros(text);\n\n for (const macro of macros) {\n if (!macro.open) continue;\n // Check if macro is within the requested range\n if (macro.range.start.line < range.start.line || macro.range.start.line > range.end.line) continue;\n\n const widget = widgetMap.get(macro.name);\n if (!widget || widget.params.length === 0) continue;\n\n if (!macro.rawArgs || macro.rawArgs.trim() === '') continue;\n\n const args = lexArguments(macro.rawArgs);\n\n // Find the position of each arg in the original text line\n const lines = text.split('\\n');\n const macroLine = lines[macro.range.start.line];\n if (!macroLine) continue;\n\n const macroText = macroLine.substring(macro.range.start.character, macro.range.end.character);\n const nameEnd = macroText.indexOf(macro.name) + macro.name.length;\n const argsText = macroText.substring(nameEnd).replace(/^\\s+/, '').replace(/\\}$/, '');\n if (!argsText) continue;\n\n for (let i = 0; i < Math.min(args.length, widget.params.length); i++) {\n const argText = args[i].text;\n const idx = macroLine.indexOf(argText, macro.range.start.character + nameEnd);\n if (idx >= 0) {\n hints.push({\n position: { line: macro.range.start.line, character: idx },\n label: `@${widget.params[i]}:`,\n kind: 'parameter',\n });\n }\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Variable type hints in StoryVariables\n// ---------------------------------------------------------------------------\n\nfunction addVariableTypeHints(\n uri: string,\n text: string,\n range: Range,\n workspace: WorkspaceModel,\n hints: InlayHintItem[],\n): void {\n const storyVarsPassage = workspace.passages.getStoryVariables();\n if (!storyVarsPassage) return;\n if (storyVarsPassage.uri !== uri) return;\n\n const lines = text.split('\\n');\n const startLine = Math.max(range.start.line, 0);\n const endLine = Math.min(range.end.line, lines.length - 1);\n\n for (let lineNum = startLine; lineNum <= endLine; lineNum++) {\n const line = lines[lineNum];\n const declMatch = line.match(/^\\$([A-Za-z_$][\\w$]*)\\s*=\\s*(.+)$/);\n if (!declMatch) continue;\n\n const valueStr = declMatch[2].trim();\n const inferredType = inferType(valueStr);\n if (!inferredType) continue;\n\n const eqIdx = line.indexOf('=');\n hints.push({\n position: { line: lineNum, character: eqIdx },\n label: `: ${inferredType}`,\n kind: 'type',\n });\n }\n}\n\nfunction inferType(value: string): string | null {\n if (/^\\d+(\\.\\d+)?$/.test(value)) return 'number';\n if (/^\"[^\"]*\"$/.test(value) || /^'[^']*'$/.test(value)) return 'string';\n if (/^\\[/.test(value)) return 'array';\n if (/^\\{/.test(value)) return 'object';\n if (value === 'true' || value === 'false') return 'boolean';\n if (value === 'null') return 'null';\n if (value === 'undefined') return 'undefined';\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const inlayHintsPlugin: SpindlePlugin = {\n id: 'inlay-hints',\n capabilities: {\n inlayHintProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.languages.inlayHint.on((params) => {\n const range: Range = {\n start: { line: params.range.start.line, character: params.range.start.character },\n end: { line: params.range.end.line, character: params.range.end.character },\n };\n\n const hints = computeInlayHints(params.textDocument.uri, range, ctx.workspace);\n\n return hints.map(h => ({\n position: { line: h.position.line, character: h.position.character },\n label: h.label,\n kind: h.kind === 'type' ? 1 : 2,\n paddingRight: h.kind === 'parameter',\n paddingLeft: h.kind === 'type',\n }));\n });\n },\n};\n", "import type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros } from '../core/parsing/macro-parser.js';\n\n// ---------------------------------------------------------------------------\n// Token legend\n// ---------------------------------------------------------------------------\n\nexport const tokenTypesLegend: string[] = [\n 'function', 'variable', 'parameter', 'property', 'keyword',\n 'string', 'number', 'comment', 'namespace', 'type',\n 'macro', 'regexp',\n];\n\nexport const tokenModifiersLegend: string[] = [\n 'declaration', 'defaultLibrary', 'global', 'local', 'readonly',\n];\n\nconst tokenTypeIndex = new Map<string, number>(\n tokenTypesLegend.map((t, i) => [t, i]),\n);\nconst tokenModifierIndex = new Map<string, number>(\n tokenModifiersLegend.map((m, i) => [m, i]),\n);\n\nfunction encodeType(type: string): number {\n return tokenTypeIndex.get(type) ?? 0;\n}\n\nfunction encodeModifiers(modifiers: string[]): number {\n let bits = 0;\n for (const m of modifiers) {\n const idx = tokenModifierIndex.get(m);\n if (idx !== undefined) bits |= (1 << idx);\n }\n return bits;\n}\n\n// ---------------------------------------------------------------------------\n// Core semantic tokens function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/** A single absolute-positioned semantic token before delta-encoding. */\nexport interface AbsoluteToken {\n line: number;\n startChar: number;\n length: number;\n tokenType: number;\n tokenModifiers: number;\n}\n\n/**\n * Compute semantic tokens for a document.\n *\n * Tokens emitted:\n * - Macro names -> 'function' (with 'defaultLibrary' if known macro)\n * - Story variables ($var) -> 'variable' + 'global'\n * - Temp variables (_var) -> 'variable' + 'local'\n * - Local variables (@var) -> 'variable' + 'readonly'\n * - Sugar keywords -> 'keyword'\n * - Passage headers -> 'namespace'\n *\n * Returns absolute tokens (for testing). Use `encodeTokens` to delta-encode.\n */\nexport function computeSemanticTokensAbsolute(\n uri: string,\n workspace: WorkspaceModel,\n): AbsoluteToken[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const lines = text.split('\\n');\n const tokens: AbsoluteToken[] = [];\n\n // Find header lines for skipping during content scanning\n const headerLines = new Set<number>();\n const passages = workspace.passages.getPassagesInDocument(uri);\n for (const passage of passages) {\n const headerLine = passage.headerEnd.start.line;\n headerLines.add(headerLine);\n\n // Emit passage header tokens\n const rawLine = lines[headerLine] ?? '';\n // :: token\n tokens.push({\n line: headerLine,\n startChar: 0,\n length: 2,\n tokenType: encodeType('namespace'),\n tokenModifiers: 0,\n });\n\n // passage name\n const nameMatch = rawLine.match(/^::\\s*(\\S.*?)(?:\\s*\\[|\\s*\\{|\\s*$)/);\n if (nameMatch) {\n const name = nameMatch[1].trim();\n const nameStart = rawLine.indexOf(name);\n tokens.push({\n line: headerLine,\n startChar: nameStart,\n length: name.length,\n tokenType: encodeType('namespace'),\n tokenModifiers: encodeModifiers(['declaration']),\n });\n }\n }\n\n // Macro name tokens\n const macros = parseMacros(text);\n for (const macro of macros) {\n const macroLine = macro.range.start.line;\n const macroChar = macro.range.start.character;\n if (headerLines.has(macroLine)) continue;\n\n const isDefined = !!workspace.macros.getMacro(macro.name);\n\n let nameOffset = 1; // for '{'\n if (!macro.open) nameOffset += 1; // for '/'\n if (macro.cssPrefix) nameOffset += macro.cssPrefix.length + 1;\n\n tokens.push({\n line: macroLine,\n startChar: macroChar + nameOffset,\n length: macro.name.length,\n tokenType: encodeType('function'),\n tokenModifiers: encodeModifiers(isDefined ? ['defaultLibrary'] : []),\n });\n }\n\n // Variable and keyword tokens\n const storyVarRegex = /(?<!\\w)\\$([A-Za-z_$][\\w$]*(?:\\.[A-Za-z_$][\\w$]*)*)/g;\n const tempVarRegex = /(?<!\\w)_([A-Za-z_$][\\w$]*)/g;\n const localVarRegex = /(?<!\\w)@([A-Za-z_$][\\w$]*)/g;\n const sugarKeywordRegex = /\\b(to|is|isnot|eq|neq|gt|gte|lt|lte|and|or|not|def|ndef)\\b/g;\n\n for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {\n if (headerLines.has(lineIndex)) continue;\n const line = lines[lineIndex];\n\n // Story vars ($var)\n storyVarRegex.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = storyVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['global']),\n });\n }\n\n // Temp vars (_var)\n tempVarRegex.lastIndex = 0;\n while ((m = tempVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['local']),\n });\n }\n\n // Local vars (@var)\n localVarRegex.lastIndex = 0;\n while ((m = localVarRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('variable'),\n tokenModifiers: encodeModifiers(['readonly']),\n });\n }\n\n // Sugar keywords\n sugarKeywordRegex.lastIndex = 0;\n while ((m = sugarKeywordRegex.exec(line)) !== null) {\n tokens.push({\n line: lineIndex,\n startChar: m.index,\n length: m[0].length,\n tokenType: encodeType('keyword'),\n tokenModifiers: 0,\n });\n }\n }\n\n // Sort by line, then by start character\n tokens.sort((a, b) => a.line - b.line || a.startChar - b.startChar);\n\n return tokens;\n}\n\n/**\n * Delta-encode absolute tokens into the LSP wire format.\n *\n * Each token becomes 5 integers: deltaLine, deltaStartChar, length, tokenType, tokenModifiers.\n */\nexport function encodeTokens(absoluteTokens: AbsoluteToken[]): number[] {\n const data: number[] = [];\n let prevLine = 0;\n let prevChar = 0;\n\n for (const token of absoluteTokens) {\n const deltaLine = token.line - prevLine;\n const deltaStart = deltaLine === 0 ? token.startChar - prevChar : token.startChar;\n\n data.push(deltaLine, deltaStart, token.length, token.tokenType, token.tokenModifiers);\n\n prevLine = token.line;\n prevChar = token.startChar;\n }\n\n return data;\n}\n\n/**\n * Compute delta-encoded semantic tokens for a document.\n */\nexport function computeSemanticTokens(uri: string, workspace: WorkspaceModel): number[] {\n const absoluteTokens = computeSemanticTokensAbsolute(uri, workspace);\n return encodeTokens(absoluteTokens);\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const semanticTokensPlugin: SpindlePlugin = {\n id: 'semantic-tokens',\n capabilities: {\n semanticTokensProvider: {\n full: true,\n legend: {\n tokenTypes: tokenTypesLegend,\n tokenModifiers: tokenModifiersLegend,\n },\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.languages.semanticTokens.on((params) => {\n const data = computeSemanticTokens(params.textDocument.uri, ctx.workspace);\n return { data };\n });\n },\n};\n", "import type { Diagnostic, Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { DiagnosticCode } from '../core/diagnostic-codes.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\nexport interface CodeAction {\n title: string;\n kind: string;\n diagnosticCodes: string[];\n edits: Array<{ uri: string; range: Range; newText: string }>;\n}\n\n// ---------------------------------------------------------------------------\n// Core code actions function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute quick-fix code actions for the given diagnostics.\n *\n * Supported fixes:\n * - SP100 (undefined macro) -> \"Add 'macroName' to spindle.config.yaml\"\n * - SP200 (undeclared variable) -> \"Declare '$varName' in StoryVariables\"\n * - SP202 (no StoryVariables) -> \"Create StoryVariables passage\"\n */\nexport function computeCodeActions(\n uri: string,\n diagnostics: Diagnostic[],\n workspace: WorkspaceModel,\n): CodeAction[] {\n const actions: CodeAction[] = [];\n\n for (const diag of diagnostics) {\n switch (diag.code) {\n case DiagnosticCode.UndefinedMacro: {\n const action = fixUndefinedMacro(diag);\n if (action) actions.push(action);\n break;\n }\n case DiagnosticCode.UndeclaredVariable: {\n const action = fixUndeclaredVariable(diag, workspace);\n if (action) actions.push(action);\n break;\n }\n case DiagnosticCode.NoStoryVariables: {\n const action = fixNoStoryVariables(uri, workspace);\n if (action) actions.push(action);\n break;\n }\n // No quick fix for other diagnostic codes\n }\n }\n\n return actions;\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP100 \u2014 Add macro to spindle.config.yaml\n// ---------------------------------------------------------------------------\n\nfunction fixUndefinedMacro(diag: Diagnostic): CodeAction | null {\n // Extract macro name from message: \"Unrecognized macro: {macroName}\"\n const match = diag.message.match(/\\{(\\w[\\w-]*)\\}/);\n if (!match) return null;\n\n const macroName = match[1];\n const configUri = 'file:///spindle.config.yaml';\n\n // Generate YAML snippet to append\n const yamlSnippet = `\\n ${macroName}:\\n description: \"\"\\n`;\n\n return {\n title: `Add '${macroName}' to spindle.config.yaml`,\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.UndefinedMacro],\n edits: [{\n uri: configUri,\n range: {\n start: { line: Number.MAX_SAFE_INTEGER, character: 0 },\n end: { line: Number.MAX_SAFE_INTEGER, character: 0 },\n },\n newText: yamlSnippet,\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP200 \u2014 Declare variable in StoryVariables\n// ---------------------------------------------------------------------------\n\nfunction fixUndeclaredVariable(\n diag: Diagnostic,\n workspace: WorkspaceModel,\n): CodeAction | null {\n // Extract variable name from message: \"Variable '$varName' is not declared in StoryVariables\"\n const match = diag.message.match(/'\\$(\\w+)'/);\n if (!match) return null;\n\n const varName = match[1];\n\n const storyVars = workspace.passages.getStoryVariables();\n if (!storyVars) return null;\n\n const storyVarsUri = storyVars.uri;\n const text = workspace.documents.getText(storyVarsUri);\n if (text === undefined) return null;\n\n // Find the end of the StoryVariables passage content\n const lines = text.split('\\n');\n const contentStart = storyVars.headerEnd.end.line + 1;\n let contentEnd = lines.length;\n for (let i = contentStart; i < lines.length; i++) {\n if (/^::\\s+/.test(lines[i])) {\n contentEnd = i;\n break;\n }\n }\n\n // Insert at the end of StoryVariables content\n const insertLine = contentEnd;\n\n return {\n title: `Declare '$${varName}' in StoryVariables`,\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.UndeclaredVariable],\n edits: [{\n uri: storyVarsUri,\n range: {\n start: { line: insertLine, character: 0 },\n end: { line: insertLine, character: 0 },\n },\n newText: `$${varName} = null\\n`,\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Quick fix: SP202 \u2014 Create StoryVariables passage\n// ---------------------------------------------------------------------------\n\nfunction fixNoStoryVariables(\n uri: string,\n workspace: WorkspaceModel,\n): CodeAction | null {\n // Find the first document in the workspace to append the passage\n const uris = workspace.documents.getUris();\n const targetUri = uris.length > 0 ? uris[0] : uri;\n\n const text = workspace.documents.getText(targetUri);\n if (text === undefined) return null;\n\n const lines = text.split('\\n');\n const lastLine = lines.length;\n\n return {\n title: 'Create StoryVariables passage',\n kind: 'quickfix',\n diagnosticCodes: [DiagnosticCode.NoStoryVariables],\n edits: [{\n uri: targetUri,\n range: {\n start: { line: lastLine, character: 0 },\n end: { line: lastLine, character: 0 },\n },\n newText: '\\n:: StoryVariables\\n',\n }],\n };\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const codeActionsPlugin: SpindlePlugin = {\n id: 'code-actions',\n capabilities: {\n codeActionProvider: {\n codeActionKinds: ['quickfix'],\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onCodeAction((params) => {\n // Convert LSP diagnostics back to our Diagnostic type\n const diagnostics: Diagnostic[] = params.context.diagnostics\n .filter(d => d.source === 'spindle')\n .map(d => ({\n range: {\n start: { line: d.range.start.line, character: d.range.start.character },\n end: { line: d.range.end.line, character: d.range.end.character },\n },\n message: d.message,\n severity: d.severity === 1 ? 'error' as const\n : d.severity === 2 ? 'warning' as const\n : d.severity === 3 ? 'info' as const\n : 'hint' as const,\n code: String(d.code ?? ''),\n source: d.source ?? 'spindle',\n }));\n\n const actions = computeCodeActions(\n params.textDocument.uri,\n diagnostics,\n ctx.workspace,\n );\n\n return actions.map(a => ({\n title: a.title,\n kind: a.kind,\n diagnostics: params.context.diagnostics.filter(d =>\n a.diagnosticCodes.includes(String(d.code)),\n ),\n edit: {\n changes: Object.fromEntries(\n a.edits.map(e => [\n e.uri,\n [{ range: toLspRange(e.range), newText: e.newText }],\n ]),\n ),\n },\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { SymbolKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core document symbol function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DocSymbol {\n name: string;\n kind: SymbolKind;\n range: Range;\n selectionRange: Range;\n children?: DocSymbol[];\n}\n\n/**\n * Compute document symbols for the outline view and breadcrumbs.\n *\n * Returns:\n * - Passages as Namespace symbols (full passage range)\n * - Widget definitions inside [widget] passages as nested Function symbols\n * - Variable declarations in StoryVariables as nested Variable symbols\n */\nexport function computeDocumentSymbols(uri: string, workspace: WorkspaceModel): DocSymbol[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const storyVarsPassage = workspace.passages.getStoryVariables();\n const lines = text.split('\\n');\n const symbols: DocSymbol[] = [];\n\n for (const passage of passages) {\n const headerLine = passage.range.start.line;\n const selectionRange: Range = {\n start: { line: headerLine, character: 0 },\n end: { line: headerLine, character: lines[headerLine]?.length ?? 0 },\n };\n\n const passageSymbol: DocSymbol = {\n name: passage.name,\n kind: SymbolKind.Namespace,\n range: passage.range,\n selectionRange,\n children: [],\n };\n\n // Widget definitions inside [widget] passages\n if (passage.tags?.includes('widget')) {\n const contentStart = passage.range.start.line + 1;\n const contentEnd = passage.range.end.line + 1;\n const widgetDefRegex = /\\{widget\\s+\"([^\"]+)\"[^}]*\\}/gi;\n\n for (let i = contentStart; i < contentEnd && i < lines.length; i++) {\n widgetDefRegex.lastIndex = 0;\n let match: RegExpExecArray | null;\n while ((match = widgetDefRegex.exec(lines[i])) !== null) {\n const charStart = match.index;\n const charEnd = charStart + match[0].length;\n passageSymbol.children!.push({\n name: match[1],\n kind: SymbolKind.Function,\n range: {\n start: { line: i, character: charStart },\n end: { line: i, character: charEnd },\n },\n selectionRange: {\n start: { line: i, character: charStart },\n end: { line: i, character: charEnd },\n },\n });\n }\n }\n }\n\n // Variable declarations in StoryVariables\n if (storyVarsPassage && storyVarsPassage.uri === uri && passage.name === 'StoryVariables') {\n const contentStart = passage.range.start.line + 1;\n const contentEnd = passage.range.end.line + 1;\n\n for (let i = contentStart; i < contentEnd && i < lines.length; i++) {\n const varMatch = lines[i].match(/^\\$([A-Za-z_$][\\w$]*)\\s*=/);\n if (varMatch) {\n const charEnd = varMatch[0].length;\n passageSymbol.children!.push({\n name: '$' + varMatch[1],\n kind: SymbolKind.Variable,\n range: {\n start: { line: i, character: 0 },\n end: { line: i, character: lines[i].length },\n },\n selectionRange: {\n start: { line: i, character: 0 },\n end: { line: i, character: charEnd },\n },\n });\n }\n }\n }\n\n symbols.push(passageSymbol);\n }\n\n return symbols;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nfunction toLspDocumentSymbol(sym: DocSymbol): import('vscode-languageserver').DocumentSymbol {\n return {\n name: sym.name,\n kind: sym.kind,\n range: toLspRange(sym.range),\n selectionRange: toLspRange(sym.selectionRange),\n children: sym.children?.map(toLspDocumentSymbol),\n };\n}\n\nexport const documentSymbolPlugin: SpindlePlugin = {\n id: 'document-symbol',\n capabilities: {\n documentSymbolProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentSymbol((params) => {\n const symbols = computeDocumentSymbols(params.textDocument.uri, ctx.workspace);\n return symbols.map(toLspDocumentSymbol);\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { SymbolKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core workspace symbol function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface WorkspaceSymbolItem {\n name: string;\n kind: SymbolKind;\n uri: string;\n range: Range;\n}\n\n/**\n * Search for symbols across the entire workspace.\n *\n * Returns:\n * - All passages as Namespace symbols\n * - All widgets as Function symbols\n * - All declared variables as Variable symbols\n *\n * Results are filtered by the query string (case-insensitive substring match).\n */\nexport function searchWorkspaceSymbols(query: string, workspace: WorkspaceModel): WorkspaceSymbolItem[] {\n const lowerQuery = query.toLowerCase();\n const results: WorkspaceSymbolItem[] = [];\n\n // Passages\n for (const passage of workspace.passages.getAllPassages()) {\n if (lowerQuery && !passage.name.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: passage.name,\n kind: SymbolKind.Namespace,\n uri: passage.uri,\n range: passage.range,\n });\n }\n\n // Widgets\n for (const widget of workspace.widgets.getAllWidgets()) {\n if (lowerQuery && !widget.name.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: widget.name,\n kind: SymbolKind.Function,\n uri: widget.uri,\n range: widget.range,\n });\n }\n\n // Declared variables\n for (const [name, decl] of workspace.variables.getDeclared()) {\n const displayName = '$' + name;\n if (lowerQuery && !displayName.toLowerCase().includes(lowerQuery)) continue;\n results.push({\n name: displayName,\n kind: SymbolKind.Variable,\n uri: decl.declarationUri ?? '',\n range: decl.declarationRange ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } },\n });\n }\n\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const workspaceSymbolPlugin: SpindlePlugin = {\n id: 'workspace-symbol',\n capabilities: {\n workspaceSymbolProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onWorkspaceSymbol((params) => {\n const symbols = searchWorkspaceSymbols(params.query, ctx.workspace);\n return symbols.map(s => ({\n name: s.name,\n kind: s.kind,\n location: {\n uri: s.uri,\n range: toLspRange(s.range),\n },\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseMacros, pairMacros } from '../core/parsing/macro-parser.js';\nimport { FoldingRangeKind } from 'vscode-languageserver';\n\n// ---------------------------------------------------------------------------\n// Core folding range function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface FoldingRangeItem {\n startLine: number;\n endLine: number;\n kind?: string;\n}\n\n/**\n * Compute folding ranges for a document.\n *\n * Returns foldable regions for:\n * - Passages: each passage header to the end of the passage (FoldingRangeKind.Region)\n * - Block macros: matched {if}...{/if}, {for}...{/for}, etc.\n */\nexport function computeFoldingRanges(uri: string, workspace: WorkspaceModel): FoldingRangeItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const ranges: FoldingRangeItem[] = [];\n\n // Passage folding ranges\n const passages = workspace.passages.getPassagesInDocument(uri);\n for (const passage of passages) {\n const startLine = passage.range.start.line;\n const endLine = passage.range.end.line;\n if (endLine > startLine) {\n ranges.push({\n startLine,\n endLine,\n kind: 'region',\n });\n }\n }\n\n // Block macro folding ranges\n const macros = parseMacros(text);\n pairMacros(macros, (name) => workspace.macros.isBlock(name));\n\n for (const macro of macros) {\n if (macro.open && macro.pair !== -1) {\n const closingMacro = macros[macro.pair];\n const startLine = macro.range.start.line;\n const endLine = closingMacro.range.start.line;\n if (endLine > startLine) {\n ranges.push({\n startLine,\n endLine,\n });\n }\n }\n }\n\n return ranges;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nexport const foldingRangePlugin: SpindlePlugin = {\n id: 'folding-range',\n capabilities: {\n foldingRangeProvider: true,\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onFoldingRanges((params) => {\n const ranges = computeFoldingRanges(params.textDocument.uri, ctx.workspace);\n return ranges.map(r => ({\n startLine: r.startLine,\n endLine: r.endLine,\n kind: r.kind === 'region' ? FoldingRangeKind.Region : undefined,\n }));\n });\n },\n};\n", "import type { Range } from '../core/types.js';\nimport type { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport type { SpindlePlugin, PluginContext } from '../core/plugin/plugin-api.js';\nimport { parseLinks } from '../core/parsing/link-parser.js';\n\n// ---------------------------------------------------------------------------\n// Core document link function (no LSP dependency)\n// ---------------------------------------------------------------------------\n\nexport interface DocumentLinkItem {\n range: Range;\n target: string | undefined;\n}\n\n/**\n * Compute document links for [[passage]] references.\n *\n * For each [[Target]] or [[Display|Target]] link:\n * - Returns a DocumentLink with the range covering the full link syntax\n * - Sets `target` to the URI of the file containing the target passage,\n * with a fragment pointing to the line number\n *\n * Links to unknown passages get `target: undefined`.\n */\nexport function computeDocumentLinks(uri: string, workspace: WorkspaceModel): DocumentLinkItem[] {\n const text = workspace.documents.getText(uri);\n if (text === undefined) return [];\n\n const passages = workspace.passages.getPassagesInDocument(uri);\n if (passages.length === 0) return [];\n\n const links: DocumentLinkItem[] = [];\n\n // Parse links from each passage's content\n for (const passage of passages) {\n const contentStartLine = passage.range.start.line + 1;\n const contentEndLine = passage.range.end.line + 1;\n const lines = text.split('\\n');\n const contentLines = lines.slice(contentStartLine, contentEndLine);\n const content = contentLines.join('\\n');\n\n const passageLinks = parseLinks(content, contentStartLine);\n\n for (const ref of passageLinks) {\n const targetPassage = workspace.passages.getPassage(ref.name);\n let target: string | undefined;\n if (targetPassage) {\n target = `${targetPassage.uri}#L${targetPassage.range.start.line + 1}`;\n }\n\n links.push({\n range: ref.range,\n target,\n });\n }\n }\n\n return links;\n}\n\n// ---------------------------------------------------------------------------\n// Plugin wrapper (LSP integration)\n// ---------------------------------------------------------------------------\n\nfunction toLspRange(r: Range): import('vscode-languageserver').Range {\n return {\n start: { line: r.start.line, character: r.start.character },\n end: { line: r.end.line, character: r.end.character },\n };\n}\n\nexport const documentLinkPlugin: SpindlePlugin = {\n id: 'document-link',\n capabilities: {\n documentLinkProvider: {\n resolveProvider: false,\n },\n },\n initialize(ctx: PluginContext) {\n ctx.connection.onDocumentLinks((params) => {\n const links = computeDocumentLinks(params.textDocument.uri, ctx.workspace);\n return links.map(l => ({\n range: toLspRange(l.range),\n target: l.target,\n }));\n });\n },\n};\n", "import type { SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { diagnosticsPlugin } from './diagnostics.js';\nimport { completionsPlugin } from './completions.js';\nimport { hoverPlugin } from './hover.js';\nimport { signaturePlugin } from './signature.js';\nimport { definitionPlugin } from './definition.js';\nimport { referencesPlugin } from './references.js';\nimport { renamePlugin } from './rename.js';\nimport { codeLensPlugin } from './code-lens.js';\nimport { inlayHintsPlugin } from './inlay-hints.js';\nimport { semanticTokensPlugin } from './semantic-tokens.js';\nimport { codeActionsPlugin } from './code-actions.js';\nimport { formatPlugin } from './format.js';\nimport { documentSymbolPlugin } from './document-symbol.js';\nimport { workspaceSymbolPlugin } from './workspace-symbol.js';\nimport { foldingRangePlugin } from './folding-range.js';\nimport { documentLinkPlugin } from './document-link.js';\n\n/**\n * Registry of all feature plugins.\n */\nexport const allPlugins: SpindlePlugin[] = [\n diagnosticsPlugin,\n completionsPlugin,\n hoverPlugin,\n signaturePlugin,\n definitionPlugin,\n referencesPlugin,\n renamePlugin,\n codeLensPlugin,\n inlayHintsPlugin,\n semanticTokensPlugin,\n codeActionsPlugin,\n formatPlugin,\n documentSymbolPlugin,\n workspaceSymbolPlugin,\n foldingRangePlugin,\n documentLinkPlugin,\n];\n", "import {\n createConnection,\n ProposedFeatures,\n DidChangeWatchedFilesNotification,\n FileChangeType,\n} from 'vscode-languageserver/node.js';\nimport { TextDocument } from 'vscode-languageserver-textdocument';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { readFileSync } from 'node:fs';\nimport { glob } from 'glob';\n\nimport { WorkspaceModel } from '../core/workspace/workspace-model.js';\nimport { loadPlugins } from '../core/plugin/plugin-loader.js';\nimport { buildCapabilities } from './capabilities.js';\nimport { allPlugins } from '../plugins/index.js';\nimport type { SpindleConfig, SpindlePlugin } from '../core/plugin/plugin-api.js';\nimport { loadConfigFromDisk } from '../core/workspace/config-loader.js';\n\n/**\n * Convert a file:// URI to a filesystem path.\n * Returns the original string if it is not a file URI.\n */\nfunction uriToFsPath(uri: string): string {\n try {\n return fileURLToPath(uri);\n } catch {\n return uri;\n }\n}\n\n/**\n * Convert a filesystem path to a file:// URI string.\n */\nfunction fsPathToUri(fsPath: string): string {\n return pathToFileURL(fsPath).toString();\n}\n\n/**\n * Start the Spindle LSP server.\n *\n * Supports `--stdio` (default) and `--socket=<port>` transport modes.\n */\nexport function startServer(_args: string[]): void {\n const connection = createConnection(ProposedFeatures.all);\n const documents = new Map<string, TextDocument>();\n let workspace: WorkspaceModel;\n let activePlugins: SpindlePlugin[] = [];\n let workspaceRoot: string | undefined;\n\n connection.onInitialize((params) => {\n const initOptions = (params.initializationOptions ?? {}) as Partial<SpindleConfig>;\n\n // Determine workspace root from LSP params\n workspaceRoot =\n initOptions.workspaceRoot ??\n (params.workspaceFolders?.[0]?.uri\n ? uriToFsPath(params.workspaceFolders[0].uri)\n : undefined);\n\n // Load project config from disk if we have a workspace root\n const projectConfig = workspaceRoot\n ? loadConfigFromDisk(workspaceRoot)\n : { macros: {} };\n\n const config: SpindleConfig = {\n disabledPlugins: initOptions.disabledPlugins,\n diagnostics: initOptions.diagnostics,\n workspaceRoot,\n };\n\n // Create workspace model\n workspace = new WorkspaceModel();\n\n // Load and filter plugins\n activePlugins = loadPlugins(allPlugins, config);\n\n // Initialize each plugin with context\n for (const plugin of activePlugins) {\n plugin.initialize({ connection, workspace, config });\n }\n\n // Load user-defined macros from project config\n if (Object.keys(projectConfig.macros).length > 0) {\n workspace.macros.loadSupplements(projectConfig.macros);\n }\n\n return {\n capabilities: buildCapabilities(activePlugins),\n };\n });\n\n connection.onInitialized(async () => {\n // Register for file watching\n connection.client.register(DidChangeWatchedFilesNotification.type, {\n watchers: [\n { globPattern: '**/*.tw' },\n { globPattern: '**/*.twee' },\n { globPattern: '**/*.js' },\n { globPattern: '**/*.ts' },\n { globPattern: '**/spindle.config.*' },\n { globPattern: '**/*twee-config.*' },\n ],\n });\n\n // Initial workspace scan\n if (workspace) {\n const fileContents = await scanWorkspaceFiles(workspaceRoot);\n workspace.initialize(fileContents);\n }\n });\n\n // --- Document synchronization ---\n\n connection.onDidOpenTextDocument(({ textDocument }) => {\n const doc = TextDocument.create(\n textDocument.uri,\n textDocument.languageId,\n textDocument.version,\n textDocument.text,\n );\n documents.set(textDocument.uri, doc);\n if (workspace) {\n workspace.documents.open(textDocument.uri, textDocument.text);\n }\n });\n\n connection.onDidChangeTextDocument(({ textDocument, contentChanges }) => {\n const existing = documents.get(textDocument.uri);\n if (existing) {\n const updated = TextDocument.update(\n existing,\n contentChanges,\n textDocument.version,\n );\n documents.set(textDocument.uri, updated);\n if (workspace) {\n workspace.documents.update(textDocument.uri, updated.getText());\n }\n }\n });\n\n connection.onDidCloseTextDocument(({ textDocument }) => {\n documents.delete(textDocument.uri);\n if (workspace) {\n workspace.documents.close(textDocument.uri);\n }\n });\n\n // --- File watcher events ---\n\n connection.onDidChangeWatchedFiles(({ changes }) => {\n if (!workspace) return;\n\n for (const change of changes) {\n if (change.type === FileChangeType.Deleted) {\n workspace.documents.close(change.uri);\n documents.delete(change.uri);\n } else {\n // Created or Changed \u2014 re-read from disk\n try {\n const fsPath = uriToFsPath(change.uri);\n const text = readFileSync(fsPath, 'utf-8');\n if (workspace.documents.has(change.uri)) {\n workspace.documents.update(change.uri, text);\n } else {\n workspace.documents.open(change.uri, text);\n }\n } catch {\n // File may have been deleted between event and read\n }\n }\n }\n });\n\n // --- Lifecycle ---\n\n connection.onShutdown(() => {\n for (const plugin of activePlugins) {\n plugin.dispose?.();\n }\n workspace?.dispose();\n });\n\n connection.listen();\n}\n\n/**\n * Scan workspace for .tw and .twee files and return their contents.\n */\nasync function scanWorkspaceFiles(\n root: string | undefined,\n): Promise<Map<string, string>> {\n const contents = new Map<string, string>();\n if (!root) return contents;\n\n try {\n const files = await glob('**/*.{tw,twee}', {\n cwd: root,\n absolute: true,\n nodir: true,\n });\n for (const filePath of files) {\n try {\n const text = readFileSync(filePath, 'utf-8');\n const uri = fsPathToUri(filePath);\n contents.set(uri, text);\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Glob failure \u2014 return empty\n }\n\n return contents;\n}\n", "export {};\n\nconst args = process.argv.slice(2);\n\nif (args[0] === 'check') {\n const { runCheck } = await import('./cli/check.js');\n const exitCode = await runCheck(args.slice(1));\n process.exit(exitCode);\n} else if (args[0] === 'format') {\n const { runFormat } = await import('./cli/format.js');\n const exitCode = await runFormat(args.slice(1));\n process.exit(exitCode);\n} else {\n // Default: start LSP server\n const { startServer } = await import('./server/server.js');\n startServer(args);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["readFileSync", "match", "EventEmitter", "args", "args", "TypeError", "buildLineStarts", "offsetToPosition", "args", "undeclared", "severityMap", "readFileSync", "existsSync", "join", "fileURLToPath", "readFileSync", "pathToFileURL", "args", "readFileSync", "glob", "parseArgs", "args", "init_format", "allPlugins", "macroRegex", "toLspRange", "passageHeaderRegex", "toLspRange", "passageHeaderRegex", "widgetDefRegex", "toLspRange", "toLspRange", "args", "toLspRange", "widgetDefRegex", "toLspRange", "SymbolKind", "toLspRange", "toLspRange", "fileURLToPath", "pathToFileURL", "readFileSync", "glob", "runCheck", "runFormat", "startServer"]
|
|
7
7
|
}
|