@reticular/speakable 1.0.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/README.md +31 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +2862 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +348 -0
- package/dist/index.js +512 -0
- package/dist/index.js.map +1 -0
- package/package.json +42 -0
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/cli/options.ts","../src/cli/io.ts","../src/parser/html-parser.ts","../src/extractor/aria-name.ts","../src/model/types.ts","../src/extractor/role-mapper.ts","../src/extractor/state-extractor.ts","../src/extractor/focus-extractor.ts","../src/extractor/tree-builder.ts","../src/model/validation.ts","../src/model/serialization.ts","../src/cli/colors.ts","../src/renderer/nvda-renderer.ts","../src/renderer/jaws-renderer.ts","../src/renderer/voiceover-renderer.ts","../src/renderer/audit-renderer.ts","../src/diff/diff-algorithm.ts","../src/diff/formatter.ts","../src/cli/orchestrator.ts"],"sourcesContent":["/**\n * Speakable CLI entry point.\n * \n * Command-line interface for analyzing HTML accessibility announcements.\n */\n\nimport { Command } from 'commander';\nimport { readFileSync } from 'fs';\nimport { fileURLToPath } from 'url';\nimport { dirname, join } from 'path';\nimport { \n validateOptions, \n parseInput, \n validateInput, \n validateDiffMode,\n validateBatchMode\n} from './cli/options.js';\nimport { readHTML, writeOutput, FileIOError } from './cli/io.js';\nimport { processHTML, processBatch, formatWarnings } from './cli/orchestrator.js';\nimport { isColorEnabled } from './cli/colors.js';\n\n// Get package.json for version\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\nconst packageJson = JSON.parse(\n readFileSync(join(__dirname, '../package.json'), 'utf-8')\n);\n\nconst program = new Command();\n\nprogram\n .name('speakable')\n .description('Analyze HTML accessibility announcements and generate screen reader output')\n .version(packageJson.version, '-v, --version', 'Output the current version')\n .helpOption('-h, --help', 'Display help for command');\n\n// Main command with input argument\nprogram\n .argument('[input...]', 'HTML file path(s) or \"-\" for stdin')\n .option('-o, --output <path>', 'Output file path (default: stdout)')\n .option(\n '-f, --format <format>',\n 'Output format: json, text, audit, or both (default: json)',\n 'json'\n )\n .option(\n '-s, --screen-reader <reader>',\n 'Screen reader: nvda, jaws, voiceover, or all (default: nvda)',\n 'nvda'\n )\n .option(\n '--selector <selector>',\n 'CSS selector to filter elements'\n )\n .option(\n '--validate',\n 'Validate round-trip serialization'\n )\n .option(\n '--diff <file>',\n 'Compare with another HTML file (semantic diff mode)'\n )\n .option(\n '--batch',\n 'Process multiple files in batch mode'\n )\n .action(async (input, rawOptions) => {\n try {\n // Parse and validate options\n const options = validateOptions(rawOptions);\n const parsedInput = parseInput(input);\n \n // Validate input\n validateInput(parsedInput);\n \n // Validate diff mode\n validateDiffMode(options, parsedInput);\n \n // Validate batch mode\n validateBatchMode(options, parsedInput);\n \n // Handle batch mode\n if (options.batch && parsedInput.inputs && parsedInput.inputs.length > 0) {\n const result = processBatch(parsedInput.inputs, options);\n \n // Write output\n writeOutput(result.output, options.output);\n \n // Display warnings to stderr\n if (result.warnings.length > 0) {\n console.error(formatWarnings(result.warnings, isColorEnabled(process.stderr)));\n }\n \n // Exit with appropriate code\n process.exit(result.exitCode);\n return;\n }\n \n // Read HTML input\n const htmlResult = readHTML(parsedInput.input, parsedInput.isStdin);\n const html = await Promise.resolve(htmlResult);\n \n // Read diff HTML if in diff mode\n let diffHTML: string | undefined;\n if (options.diff) {\n diffHTML = readHTML(options.diff, false) as string;\n }\n \n // Process HTML\n const result = processHTML(html, options, diffHTML);\n \n // Write output\n writeOutput(result.output, options.output);\n \n // Display warnings to stderr\n if (result.warnings.length > 0) {\n console.error(formatWarnings(result.warnings, isColorEnabled(process.stderr)));\n }\n \n // Exit with appropriate code\n process.exit(result.exitCode);\n } catch (error) {\n if (error instanceof FileIOError) {\n console.error(`Error: ${error.message}`);\n process.exit(3); // System error\n }\n \n if (error instanceof Error) {\n console.error(`Error: ${error.message}`);\n process.exit(1); // User error\n }\n \n throw error;\n }\n });\n\n// Add usage examples to help\nprogram.addHelpText('after', `\n\nExamples:\n $ speakable input.html\n $ speakable input.html -f text -s nvda\n $ speakable input.html -f both -s all\n $ speakable input.html --selector \"button\"\n $ speakable input.html --diff old.html\n $ speakable --batch file1.html file2.html file3.html\n $ cat input.html | speakable -\n $ speakable input.html -o output.json\n $ speakable input.html -f audit\n\nScreen Readers:\n nvda - NVDA (Windows)\n jaws - JAWS (Windows)\n voiceover - VoiceOver (macOS)\n all - All screen readers\n\nOutput Formats:\n json - Semantic model as JSON\n text - Screen reader announcement text\n audit - Developer-friendly audit report\n both - Both JSON and text\n\nNotes:\n - Screen reader output is heuristic and may differ from actual behavior\n - Use --validate to check serialization round-trip integrity\n - Use --diff to detect accessibility changes between versions\n - Use --batch to process multiple files (continues on individual errors)\n`);\n\nprogram.parse();\n\n","/**\n * CLI option types and validation.\n */\n\nexport type OutputFormat = 'json' | 'text' | 'audit' | 'both';\nexport type ScreenReader = 'nvda' | 'jaws' | 'voiceover' | 'all';\n\nexport interface CLIOptions {\n /** Output file path (undefined = stdout) */\n output?: string;\n \n /** Output format */\n format: OutputFormat;\n \n /** Screen reader to simulate */\n screenReader: ScreenReader;\n \n /** CSS selector to filter elements */\n selector?: string;\n \n /** Enable round-trip validation */\n validate: boolean;\n \n /** Second HTML file for diff mode */\n diff?: string;\n \n /** Enable batch processing mode */\n batch: boolean;\n}\n\nexport interface ParsedInput {\n /** Input source: file path, stdin, or undefined */\n input?: string;\n \n /** Whether input is from stdin */\n isStdin: boolean;\n \n /** Multiple input files for batch mode */\n inputs?: string[];\n}\n\n/**\n * Validates and normalizes CLI options.\n * \n * @param rawOptions - Raw options from Commander\n * @returns Validated options\n * @throws Error if options are invalid\n */\nexport function validateOptions(rawOptions: any): CLIOptions {\n const format = rawOptions.format as string;\n const screenReader = rawOptions.screenReader as string;\n \n // Validate format\n const validFormats: OutputFormat[] = ['json', 'text', 'audit', 'both'];\n if (!validFormats.includes(format as OutputFormat)) {\n throw new Error(\n `Invalid format: ${format}. Must be one of: ${validFormats.join(', ')}`\n );\n }\n \n // Validate screen reader\n const validReaders: ScreenReader[] = ['nvda', 'jaws', 'voiceover', 'all'];\n if (!validReaders.includes(screenReader as ScreenReader)) {\n throw new Error(\n `Invalid screen reader: ${screenReader}. Must be one of: ${validReaders.join(', ')}`\n );\n }\n \n return {\n output: rawOptions.output,\n format: format as OutputFormat,\n screenReader: screenReader as ScreenReader,\n selector: rawOptions.selector,\n validate: rawOptions.validate || false,\n diff: rawOptions.diff,\n batch: rawOptions.batch || false,\n };\n}\n\n/**\n * Parses and validates input argument(s).\n * \n * @param input - Input argument from Commander (can be array in batch mode)\n * @returns Parsed input information\n */\nexport function parseInput(input?: string | string[]): ParsedInput {\n // Handle array input (from Commander variadic argument)\n if (Array.isArray(input)) {\n if (input.length === 0) {\n return {\n input: undefined,\n isStdin: false,\n inputs: [],\n };\n }\n \n // Check if any input is stdin\n if (input.includes('-')) {\n if (input.length === 1) {\n return { input: undefined, isStdin: true };\n }\n throw new Error('Batch mode cannot be used with stdin input');\n }\n \n // Single file — treat as normal single input\n if (input.length === 1) {\n return {\n input: input[0],\n isStdin: false,\n };\n }\n \n return {\n input: undefined,\n isStdin: false,\n inputs: input,\n };\n }\n \n // Handle single input\n if (!input) {\n return {\n input: undefined,\n isStdin: false,\n };\n }\n \n if (input === '-') {\n return {\n input: undefined,\n isStdin: true,\n };\n }\n \n return {\n input,\n isStdin: false,\n };\n}\n\n/**\n * Validates that required input is provided.\n * \n * @param parsedInput - Parsed input information\n * @throws Error if no input is provided\n */\nexport function validateInput(parsedInput: ParsedInput): void {\n const hasInputs = parsedInput.inputs && parsedInput.inputs.length > 0;\n \n if (!parsedInput.input && !parsedInput.isStdin && !hasInputs) {\n throw new Error(\n 'No input provided. Specify an HTML file path or use \"-\" for stdin.'\n );\n }\n}\n\n/**\n * Validates diff mode requirements.\n * \n * @param options - CLI options\n * @param parsedInput - Parsed input information\n * @throws Error if diff mode is invalid\n */\nexport function validateDiffMode(\n options: CLIOptions,\n parsedInput: ParsedInput\n): void {\n if (options.diff) {\n if (parsedInput.isStdin) {\n throw new Error('Diff mode cannot be used with stdin input');\n }\n \n if (!parsedInput.input) {\n throw new Error('Diff mode requires an input file');\n }\n \n if (parsedInput.inputs && parsedInput.inputs.length > 0) {\n throw new Error('Diff mode cannot be used with batch mode');\n }\n }\n}\n\n/**\n * Validates batch mode requirements.\n * \n * @param options - CLI options\n * @param parsedInput - Parsed input information\n * @throws Error if batch mode is invalid\n */\nexport function validateBatchMode(\n options: CLIOptions,\n parsedInput: ParsedInput\n): void {\n if (options.batch) {\n if (parsedInput.isStdin) {\n throw new Error('Batch mode cannot be used with stdin input');\n }\n \n if (options.diff) {\n throw new Error('Batch mode cannot be used with diff mode');\n }\n \n if (!parsedInput.inputs || parsedInput.inputs.length === 0) {\n throw new Error('Batch mode requires multiple input files');\n }\n }\n}\n","/**\n * File I/O operations for CLI.\n */\n\nimport { readFileSync, writeFileSync } from 'fs';\nimport { stdin } from 'process';\n\n/**\n * Error thrown when file operations fail.\n */\nexport class FileIOError extends Error {\n constructor(\n message: string,\n public readonly code?: string,\n public readonly path?: string\n ) {\n super(message);\n this.name = 'FileIOError';\n }\n}\n\n/**\n * Reads HTML content from a file.\n * \n * @param filePath - Path to HTML file\n * @returns HTML content as string\n * @throws FileIOError if file cannot be read\n */\nexport function readHTMLFromFile(filePath: string): string {\n try {\n return readFileSync(filePath, 'utf-8');\n } catch (error: any) {\n if (error.code === 'ENOENT') {\n throw new FileIOError(\n `File not found: ${filePath}`,\n 'ENOENT',\n filePath\n );\n }\n \n if (error.code === 'EACCES') {\n throw new FileIOError(\n `Permission denied: ${filePath}`,\n 'EACCES',\n filePath\n );\n }\n \n if (error.code === 'EISDIR') {\n throw new FileIOError(\n `Path is a directory, not a file: ${filePath}`,\n 'EISDIR',\n filePath\n );\n }\n \n throw new FileIOError(\n `Failed to read file: ${filePath}. ${error.message}`,\n error.code,\n filePath\n );\n }\n}\n\n/**\n * Reads HTML content from stdin.\n * \n * @returns Promise that resolves to HTML content as string\n * @throws FileIOError if stdin cannot be read\n */\nexport async function readHTMLFromStdin(): Promise<string> {\n return new Promise((resolve, reject) => {\n const chunks: Buffer[] = [];\n \n stdin.on('data', (chunk: Buffer) => {\n chunks.push(chunk);\n });\n \n stdin.on('end', () => {\n const content = Buffer.concat(chunks).toString('utf-8');\n resolve(content);\n });\n \n stdin.on('error', (error: Error) => {\n reject(new FileIOError(\n `Failed to read from stdin: ${error.message}`,\n 'STDIN_ERROR'\n ));\n });\n \n // Handle case where stdin is closed immediately\n stdin.resume();\n });\n}\n\n/**\n * Writes output to a file.\n * \n * @param filePath - Path to output file\n * @param content - Content to write\n * @throws FileIOError if file cannot be written\n */\nexport function writeOutputToFile(filePath: string, content: string): void {\n try {\n writeFileSync(filePath, content, 'utf-8');\n } catch (error: any) {\n if (error.code === 'EACCES') {\n throw new FileIOError(\n `Permission denied: ${filePath}`,\n 'EACCES',\n filePath\n );\n }\n \n if (error.code === 'ENOSPC') {\n throw new FileIOError(\n `No space left on device: ${filePath}`,\n 'ENOSPC',\n filePath\n );\n }\n \n if (error.code === 'EISDIR') {\n throw new FileIOError(\n `Path is a directory, not a file: ${filePath}`,\n 'EISDIR',\n filePath\n );\n }\n \n throw new FileIOError(\n `Failed to write file: ${filePath}. ${error.message}`,\n error.code,\n filePath\n );\n }\n}\n\n/**\n * Writes output to stdout.\n * \n * @param content - Content to write\n */\nexport function writeOutputToStdout(content: string): void {\n console.log(content);\n}\n\n/**\n * Reads HTML from file or stdin based on parsed input.\n * \n * @param filePath - File path (undefined for stdin)\n * @param isStdin - Whether to read from stdin\n * @returns HTML content as string (or Promise for stdin)\n */\nexport function readHTML(\n filePath: string | undefined,\n isStdin: boolean\n): string | Promise<string> {\n if (isStdin) {\n return readHTMLFromStdin();\n }\n \n if (!filePath) {\n throw new FileIOError('No input source specified');\n }\n \n return readHTMLFromFile(filePath);\n}\n\n/**\n * Writes output to file or stdout based on options.\n * \n * @param content - Content to write\n * @param outputPath - Output file path (undefined for stdout)\n */\nexport function writeOutput(content: string, outputPath?: string): void {\n if (outputPath) {\n writeOutputToFile(outputPath, content);\n } else {\n writeOutputToStdout(content);\n }\n}\n","/**\n * HTML parsing using jsdom.\n * \n * Provides lenient parsing with error recovery for malformed HTML.\n */\n\nimport { JSDOM } from 'jsdom';\n\n/**\n * Parsing error class.\n */\nexport class ParsingError extends Error {\n constructor(message: string, public readonly cause?: Error) {\n super(message);\n this.name = 'ParsingError';\n }\n}\n\n/**\n * Parsing warning.\n */\nexport interface ParsingWarning {\n message: string;\n line?: number;\n column?: number;\n}\n\n/**\n * Result of HTML parsing.\n */\nexport interface ParseResult {\n /** Parsed DOM document */\n document: Document;\n \n /** Warnings encountered during parsing */\n warnings: ParsingWarning[];\n}\n\n/**\n * Parses HTML string into a DOM document.\n * \n * Uses jsdom with lenient parsing mode to handle malformed HTML.\n * Emits warnings for issues but continues processing.\n * \n * @param html - HTML string to parse\n * @returns Parse result with document and warnings\n * @throws ParsingError if parsing fails completely\n */\nexport function parseHTML(html: string): ParseResult {\n const warnings: ParsingWarning[] = [];\n\n try {\n // Create JSDOM instance with lenient parsing\n const dom = new JSDOM(html, {\n contentType: 'text/html',\n // Include useful defaults for accessibility tree extraction\n includeNodeLocations: false,\n storageQuota: 0,\n });\n\n const document = dom.window.document;\n\n // Check for parsing errors in the document\n // jsdom doesn't expose parse errors directly, but we can check for common issues\n if (!document.documentElement) {\n warnings.push({\n message: 'Document has no root element. HTML may be severely malformed.',\n });\n }\n\n // Check if body exists (should be created even for empty HTML)\n if (!document.body) {\n warnings.push({\n message: 'Document has no body element. HTML may be malformed.',\n });\n }\n\n return {\n document,\n warnings,\n };\n } catch (error) {\n // jsdom parsing failed completely\n throw new ParsingError(\n `Failed to parse HTML: ${error instanceof Error ? error.message : String(error)}`,\n error instanceof Error ? error : undefined\n );\n }\n}\n\n/**\n * Parses HTML and returns just the document (throws on warnings).\n * \n * Convenience function for cases where warnings should be treated as errors.\n * \n * @param html - HTML string to parse\n * @returns Parsed DOM document\n * @throws ParsingError if parsing fails or warnings are present\n */\nexport function parseHTMLStrict(html: string): Document {\n const result = parseHTML(html);\n\n if (result.warnings.length > 0) {\n const warningMessages = result.warnings.map((w) => w.message).join('; ');\n throw new ParsingError(`HTML parsing warnings: ${warningMessages}`);\n }\n\n return result.document;\n}\n\n/**\n * Validates that HTML string is not empty.\n * \n * @param html - HTML string to validate\n * @throws ParsingError if HTML is empty or whitespace-only\n */\nexport function validateHTMLNotEmpty(html: string): void {\n if (!html || html.trim().length === 0) {\n throw new ParsingError('HTML input is empty or contains only whitespace');\n }\n}\n","/**\n * ARIA accessible name computation.\n * \n * Implements the ARIA name computation algorithm following the W3C specification.\n * https://www.w3.org/TR/accname-1.2/\n */\n\n/**\n * Warning emitted during name computation.\n */\nexport interface NameComputationWarning {\n message: string;\n element: Element;\n}\n\n/**\n * Result of name computation.\n */\nexport interface NameComputationResult {\n name: string;\n warnings: NameComputationWarning[];\n}\n\n/**\n * Result of description computation.\n */\nexport interface DescriptionComputationResult {\n description: string;\n warnings: NameComputationWarning[];\n}\n\n/**\n * Computes the accessible name for an element following ARIA specification.\n * \n * Priority order:\n * 1. aria-labelledby (references to other elements)\n * 2. aria-label\n * 3. Native label (for form controls)\n * 4. alt attribute (for images)\n * 5. Text content (for elements that support it)\n * 6. title attribute (fallback)\n * \n * @param element - Element to compute name for\n * @param visited - Set of visited elements (for cycle detection)\n * @returns Computed accessible name and warnings\n */\nexport function computeAccessibleName(\n element: Element,\n visited: Set<Element> = new Set()\n): NameComputationResult {\n const warnings: NameComputationWarning[] = [];\n\n // Detect circular references\n if (visited.has(element)) {\n warnings.push({\n message: 'Circular reference detected in aria-labelledby chain',\n element,\n });\n return { name: '', warnings };\n }\n\n visited.add(element);\n\n // 1. aria-labelledby (highest priority)\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n const name = computeNameFromLabelledBy(element, labelledBy, visited, warnings);\n // Always return if aria-labelledby is present, even if name is empty\n return { name, warnings };\n }\n\n // 2. aria-label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.trim()) {\n return { name: ariaLabel.trim(), warnings };\n }\n\n // 3. Native label (for form controls)\n if (isFormControl(element)) {\n const labelName = computeNameFromLabel(element);\n if (labelName) {\n return { name: labelName, warnings };\n }\n }\n\n // 4. alt attribute (for images)\n if (element.tagName.toLowerCase() === 'img') {\n const alt = element.getAttribute('alt');\n if (alt !== null) {\n return { name: alt.trim(), warnings };\n }\n }\n\n // 5. Text content (for elements that support it)\n if (supportsNameFromContent(element)) {\n const textName = computeNameFromContent(element, visited);\n if (textName) {\n return { name: textName, warnings };\n }\n }\n\n // 6. title attribute (fallback)\n const title = element.getAttribute('title');\n if (title && title.trim()) {\n return { name: title.trim(), warnings };\n }\n\n // No name found\n return { name: '', warnings };\n}\n\n/**\n * Computes name from aria-labelledby attribute.\n * \n * @param element - Element with aria-labelledby\n * @param labelledBy - Space-separated list of IDs\n * @param visited - Set of visited elements\n * @param warnings - Array to collect warnings\n * @returns Computed name or empty string\n */\nfunction computeNameFromLabelledBy(\n element: Element,\n labelledBy: string,\n visited: Set<Element>,\n warnings: NameComputationWarning[]\n): string {\n const document = element.ownerDocument;\n if (!document) {\n return '';\n }\n\n const ids = labelledBy.trim().split(/\\s+/);\n const names: string[] = [];\n\n for (const id of ids) {\n if (!id) continue;\n\n const referencedElement = document.getElementById(id);\n if (!referencedElement) {\n warnings.push({\n message: `aria-labelledby references non-existent ID: ${id}`,\n element,\n });\n continue;\n }\n\n // Recursively compute name for referenced element\n // For labelledby, we want the text content of the referenced element\n const result = computeAccessibleName(referencedElement, new Set(visited));\n warnings.push(...result.warnings);\n \n // If no name was computed, fall back to text content\n const name = result.name || getTextContent(referencedElement);\n if (name) {\n names.push(name);\n }\n }\n\n return names.join(' ').trim();\n}\n\n/**\n * Computes name from associated label element.\n * \n * @param element - Form control element\n * @returns Name from label or empty string\n */\nfunction computeNameFromLabel(element: Element): string {\n const document = element.ownerDocument;\n if (!document) {\n return '';\n }\n\n // Check for explicit label association via id\n const id = element.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${id}\"]`);\n if (label) {\n return getTextContent(label);\n }\n }\n\n // Check for implicit label (element inside label)\n const parentLabel = element.closest('label');\n if (parentLabel) {\n return getTextContent(parentLabel);\n }\n\n return '';\n}\n\n/**\n * Computes name from element's text content.\n * \n * @param element - Element to get text from\n * @param visited - Set of visited elements\n * @returns Text content or empty string\n */\nfunction computeNameFromContent(element: Element, _visited: Set<Element>): string {\n return getTextContent(element);\n}\n\n/**\n * Gets text content from an element, excluding hidden elements.\n * \n * @param element - Element to get text from\n * @returns Trimmed text content\n */\nfunction getTextContent(element: Element): string {\n // Skip hidden elements\n if (element.getAttribute('aria-hidden') === 'true') {\n return '';\n }\n\n let text = '';\n\n for (const node of Array.from(element.childNodes)) {\n if (node.nodeType === 3) { // TEXT_NODE\n text += node.textContent || '';\n } else if (node.nodeType === 1) { // ELEMENT_NODE\n const childElement = node as Element;\n \n // Skip hidden children\n if (childElement.getAttribute('aria-hidden') === 'true') {\n continue;\n }\n\n text += getTextContent(childElement);\n }\n }\n\n return text.trim();\n}\n\n/**\n * Checks if element is a form control.\n * \n * @param element - Element to check\n * @returns true if element is a form control\n */\nfunction isFormControl(element: Element): boolean {\n const tagName = element.tagName.toLowerCase();\n return (\n tagName === 'input' ||\n tagName === 'textarea' ||\n tagName === 'select' ||\n tagName === 'button'\n );\n}\n\n/**\n * Checks if element supports name from content.\n * \n * Elements like buttons, links, and headings get their name from text content.\n * Form inputs do not.\n * \n * @param element - Element to check\n * @returns true if element supports name from content\n */\nfunction supportsNameFromContent(element: Element): boolean {\n const tagName = element.tagName.toLowerCase();\n const role = element.getAttribute('role');\n\n // Elements that support name from content\n const contentElements = [\n 'button',\n 'a',\n 'h1', 'h2', 'h3', 'h4', 'h5', 'h6',\n 'summary',\n 'figcaption',\n 'legend',\n 'caption',\n 'th',\n 'td',\n 'li',\n 'dt',\n 'dd',\n ];\n\n if (contentElements.includes(tagName)) {\n return true;\n }\n\n // Roles that support name from content\n const contentRoles = [\n 'button',\n 'link',\n 'heading',\n 'tab',\n 'treeitem',\n 'option',\n 'row',\n 'cell',\n 'columnheader',\n 'rowheader',\n 'tooltip',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n ];\n\n if (role && contentRoles.includes(role)) {\n return true;\n }\n\n return false;\n}\n\n\n/**\n * Computes the accessible description for an element.\n * \n * Priority order:\n * 1. aria-describedby (references to other elements)\n * 2. title attribute (fallback)\n * \n * @param element - Element to compute description for\n * @returns Computed accessible description and warnings\n */\nexport function computeAccessibleDescription(\n element: Element\n): DescriptionComputationResult {\n const warnings: NameComputationWarning[] = [];\n\n // 1. aria-describedby (highest priority)\n const describedBy = element.getAttribute('aria-describedby');\n if (describedBy) {\n const description = computeDescriptionFromDescribedBy(\n element,\n describedBy,\n warnings\n );\n if (description) {\n return { description, warnings };\n }\n }\n\n // 2. title attribute (fallback)\n const title = element.getAttribute('title');\n if (title && title.trim()) {\n return { description: title.trim(), warnings };\n }\n\n // No description found\n return { description: '', warnings };\n}\n\n/**\n * Computes description from aria-describedby attribute.\n * \n * @param element - Element with aria-describedby\n * @param describedBy - Space-separated list of IDs\n * @param warnings - Array to collect warnings\n * @returns Computed description or empty string\n */\nfunction computeDescriptionFromDescribedBy(\n element: Element,\n describedBy: string,\n warnings: NameComputationWarning[]\n): string {\n const document = element.ownerDocument;\n if (!document) {\n return '';\n }\n\n const ids = describedBy.trim().split(/\\s+/);\n const descriptions: string[] = [];\n\n for (const id of ids) {\n if (!id) continue;\n\n const referencedElement = document.getElementById(id);\n if (!referencedElement) {\n warnings.push({\n message: `aria-describedby references non-existent ID: ${id}`,\n element,\n });\n continue;\n }\n\n // Get text content from referenced element\n const text = getTextContent(referencedElement);\n if (text) {\n descriptions.push(text);\n }\n }\n\n return descriptions.join(' ').trim();\n}\n","/**\n * Canonical Announcement Model - Version 1\n * \n * Platform-agnostic representation of accessibility semantics.\n * Deterministic, serializable, suitable for snapshot testing.\n */\n\n/**\n * Model version for forward compatibility.\n * Breaking changes increment major version.\n */\nexport interface ModelVersion {\n major: number;\n minor: number;\n}\n\n/**\n * Accessible role following ARIA specification.\n * V1 supports common interactive and structural roles.\n */\nexport type AccessibleRole =\n // Interactive elements\n | 'button'\n | 'link'\n | 'heading'\n | 'textbox'\n | 'checkbox'\n | 'radio'\n | 'combobox'\n | 'listbox'\n | 'option'\n // Structural\n | 'list'\n | 'listitem'\n | 'article'\n | 'generic'\n // Landmarks\n | 'navigation'\n | 'main'\n | 'banner'\n | 'contentinfo'\n | 'region'\n | 'img'\n | 'complementary'\n | 'form'\n | 'search'\n // Static content (new)\n | 'paragraph'\n | 'blockquote'\n | 'code'\n | 'staticText'\n // Tables (new)\n | 'table'\n | 'row'\n | 'cell'\n | 'columnheader'\n | 'rowheader'\n // Definition lists (new)\n | 'term'\n | 'definition'\n // Figures (new)\n | 'figure'\n | 'caption'\n // Grouping & disclosure (new)\n | 'group'\n | 'dialog'\n // Widgets (new)\n | 'meter'\n | 'progressbar'\n | 'status'\n // Embedded content (new)\n | 'document'\n | 'application'\n | 'separator';\n\n/**\n * Accessible states and properties.\n * Only includes properties relevant to the element's role.\n */\nexport interface AccessibleState {\n /** Whether the element is expanded (e.g., accordion, dropdown) */\n expanded?: boolean;\n \n /** Whether the element is checked (checkbox, radio, or mixed state) */\n checked?: boolean | 'mixed';\n \n /** Whether the element is pressed (toggle button) */\n pressed?: boolean | 'mixed';\n \n /** Whether the element is selected (option, tab, etc.) */\n selected?: boolean;\n \n /** Whether the element is disabled */\n disabled?: boolean;\n \n /** Whether the element has invalid input */\n invalid?: boolean;\n \n /** Whether the element is required */\n required?: boolean;\n \n /** Whether the element is read-only */\n readonly?: boolean;\n \n /** Whether the element is busy loading */\n busy?: boolean;\n \n /** Current page/step/location indicator */\n current?: 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | false;\n \n /** Whether the element is grabbed for drag-and-drop */\n grabbed?: boolean;\n \n /** Whether the element is hidden from accessibility tree */\n hidden?: boolean;\n \n /** Heading level (1-6) */\n level?: number;\n \n /** Position in set (1-indexed) for lists, tabs, etc. */\n posinset?: number;\n \n /** Total size of set */\n setsize?: number;\n}\n\n/**\n * Value for form controls and range widgets.\n */\nexport interface AccessibleValue {\n /** Current value */\n current: string | number;\n \n /** Minimum value (for range widgets) */\n min?: number;\n \n /** Maximum value (for range widgets) */\n max?: number;\n \n /** Textual representation (e.g., \"50%\") */\n text?: string;\n}\n\n/**\n * Focusability information.\n */\nexport interface FocusInfo {\n /** Whether the element can receive focus */\n focusable: boolean;\n \n /** Explicit tabindex value (only present if explicitly set) */\n tabindex?: number;\n}\n\n/**\n * Single node in the accessibility tree.\n */\nexport interface AccessibleNode {\n /** ARIA role of the element */\n role: AccessibleRole;\n \n /** Accessible name (computed via ARIA name algorithm) */\n name: string;\n \n /** Accessible description (aria-describedby, title, etc.) */\n description?: string;\n \n /** Value for form controls */\n value?: AccessibleValue;\n \n /** State properties */\n state: AccessibleState;\n \n /** Focus information */\n focus: FocusInfo;\n \n /** Child nodes in the accessibility tree */\n children: AccessibleNode[];\n}\n\n/**\n * Root of the Canonical Announcement Model.\n */\nexport interface AnnouncementModel {\n /** Model version for forward compatibility */\n version: ModelVersion;\n \n /** Root node of the accessibility tree */\n root: AccessibleNode;\n \n /** Metadata about the extraction */\n metadata: {\n /** ISO 8601 timestamp of extraction */\n extractedAt: string;\n \n /** Optional hash of source HTML for change detection */\n sourceHash?: string;\n };\n}\n\n/**\n * Supported roles as a constant array for validation.\n */\nexport const SUPPORTED_ROLES: readonly AccessibleRole[] = [\n // Original roles (22)\n 'button',\n 'link',\n 'heading',\n 'textbox',\n 'checkbox',\n 'radio',\n 'combobox',\n 'listbox',\n 'option',\n 'list',\n 'listitem',\n 'navigation',\n 'main',\n 'banner',\n 'contentinfo',\n 'region',\n 'img',\n 'article',\n 'complementary',\n 'form',\n 'search',\n 'generic',\n // New roles (21)\n 'paragraph',\n 'blockquote',\n 'code',\n 'staticText',\n 'table',\n 'row',\n 'cell',\n 'columnheader',\n 'rowheader',\n 'term',\n 'definition',\n 'figure',\n 'caption',\n 'group',\n 'dialog',\n 'meter',\n 'progressbar',\n 'status',\n 'document',\n 'application',\n 'separator',\n] as const;\n\n/**\n * Current model version constant.\n */\nexport const CURRENT_MODEL_VERSION: ModelVersion = {\n major: 1,\n minor: 0,\n};\n","/**\n * Role computation and mapping.\n * \n * Maps HTML elements to their implicit ARIA roles and validates explicit roles.\n */\n\nimport type { AccessibleRole } from '../model/types.js';\nimport { SUPPORTED_ROLES } from '../model/types.js';\n\n/**\n * Warning emitted during role computation.\n */\nexport interface RoleComputationWarning {\n message: string;\n element: Element;\n}\n\n/**\n * Result of role computation.\n */\nexport interface RoleComputationResult {\n role: AccessibleRole | null;\n warnings: RoleComputationWarning[];\n}\n\n/**\n * Mapping of HTML elements to their implicit ARIA roles.\n */\nconst IMPLICIT_ROLE_MAP: Record<string, AccessibleRole> = {\n // Interactive elements\n 'button': 'button',\n 'a': 'link', // Only if href attribute present\n \n // Form controls\n 'input': 'textbox', // Default, varies by type\n 'textarea': 'textbox',\n 'select': 'listbox',\n \n // Headings\n 'h1': 'heading',\n 'h2': 'heading',\n 'h3': 'heading',\n 'h4': 'heading',\n 'h5': 'heading',\n 'h6': 'heading',\n \n // Landmarks\n 'nav': 'navigation',\n 'main': 'main',\n 'header': 'banner', // Only if not nested in article/section\n 'footer': 'contentinfo', // Only if not nested in article/section\n 'aside': 'complementary',\n 'form': 'form',\n 'section': 'region', // Only if has accessible name\n \n // Lists\n 'ul': 'list',\n 'ol': 'list',\n 'li': 'listitem',\n \n // Images\n 'img': 'img',\n \n // Articles\n 'article': 'article',\n\n // Static content (new)\n 'p': 'paragraph',\n 'blockquote': 'blockquote',\n 'code': 'code',\n 'pre': 'code',\n\n // Tables (new)\n 'table': 'table',\n 'tr': 'row',\n 'td': 'cell',\n 'th': 'columnheader', // Default; scope=\"row\" handled in computeImplicitRole\n\n // Definition lists (new)\n 'dl': 'list',\n 'dt': 'term',\n 'dd': 'definition',\n\n // Figures (new)\n 'figure': 'figure',\n 'figcaption': 'caption',\n\n // Disclosure (new)\n 'details': 'group',\n 'summary': 'button',\n\n // Dialogs and widgets (new)\n 'dialog': 'dialog',\n 'meter': 'meter',\n 'progress': 'progressbar',\n 'output': 'status',\n\n // Forms (new)\n 'fieldset': 'group',\n 'legend': 'caption',\n\n // Embedded content (new)\n 'iframe': 'document',\n 'video': 'application',\n 'audio': 'application',\n\n // Separators (new)\n 'hr': 'separator',\n\n // Table caption (new)\n 'caption': 'caption',\n};\n\n/**\n * Input type to role mapping.\n */\nconst INPUT_TYPE_ROLE_MAP: Record<string, AccessibleRole> = {\n 'button': 'button',\n 'submit': 'button',\n 'reset': 'button',\n 'checkbox': 'checkbox',\n 'radio': 'radio',\n 'text': 'textbox',\n 'email': 'textbox',\n 'password': 'textbox',\n 'search': 'textbox',\n 'tel': 'textbox',\n 'url': 'textbox',\n 'number': 'textbox',\n};\n\n/**\n * Computes the accessible role for an element.\n * \n * Priority:\n * 1. Explicit role attribute (if valid)\n * 2. Implicit role based on element type\n * 3. null if no role\n * \n * @param element - Element to compute role for\n * @returns Computed role and warnings\n */\nexport function computeRole(element: Element): RoleComputationResult {\n const warnings: RoleComputationWarning[] = [];\n \n // 1. Check for explicit role attribute\n const explicitRole = element.getAttribute('role');\n if (explicitRole) {\n const role = validateAndNormalizeRole(explicitRole, element, warnings);\n if (role) {\n return { role, warnings };\n }\n // If explicit role is invalid, fall through to implicit role\n }\n \n // 2. Compute implicit role\n const implicitRole = computeImplicitRole(element, warnings);\n return { role: implicitRole, warnings };\n}\n\n/**\n * Validates and normalizes an explicit role attribute.\n * \n * @param roleAttr - Role attribute value\n * @param element - Element with the role\n * @param warnings - Array to collect warnings\n * @returns Validated role or null if invalid\n */\nfunction validateAndNormalizeRole(\n roleAttr: string,\n element: Element,\n warnings: RoleComputationWarning[]\n): AccessibleRole | null {\n const role = roleAttr.trim().toLowerCase();\n \n // Check for presentation/none roles (elements should be hidden from a11y tree)\n if (role === 'presentation' || role === 'none') {\n return null;\n }\n \n // Validate against supported roles\n if (SUPPORTED_ROLES.includes(role as AccessibleRole)) {\n return role as AccessibleRole;\n }\n \n // Invalid or unsupported role\n warnings.push({\n message: `Invalid or unsupported role: \"${roleAttr}\". Falling back to implicit role.`,\n element,\n });\n \n return null;\n}\n\n/**\n * Computes the implicit ARIA role for an element.\n * \n * @param element - Element to compute implicit role for\n * @param warnings - Array to collect warnings\n * @returns Implicit role or null\n */\nfunction computeImplicitRole(\n element: Element,\n _warnings: RoleComputationWarning[]\n): AccessibleRole | null {\n const tagName = element.tagName.toLowerCase();\n \n // Special case: input elements vary by type\n if (tagName === 'input') {\n return computeInputRole(element as HTMLInputElement);\n }\n \n // Special case: links only have link role if href present\n if (tagName === 'a') {\n return element.hasAttribute('href') ? 'link' : null;\n }\n \n // Special case: header/footer only landmarks if not nested\n if (tagName === 'header') {\n return isTopLevelLandmark(element) ? 'banner' : null;\n }\n \n if (tagName === 'footer') {\n return isTopLevelLandmark(element) ? 'contentinfo' : null;\n }\n \n // Special case: th elements — scope=\"row\" maps to rowheader\n if (tagName === 'th') {\n const scope = element.getAttribute('scope');\n return scope === 'row' ? 'rowheader' : 'columnheader';\n }\n\n // Special case: section only has region role if it has accessible name\n if (tagName === 'section') {\n // For now, we'll return 'region' - the caller should check if it has a name\n // In a full implementation, we'd check for aria-label or aria-labelledby\n return element.hasAttribute('aria-label') || element.hasAttribute('aria-labelledby')\n ? 'region'\n : null;\n }\n \n // Look up in implicit role map\n const implicitRole = IMPLICIT_ROLE_MAP[tagName];\n return implicitRole || null;\n}\n\n/**\n * Computes the role for an input element based on its type.\n * \n * @param input - Input element\n * @returns Role for the input\n */\nfunction computeInputRole(input: HTMLInputElement): AccessibleRole {\n const type = (input.getAttribute('type') || 'text').toLowerCase();\n return INPUT_TYPE_ROLE_MAP[type] || 'textbox';\n}\n\n/**\n * Checks if header/footer is a top-level landmark.\n * \n * Header and footer only have landmark roles (banner/contentinfo) when they\n * are not nested inside article or section elements.\n * \n * @param element - Header or footer element\n * @returns true if top-level landmark\n */\nfunction isTopLevelLandmark(element: Element): boolean {\n let parent = element.parentElement;\n \n while (parent) {\n const tagName = parent.tagName.toLowerCase();\n if (tagName === 'article' || tagName === 'section') {\n return false;\n }\n parent = parent.parentElement;\n }\n \n return true;\n}\n\n/**\n * Checks if an element should be included in the accessibility tree.\n * \n * Elements are excluded if:\n * - They have role=\"presentation\" or role=\"none\"\n * - They have aria-hidden=\"true\"\n * - They have no accessible role\n * \n * @param element - Element to check\n * @returns true if element should be included\n */\nexport function isAccessible(element: Element): boolean {\n // Check aria-hidden\n if (element.getAttribute('aria-hidden') === 'true') {\n return false;\n }\n \n // Check for presentation/none role\n const role = element.getAttribute('role');\n if (role === 'presentation' || role === 'none') {\n return false;\n }\n \n // Element is accessible if it has a role (explicit or implicit)\n const roleResult = computeRole(element);\n return roleResult.role !== null;\n}\n","/**\n * State and property extraction from ARIA attributes.\n * \n * Extracts accessibility states and properties from elements.\n */\n\nimport type { AccessibleState, AccessibleValue } from '../model/types.js';\n\n/**\n * Warning emitted during state extraction.\n */\nexport interface StateExtractionWarning {\n message: string;\n element: Element;\n}\n\n/**\n * Result of state extraction.\n */\nexport interface StateExtractionResult {\n state: AccessibleState;\n warnings: StateExtractionWarning[];\n}\n\n/**\n * Result of value extraction.\n */\nexport interface ValueExtractionResult {\n value: AccessibleValue | undefined;\n warnings: StateExtractionWarning[];\n}\n\n/**\n * Extracts accessibility state from an element.\n * \n * Extracts ARIA state attributes and native element states.\n * \n * @param element - Element to extract state from\n * @returns Extracted state and warnings\n */\nexport function extractState(element: Element): StateExtractionResult {\n const warnings: StateExtractionWarning[] = [];\n const state: AccessibleState = {};\n\n // aria-expanded\n const expanded = extractBooleanAttribute(element, 'aria-expanded', warnings);\n if (expanded !== undefined) {\n state.expanded = expanded;\n }\n\n // aria-checked (boolean or 'mixed')\n const checked = extractTriStateAttribute(element, 'aria-checked', warnings);\n if (checked !== undefined) {\n state.checked = checked;\n }\n\n // aria-pressed (boolean or 'mixed')\n const pressed = extractTriStateAttribute(element, 'aria-pressed', warnings);\n if (pressed !== undefined) {\n state.pressed = pressed;\n }\n\n // aria-selected\n const selected = extractBooleanAttribute(element, 'aria-selected', warnings);\n if (selected !== undefined) {\n state.selected = selected;\n }\n\n // aria-disabled\n const disabled = extractBooleanAttribute(element, 'aria-disabled', warnings);\n if (disabled !== undefined) {\n state.disabled = disabled;\n }\n\n // aria-invalid\n const invalid = extractBooleanAttribute(element, 'aria-invalid', warnings);\n if (invalid !== undefined) {\n state.invalid = invalid;\n }\n\n // aria-required\n const required = extractBooleanAttribute(element, 'aria-required', warnings);\n if (required !== undefined) {\n state.required = required;\n }\n\n // aria-readonly\n const readonly = extractBooleanAttribute(element, 'aria-readonly', warnings);\n if (readonly !== undefined) {\n state.readonly = readonly;\n }\n\n // aria-busy\n const busy = extractBooleanAttribute(element, 'aria-busy', warnings);\n if (busy !== undefined) {\n state.busy = busy;\n }\n\n // aria-current\n const current = extractCurrentAttribute(element, warnings);\n if (current !== undefined) {\n state.current = current;\n }\n\n // aria-grabbed\n const grabbed = extractBooleanAttribute(element, 'aria-grabbed', warnings);\n if (grabbed !== undefined) {\n state.grabbed = grabbed;\n }\n\n // aria-hidden\n const hidden = extractBooleanAttribute(element, 'aria-hidden', warnings);\n if (hidden !== undefined) {\n state.hidden = hidden;\n }\n\n // aria-level (for headings)\n const level = extractLevelAttribute(element, warnings);\n if (level !== undefined) {\n state.level = level;\n }\n\n // aria-posinset and aria-setsize (for lists, tabs, etc.)\n const posinset = extractNumberAttribute(element, 'aria-posinset', warnings);\n if (posinset !== undefined) {\n state.posinset = posinset;\n }\n\n const setsize = extractNumberAttribute(element, 'aria-setsize', warnings);\n if (setsize !== undefined) {\n state.setsize = setsize;\n }\n\n // Extract native element states\n extractNativeStates(element, state, warnings);\n\n return { state, warnings };\n}\n\n/**\n * Extracts value information from form controls.\n * \n * @param element - Element to extract value from\n * @returns Extracted value and warnings\n */\nexport function extractValue(element: Element): ValueExtractionResult {\n const warnings: StateExtractionWarning[] = [];\n\n // Only extract value for form controls\n const tagName = element.tagName.toLowerCase();\n \n if (tagName === 'input') {\n return extractInputValue(element as HTMLInputElement, warnings);\n }\n\n if (tagName === 'textarea') {\n return extractTextareaValue(element as HTMLTextAreaElement, warnings);\n }\n\n if (tagName === 'select') {\n return extractSelectValue(element as HTMLSelectElement, warnings);\n }\n\n // Check for aria-valuenow (for range widgets)\n const valueNow = element.getAttribute('aria-valuenow');\n if (valueNow !== null) {\n const current = parseFloat(valueNow);\n if (!isNaN(current)) {\n const valueMin = element.getAttribute('aria-valuemin');\n const valueMax = element.getAttribute('aria-valuemax');\n const valueText = element.getAttribute('aria-valuetext');\n\n return {\n value: {\n current,\n min: valueMin !== null ? parseFloat(valueMin) : undefined,\n max: valueMax !== null ? parseFloat(valueMax) : undefined,\n text: valueText || undefined,\n },\n warnings,\n };\n }\n }\n\n return { value: undefined, warnings };\n}\n\n/**\n * Extracts boolean ARIA attribute.\n * \n * @param element - Element to extract from\n * @param attrName - Attribute name\n * @param warnings - Array to collect warnings\n * @returns Boolean value or undefined\n */\nfunction extractBooleanAttribute(\n element: Element,\n attrName: string,\n warnings: StateExtractionWarning[]\n): boolean | undefined {\n const value = element.getAttribute(attrName);\n if (value === null) {\n return undefined;\n }\n\n const normalized = value.toLowerCase().trim();\n if (normalized === 'true') {\n return true;\n }\n if (normalized === 'false') {\n return false;\n }\n\n warnings.push({\n message: `Invalid ${attrName} value: \"${value}\". Expected \"true\" or \"false\".`,\n element,\n });\n return undefined;\n}\n\n/**\n * Extracts tri-state ARIA attribute (boolean or 'mixed').\n * \n * @param element - Element to extract from\n * @param attrName - Attribute name\n * @param warnings - Array to collect warnings\n * @returns Boolean, 'mixed', or undefined\n */\nfunction extractTriStateAttribute(\n element: Element,\n attrName: string,\n warnings: StateExtractionWarning[]\n): boolean | 'mixed' | undefined {\n const value = element.getAttribute(attrName);\n if (value === null) {\n return undefined;\n }\n\n const normalized = value.toLowerCase().trim();\n if (normalized === 'true') {\n return true;\n }\n if (normalized === 'false') {\n return false;\n }\n if (normalized === 'mixed') {\n return 'mixed';\n }\n\n warnings.push({\n message: `Invalid ${attrName} value: \"${value}\". Expected \"true\", \"false\", or \"mixed\".`,\n element,\n });\n return undefined;\n}\n\n/**\n * Extracts aria-current attribute.\n * \n * @param element - Element to extract from\n * @param warnings - Array to collect warnings\n * @returns Current value or undefined\n */\nfunction extractCurrentAttribute(\n element: Element,\n warnings: StateExtractionWarning[]\n): 'page' | 'step' | 'location' | 'date' | 'time' | 'true' | false | undefined {\n const value = element.getAttribute('aria-current');\n if (value === null) {\n return undefined;\n }\n\n const normalized = value.toLowerCase().trim();\n const validValues = ['page', 'step', 'location', 'date', 'time', 'true', 'false'];\n\n if (validValues.includes(normalized)) {\n return normalized === 'false' ? false : (normalized as any);\n }\n\n warnings.push({\n message: `Invalid aria-current value: \"${value}\". Expected one of: ${validValues.join(', ')}.`,\n element,\n });\n return undefined;\n}\n\n/**\n * Extracts aria-level attribute for headings.\n * \n * @param element - Element to extract from\n * @param warnings - Array to collect warnings\n * @returns Level (1-6) or undefined\n */\nfunction extractLevelAttribute(\n element: Element,\n warnings: StateExtractionWarning[]\n): number | undefined {\n // Check aria-level attribute\n const ariaLevel = element.getAttribute('aria-level');\n if (ariaLevel !== null) {\n const level = parseInt(ariaLevel, 10);\n if (!isNaN(level) && level >= 1 && level <= 6) {\n return level;\n }\n warnings.push({\n message: `Invalid aria-level value: \"${ariaLevel}\". Expected integer 1-6.`,\n element,\n });\n return undefined;\n }\n\n // Check native heading level\n const tagName = element.tagName.toLowerCase();\n const match = tagName.match(/^h([1-6])$/);\n if (match) {\n return parseInt(match[1], 10);\n }\n\n return undefined;\n}\n\n/**\n * Extracts numeric ARIA attribute.\n * \n * @param element - Element to extract from\n * @param attrName - Attribute name\n * @param warnings - Array to collect warnings\n * @returns Number or undefined\n */\nfunction extractNumberAttribute(\n element: Element,\n attrName: string,\n warnings: StateExtractionWarning[]\n): number | undefined {\n const value = element.getAttribute(attrName);\n if (value === null) {\n return undefined;\n }\n\n const num = parseInt(value, 10);\n if (isNaN(num) || num < 1) {\n warnings.push({\n message: `Invalid ${attrName} value: \"${value}\". Expected positive integer.`,\n element,\n });\n return undefined;\n }\n\n return num;\n}\n\n/**\n * Extracts native element states (checked, disabled, etc.).\n * \n * @param element - Element to extract from\n * @param state - State object to populate\n * @param warnings - Array to collect warnings\n */\nfunction extractNativeStates(\n element: Element,\n state: AccessibleState,\n _warnings: StateExtractionWarning[]\n): void {\n const tagName = element.tagName.toLowerCase();\n\n // Native checked state for checkboxes and radios\n if (tagName === 'input') {\n const input = element as HTMLInputElement;\n const type = input.type.toLowerCase();\n\n if (type === 'checkbox' || type === 'radio') {\n // Only set if not already set by aria-checked\n if (state.checked === undefined) {\n state.checked = input.checked;\n }\n }\n }\n\n // Native disabled state\n if ('disabled' in element) {\n const htmlElement = element as HTMLInputElement | HTMLButtonElement | HTMLSelectElement | HTMLTextAreaElement;\n // Only set if not already set by aria-disabled\n if (state.disabled === undefined && htmlElement.disabled) {\n state.disabled = true;\n }\n }\n\n // Native required state\n if ('required' in element) {\n const htmlElement = element as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n // Only set if not already set by aria-required\n if (state.required === undefined && htmlElement.required) {\n state.required = true;\n }\n }\n\n // Native readonly state\n if ('readOnly' in element) {\n const htmlElement = element as HTMLInputElement | HTMLTextAreaElement;\n // Only set if not already set by aria-readonly\n if (state.readonly === undefined && htmlElement.readOnly) {\n state.readonly = true;\n }\n }\n}\n\n/**\n * Extracts value from input element.\n */\nfunction extractInputValue(\n input: HTMLInputElement,\n warnings: StateExtractionWarning[]\n): ValueExtractionResult {\n const type = input.type.toLowerCase();\n\n // Checkbox and radio use checked state, not value\n if (type === 'checkbox' || type === 'radio') {\n return { value: undefined, warnings };\n }\n\n // Button types don't have meaningful values\n if (type === 'button' || type === 'submit' || type === 'reset') {\n return { value: undefined, warnings };\n }\n\n // Text-like inputs\n const value = input.value;\n if (value) {\n return {\n value: {\n current: value,\n text: value,\n },\n warnings,\n };\n }\n\n return { value: undefined, warnings };\n}\n\n/**\n * Extracts value from textarea element.\n */\nfunction extractTextareaValue(\n textarea: HTMLTextAreaElement,\n warnings: StateExtractionWarning[]\n): ValueExtractionResult {\n const value = textarea.value;\n if (value) {\n return {\n value: {\n current: value,\n text: value,\n },\n warnings,\n };\n }\n\n return { value: undefined, warnings };\n}\n\n/**\n * Extracts value from select element.\n */\nfunction extractSelectValue(\n select: HTMLSelectElement,\n warnings: StateExtractionWarning[]\n): ValueExtractionResult {\n const value = select.value;\n const selectedOption = select.options[select.selectedIndex];\n const text = selectedOption?.textContent || value;\n\n if (value) {\n return {\n value: {\n current: value,\n text,\n },\n warnings,\n };\n }\n\n return { value: undefined, warnings };\n}\n","/**\n * Focus information extraction.\n * \n * Determines focusability and tabindex for elements.\n */\n\nimport type { FocusInfo } from '../model/types.js';\n\n/**\n * Natively focusable element types.\n */\nconst NATIVELY_FOCUSABLE_ELEMENTS = [\n 'a',\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'area',\n 'iframe',\n 'object',\n 'embed',\n 'audio',\n 'video',\n];\n\n/**\n * Extracts focus information from an element.\n * \n * Determines if an element is focusable and extracts explicit tabindex.\n * \n * @param element - Element to extract focus info from\n * @returns Focus information\n */\nexport function extractFocusInfo(element: Element): FocusInfo {\n const tabindexAttr = element.getAttribute('tabindex');\n const tabindex = tabindexAttr !== null ? parseInt(tabindexAttr, 10) : undefined;\n\n // Determine focusability\n const focusable = isFocusable(element, tabindex);\n\n // Only include tabindex if explicitly set\n return {\n focusable,\n ...(tabindexAttr !== null && !isNaN(tabindex!) && { tabindex }),\n };\n}\n\n/**\n * Determines if an element is focusable.\n * \n * An element is focusable if:\n * - It's a natively focusable element (and not disabled)\n * - It has tabindex >= 0\n * - It has tabindex = -1 (programmatically focusable)\n * \n * @param element - Element to check\n * @param tabindex - Parsed tabindex value\n * @returns true if element is focusable\n */\nfunction isFocusable(element: Element, tabindex: number | undefined): boolean {\n const tagName = element.tagName.toLowerCase();\n\n // Check if element is disabled\n if (isDisabled(element)) {\n return false;\n }\n\n // Explicit tabindex makes element focusable (including -1 for programmatic focus)\n if (tabindex !== undefined && !isNaN(tabindex)) {\n return true;\n }\n\n // Check if natively focusable\n if (isNativelyFocusable(element, tagName)) {\n return true;\n }\n\n // Elements with explicit ARIA roles may be focusable\n // For now, we'll be conservative and only mark as focusable if tabindex is set\n return false;\n}\n\n/**\n * Checks if an element is natively focusable.\n * \n * @param element - Element to check\n * @param tagName - Tag name (lowercase)\n * @returns true if natively focusable\n */\nfunction isNativelyFocusable(element: Element, tagName: string): boolean {\n // Links must have href to be focusable\n if (tagName === 'a' || tagName === 'area') {\n return element.hasAttribute('href');\n }\n\n // Check if in the list of natively focusable elements\n if (NATIVELY_FOCUSABLE_ELEMENTS.includes(tagName)) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Checks if an element is disabled.\n * \n * @param element - Element to check\n * @returns true if disabled\n */\nfunction isDisabled(element: Element): boolean {\n // Check native disabled attribute\n if ('disabled' in element) {\n const htmlElement = element as HTMLInputElement | HTMLButtonElement | HTMLSelectElement | HTMLTextAreaElement;\n if (htmlElement.disabled) {\n return true;\n }\n }\n\n // Check aria-disabled\n const ariaDisabled = element.getAttribute('aria-disabled');\n if (ariaDisabled === 'true') {\n return true;\n }\n\n return false;\n}\n","/**\n * Accessibility tree builder.\n * \n * Builds the complete accessibility tree from a DOM tree by integrating\n * all extraction components (role, name, description, state, value, focus).\n * \n * Supports transparent traversal through role-less elements, text node\n * capture as staticText nodes, shadow DOM traversal, and CSS hidden state.\n */\n\nimport type { AccessibleNode, AnnouncementModel } from '../model/types.js';\nimport { CURRENT_MODEL_VERSION } from '../model/types.js';\nimport { computeAccessibleName, computeAccessibleDescription } from './aria-name.js';\nimport { computeRole, isAccessible } from './role-mapper.js';\nimport { extractState, extractValue } from './state-extractor.js';\nimport { extractFocusInfo } from './focus-extractor.js';\n\n/**\n * Warning emitted during tree building.\n */\nexport interface TreeBuildWarning {\n message: string;\n element: Element;\n}\n\n/**\n * Result of tree building.\n */\nexport interface TreeBuildResult {\n model: AnnouncementModel;\n warnings: TreeBuildWarning[];\n}\n\n/**\n * Error thrown when selector filtering fails.\n */\nexport class SelectorError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'SelectorError';\n }\n}\n\n/**\n * Checks whether an element is hidden from the accessibility tree.\n * \n * Checks aria-hidden=\"true\", display: none, and visibility: hidden.\n * Gracefully skips CSS checks when getComputedStyle is unavailable.\n * \n * @param element - Element to check\n * @returns true if the element is hidden\n */\nfunction isHidden(element: Element): boolean {\n // Check aria-hidden on element itself\n if (element.getAttribute('aria-hidden') === 'true') return true;\n\n // Check CSS hidden state if getComputedStyle is available\n if (typeof getComputedStyle === 'function') {\n try {\n const style = getComputedStyle(element);\n if (style.display === 'none') return true;\n if (style.visibility === 'hidden') return true;\n } catch {\n // Environment doesn't support getComputedStyle — skip CSS checks\n }\n }\n\n return false;\n}\n\n/**\n * Processes a single child node (Text or Element) and appends resulting\n * AccessibleNodes to the children array.\n * \n * For Text nodes: creates a staticText AccessibleNode with trimmed text.\n * For Element nodes: checks hidden/accessible state; if role-less, does\n * transparent traversal via collectChildrenFromRolelessElement.\n * \n * @param node - DOM node to process\n * @param children - Array to append resulting AccessibleNodes to\n * @param warnings - Array to collect warnings\n */\nfunction processChildNode(\n node: Node,\n children: AccessibleNode[],\n warnings: TreeBuildWarning[]\n): void {\n if (node.nodeType === 3) { // TEXT_NODE\n const text = (node.textContent || '').trim();\n if (text.length > 0) {\n children.push({\n role: 'staticText',\n name: text,\n state: {},\n focus: { focusable: false },\n children: [],\n });\n }\n return;\n }\n if (node.nodeType === 1) { // ELEMENT_NODE\n const element = node as Element;\n if (isHidden(element)) return;\n if (!isAccessible(element)) {\n // Transparent traversal: collect children from role-less element\n const grandchildren = collectChildrenFromRolelessElement(element, warnings);\n children.push(...grandchildren);\n return;\n }\n const childNode = buildNodeRecursive(element, warnings);\n if (childNode) children.push(childNode);\n }\n}\n\n/**\n * Collects accessible children from a role-less element (transparent traversal).\n * \n * Traverses shadow DOM first (if present), then light DOM childNodes.\n * Returns a flat array of AccessibleNodes to be merged into the parent's children.\n * \n * @param element - Role-less element to collect children from\n * @param warnings - Array to collect warnings\n * @returns Flat array of AccessibleNodes\n */\nfunction collectChildrenFromRolelessElement(\n element: Element,\n warnings: TreeBuildWarning[]\n): AccessibleNode[] {\n const children: AccessibleNode[] = [];\n // Traverse shadow DOM first if present\n if (element.shadowRoot) {\n for (const child of Array.from(element.shadowRoot.childNodes)) {\n processChildNode(child, children, warnings);\n }\n }\n // Then light DOM\n for (const child of Array.from(element.childNodes)) {\n processChildNode(child, children, warnings);\n }\n return children;\n}\n\n/**\n * Builds an accessibility tree from a DOM element.\n * \n * Traverses the DOM tree depth-first, applies all extractors,\n * filters inaccessible elements, and builds the hierarchical tree.\n * \n * @param rootElement - Root DOM element to build tree from\n * @param sourceHash - Optional hash of source HTML for change detection\n * @returns Announcement model and warnings\n */\nexport function buildAccessibilityTree(\n rootElement: Element,\n sourceHash?: string\n): TreeBuildResult {\n const warnings: TreeBuildWarning[] = [];\n \n // If root element is hidden, return empty generic container\n if (isHidden(rootElement)) {\n const model: AnnouncementModel = {\n version: CURRENT_MODEL_VERSION,\n root: {\n role: 'generic',\n name: '',\n state: {},\n focus: { focusable: false },\n children: [],\n },\n metadata: {\n extractedAt: new Date().toISOString(),\n ...(sourceHash && { sourceHash }),\n },\n };\n return { model, warnings };\n }\n\n // Build the root node\n const rootNode = buildNodeRecursive(rootElement, warnings);\n \n // If root element is not accessible, create a generic container\n const accessibleRoot = rootNode || createGenericContainer(rootElement, warnings);\n \n // Create the announcement model\n const model: AnnouncementModel = {\n version: CURRENT_MODEL_VERSION,\n root: accessibleRoot,\n metadata: {\n extractedAt: new Date().toISOString(),\n ...(sourceHash && { sourceHash }),\n },\n };\n \n return { model, warnings };\n}\n\n/**\n * Builds accessibility trees for elements matching a CSS selector.\n * \n * Uses querySelector/querySelectorAll to find matching elements,\n * then builds an accessibility tree for each match.\n * \n * @param rootElement - Root DOM element to search within\n * @param selector - CSS selector to match elements\n * @param sourceHash - Optional hash of source HTML for change detection\n * @returns Array of announcement models and warnings\n * @throws SelectorError if no elements match the selector\n */\nexport function buildAccessibilityTreeWithSelector(\n rootElement: Element,\n selector: string,\n sourceHash?: string\n): TreeBuildResult[] {\n const document = rootElement.ownerDocument;\n if (!document) {\n throw new SelectorError('Element has no owner document');\n }\n \n // Find all matching elements\n let matchingElements: Element[];\n try {\n // Check if rootElement itself matches\n if (rootElement.matches(selector)) {\n matchingElements = [rootElement];\n } else {\n // Query for matching descendants\n matchingElements = Array.from(rootElement.querySelectorAll(selector));\n }\n } catch (error) {\n throw new SelectorError(`Invalid CSS selector: \"${selector}\". ${error instanceof Error ? error.message : String(error)}`);\n }\n \n // Error if no matches found\n if (matchingElements.length === 0) {\n throw new SelectorError(`No elements match selector: \"${selector}\"`);\n }\n \n // Build accessibility tree for each matching element\n const results: TreeBuildResult[] = [];\n for (const element of matchingElements) {\n const result = buildAccessibilityTree(element, sourceHash);\n results.push(result);\n }\n \n return results;\n}\n\n/**\n * Recursively builds an accessible node from a DOM element.\n * \n * Checks hidden state first, then accessibility. If the element has no role,\n * transparent traversal is not done here (it's handled by processChildNode\n * in the parent's iteration). This function is only called for elements\n * that are known to be accessible.\n * \n * @param element - DOM element to build node from\n * @param warnings - Array to collect warnings\n * @returns Accessible node or null if element is hidden or not accessible\n */\nfunction buildNodeRecursive(\n element: Element,\n warnings: TreeBuildWarning[]\n): AccessibleNode | null {\n // Check hidden state first (before any extraction)\n if (isHidden(element)) {\n return null;\n }\n\n // Check if element should be included in accessibility tree\n if (!isAccessible(element)) {\n return null;\n }\n \n // Extract role\n const roleResult = computeRole(element);\n warnings.push(...roleResult.warnings.map(w => ({\n message: w.message,\n element: w.element,\n })));\n \n // If no role, element is not accessible\n if (!roleResult.role) {\n return null;\n }\n \n // Extract accessible name\n const nameResult = computeAccessibleName(element);\n warnings.push(...nameResult.warnings.map(w => ({\n message: w.message,\n element: w.element,\n })));\n \n // Extract accessible description\n const descResult = computeAccessibleDescription(element);\n warnings.push(...descResult.warnings.map(w => ({\n message: w.message,\n element: w.element,\n })));\n \n // Extract state\n const stateResult = extractState(element);\n warnings.push(...stateResult.warnings.map(w => ({\n message: w.message,\n element: w.element,\n })));\n \n // Extract value\n const valueResult = extractValue(element);\n warnings.push(...valueResult.warnings.map(w => ({\n message: w.message,\n element: w.element,\n })));\n \n // Extract focus info\n const focusInfo = extractFocusInfo(element);\n \n // Build children from childNodes (includes Text nodes)\n const children: AccessibleNode[] = [];\n // Shadow DOM first\n if (element.shadowRoot) {\n for (const child of Array.from(element.shadowRoot.childNodes)) {\n processChildNode(child, children, warnings);\n }\n }\n // Light DOM\n for (const child of Array.from(element.childNodes)) {\n processChildNode(child, children, warnings);\n }\n \n // Create the accessible node\n const node: AccessibleNode = {\n role: roleResult.role,\n name: nameResult.name,\n ...(descResult.description && { description: descResult.description }),\n ...(valueResult.value && { value: valueResult.value }),\n state: stateResult.state,\n focus: focusInfo,\n children,\n };\n \n return node;\n}\n\n/**\n * Creates a generic container node when root element is not accessible.\n * \n * This ensures we always have a valid root node even if the root element\n * itself is not accessible (e.g., a plain div).\n * Uses childNodes and processChildNode for text node and transparent traversal support.\n * \n * @param rootElement - Root DOM element\n * @param warnings - Array to collect warnings\n * @returns Generic container node with accessible children\n */\nfunction createGenericContainer(\n rootElement: Element,\n warnings: TreeBuildWarning[]\n): AccessibleNode {\n // Build children from root element using childNodes\n const children: AccessibleNode[] = [];\n // Shadow DOM first\n if (rootElement.shadowRoot) {\n for (const child of Array.from(rootElement.shadowRoot.childNodes)) {\n processChildNode(child, children, warnings);\n }\n }\n // Light DOM\n for (const child of Array.from(rootElement.childNodes)) {\n processChildNode(child, children, warnings);\n }\n \n // Create a generic container\n return {\n role: 'generic',\n name: '',\n state: {},\n focus: {\n focusable: false,\n },\n children,\n };\n}\n","/**\n * Validation functions for the Canonical Announcement Model.\n */\n\nimport type {\n AccessibleNode,\n AccessibleRole,\n AccessibleState,\n AnnouncementModel,\n} from './types.js';\nimport { SUPPORTED_ROLES } from './types.js';\n\n/**\n * Validation error class.\n */\nexport class ValidationError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ValidationError';\n }\n}\n\n/**\n * Validates that a role is supported in V1.\n * \n * @param role - The role to validate\n * @returns true if valid\n * @throws ValidationError if invalid\n */\nexport function validateRole(role: string): role is AccessibleRole {\n if (!SUPPORTED_ROLES.includes(role as AccessibleRole)) {\n throw new ValidationError(\n `Invalid role: \"${role}\". Supported roles: ${SUPPORTED_ROLES.join(', ')}`\n );\n }\n return true;\n}\n\n/**\n * Validates accessible state constraints.\n * \n * @param state - The state object to validate\n * @throws ValidationError if invalid\n */\nexport function validateState(state: AccessibleState): void {\n // Validate level is in range 1-6 for headings\n if (state.level !== undefined) {\n if (!Number.isInteger(state.level) || state.level < 1 || state.level > 6) {\n throw new ValidationError(\n `Invalid heading level: ${state.level}. Must be an integer between 1 and 6.`\n );\n }\n }\n\n // Validate posinset is positive\n if (state.posinset !== undefined) {\n if (!Number.isInteger(state.posinset) || state.posinset < 1) {\n throw new ValidationError(\n `Invalid posinset: ${state.posinset}. Must be a positive integer.`\n );\n }\n }\n\n // Validate setsize is positive\n if (state.setsize !== undefined) {\n if (!Number.isInteger(state.setsize) || state.setsize < 1) {\n throw new ValidationError(\n `Invalid setsize: ${state.setsize}. Must be a positive integer.`\n );\n }\n }\n\n // Validate posinset <= setsize if both present\n if (\n state.posinset !== undefined &&\n state.setsize !== undefined &&\n state.posinset > state.setsize\n ) {\n throw new ValidationError(\n `Invalid set position: posinset (${state.posinset}) cannot exceed setsize (${state.setsize}).`\n );\n }\n\n // Validate checked is boolean or 'mixed'\n if (state.checked !== undefined) {\n if (typeof state.checked !== 'boolean' && state.checked !== 'mixed') {\n throw new ValidationError(\n `Invalid checked value: ${state.checked}. Must be boolean or 'mixed'.`\n );\n }\n }\n\n // Validate pressed is boolean or 'mixed'\n if (state.pressed !== undefined) {\n if (typeof state.pressed !== 'boolean' && state.pressed !== 'mixed') {\n throw new ValidationError(\n `Invalid pressed value: ${state.pressed}. Must be boolean or 'mixed'.`\n );\n }\n }\n\n // Validate current is valid enum value\n if (state.current !== undefined) {\n const validCurrentValues = ['page', 'step', 'location', 'date', 'time', 'true', false];\n if (!validCurrentValues.includes(state.current as any)) {\n throw new ValidationError(\n `Invalid current value: ${state.current}. Must be one of: ${validCurrentValues.join(', ')}`\n );\n }\n }\n}\n\n/**\n * Validates tree structure integrity (no cycles).\n * \n * @param node - The root node to validate\n * @param visited - Set of visited nodes (for cycle detection)\n * @throws ValidationError if cycles detected\n */\nexport function validateTreeStructure(\n node: AccessibleNode,\n visited: Set<AccessibleNode> = new Set()\n): void {\n // Check for cycles\n if (visited.has(node)) {\n throw new ValidationError(\n 'Circular reference detected in accessibility tree. Tree must be acyclic.'\n );\n }\n\n visited.add(node);\n\n // Validate role\n validateRole(node.role);\n\n // Validate state\n validateState(node.state);\n\n // Recursively validate children\n for (const child of node.children) {\n validateTreeStructure(child, new Set(visited));\n }\n}\n\n/**\n * Validates an entire AnnouncementModel.\n * \n * @param model - The model to validate\n * @throws ValidationError if invalid\n */\nexport function validateModel(model: AnnouncementModel): void {\n // Validate version\n if (!model.version || typeof model.version.major !== 'number' || typeof model.version.minor !== 'number') {\n throw new ValidationError('Invalid model version. Must have major and minor number fields.');\n }\n\n // Validate metadata\n if (!model.metadata || !model.metadata.extractedAt) {\n throw new ValidationError('Invalid metadata. Must have extractedAt timestamp.');\n }\n\n // Validate timestamp is ISO 8601\n const timestamp = new Date(model.metadata.extractedAt);\n if (isNaN(timestamp.getTime())) {\n throw new ValidationError(\n `Invalid extractedAt timestamp: ${model.metadata.extractedAt}. Must be ISO 8601 format.`\n );\n }\n\n // Validate root node and tree structure\n if (!model.root) {\n throw new ValidationError('Model must have a root node.');\n }\n\n validateTreeStructure(model.root);\n}\n","/**\n * JSON serialization and deserialization for the Canonical Announcement Model.\n * \n * Ensures deterministic output with consistent property ordering.\n */\n\nimport type { AnnouncementModel, AccessibleNode } from './types.js';\nimport { CURRENT_MODEL_VERSION } from './types.js';\nimport { validateModel } from './validation.js';\n\n/**\n * Serialization options.\n */\nexport interface SerializationOptions {\n /** Whether to pretty-print the JSON output */\n pretty?: boolean;\n \n /** Whether to validate the model before serialization */\n validate?: boolean;\n}\n\n/**\n * Deserialization options.\n */\nexport interface DeserializationOptions {\n /** Whether to validate the model after deserialization */\n validate?: boolean;\n}\n\n/**\n * Sorts object keys to ensure deterministic JSON output.\n * \n * @param obj - Object to sort\n * @returns New object with sorted keys\n */\nfunction sortObjectKeys<T extends Record<string, any>>(obj: T): T {\n if (obj === null || typeof obj !== 'object') {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map(sortObjectKeys) as any as T;\n }\n\n const sorted: Record<string, any> = {};\n const keys = Object.keys(obj).sort();\n\n for (const key of keys) {\n const value = obj[key];\n sorted[key] = typeof value === 'object' && value !== null \n ? sortObjectKeys(value) \n : value;\n }\n\n return sorted as T;\n}\n\n/**\n * Serializes an AnnouncementModel to JSON string.\n * \n * Produces deterministic output with consistent property ordering.\n * \n * @param model - The model to serialize\n * @param options - Serialization options\n * @returns JSON string representation\n * @throws ValidationError if validation is enabled and model is invalid\n */\nexport function serializeModel(\n model: AnnouncementModel,\n options: SerializationOptions = {}\n): string {\n const { pretty = false, validate = true } = options;\n\n // Validate model if requested\n if (validate) {\n validateModel(model);\n }\n\n // Sort keys for deterministic output\n const sorted = sortObjectKeys(model);\n\n // Serialize with optional pretty printing\n return pretty \n ? JSON.stringify(sorted, null, 2)\n : JSON.stringify(sorted);\n}\n\n/**\n * Deserializes a JSON string to an AnnouncementModel.\n * \n * @param json - JSON string to deserialize\n * @param options - Deserialization options\n * @returns Parsed AnnouncementModel\n * @throws SyntaxError if JSON is invalid\n * @throws ValidationError if validation is enabled and model is invalid\n */\nexport function deserializeModel(\n json: string,\n options: DeserializationOptions = {}\n): AnnouncementModel {\n const { validate = true } = options;\n\n // Parse JSON\n const model = JSON.parse(json) as AnnouncementModel;\n\n // Validate model if requested\n if (validate) {\n validateModel(model);\n }\n\n return model;\n}\n\n/**\n * Creates a new AnnouncementModel with current version and timestamp.\n * \n * @param root - Root accessible node\n * @param sourceHash - Optional hash of source HTML\n * @returns New AnnouncementModel\n */\nexport function createModel(\n root: AccessibleNode,\n sourceHash?: string\n): AnnouncementModel {\n return {\n version: { ...CURRENT_MODEL_VERSION },\n root,\n metadata: {\n extractedAt: new Date().toISOString(),\n ...(sourceHash && { sourceHash }),\n },\n };\n}\n\n/**\n * Compares two models for equality (deep comparison).\n * \n * @param a - First model\n * @param b - Second model\n * @returns true if models are equivalent\n */\nexport function modelsEqual(a: AnnouncementModel, b: AnnouncementModel): boolean {\n // Simple approach: serialize both and compare strings\n // This works because serialization is deterministic\n const jsonA = serializeModel(a, { validate: false });\n const jsonB = serializeModel(b, { validate: false });\n return jsonA === jsonB;\n}\n\n/**\n * Clones a model (deep copy).\n * \n * @param model - Model to clone\n * @returns Deep copy of the model\n */\nexport function cloneModel(model: AnnouncementModel): AnnouncementModel {\n const json = serializeModel(model, { validate: false });\n return deserializeModel(json, { validate: false });\n}\n","import pc from 'picocolors';\n\nexport interface ColorFunctions {\n // Semantic colors for audit report\n error: (s: string) => string;\n warning: (s: string) => string;\n info: (s: string) => string;\n success: (s: string) => string;\n heading: (s: string) => string;\n title: (s: string) => string;\n dim: (s: string) => string;\n\n // Semantic colors for screen reader output\n roleName: (s: string) => string;\n stateName: (s: string) => string;\n elementName: (s: string) => string;\n sectionHeader: (s: string) => string;\n description: (s: string) => string;\n\n // Utility\n bold: (s: string) => string;\n enabled: boolean;\n}\n\nconst identity = (s: string): string => s;\n\n/** Check if color output should be enabled for a given stream */\nexport function isColorEnabled(stream: { isTTY?: boolean }): boolean {\n return stream.isTTY === true;\n}\n\n/** Create a set of color functions, either active or passthrough */\nexport function createColors(enabled: boolean): ColorFunctions {\n if (!enabled) {\n return {\n error: identity,\n warning: identity,\n info: identity,\n success: identity,\n heading: identity,\n title: identity,\n dim: identity,\n roleName: identity,\n stateName: identity,\n elementName: identity,\n sectionHeader: identity,\n description: identity,\n bold: identity,\n enabled: false,\n };\n }\n\n return {\n error: pc.red,\n warning: pc.yellow,\n info: pc.blue,\n success: pc.green,\n heading: (s: string) => pc.bold(pc.cyan(s)),\n title: (s: string) => pc.bold(pc.cyan(s)),\n dim: pc.dim,\n roleName: pc.cyan,\n stateName: pc.yellow,\n elementName: (s: string) => pc.bold(pc.white(s)),\n sectionHeader: (s: string) => pc.bold(pc.white(s)),\n description: pc.dim,\n bold: pc.bold,\n enabled: true,\n };\n}\n","/**\n * NVDA screen reader announcement renderer.\n * \n * Generates heuristic announcement text approximating NVDA output.\n * This is NOT a perfect emulation - real NVDA behavior varies by version,\n * settings, and context. Use for development guidance only.\n */\n\nimport type { AccessibleNode, AnnouncementModel } from '../model/types.js';\nimport { createColors, type ColorFunctions } from '../cli/colors.js';\n\n/**\n * Renders an announcement model as NVDA-style announcement text.\n * \n * @param model - Announcement model to render\n * @param colorize - Whether to apply ANSI color codes to the output\n * @returns NVDA-style announcement text\n */\nexport function renderNVDA(model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const announcements: string[] = [];\n renderNodeNVDA(model.root, announcements, c);\n return announcements.join('\\n');\n}\n\n/**\n * Recursively renders a node and its children as NVDA announcements.\n * \n * @param node - Node to render\n * @param announcements - Array to collect announcement strings\n * @param c - Color functions for formatting\n */\nfunction renderNodeNVDA(node: AccessibleNode, announcements: string[], c: ColorFunctions): void {\n const announcement = formatNodeNVDA(node, c);\n if (announcement) {\n announcements.push(announcement);\n }\n \n // Recursively render children\n for (const child of node.children) {\n renderNodeNVDA(child, announcements, c);\n }\n}\n\n/**\n * Formats a single node as an NVDA announcement.\n * \n * @param node - Node to format\n * @param c - Color functions for formatting\n * @returns Formatted announcement string or empty string if node should not be announced\n */\nfunction formatNodeNVDA(node: AccessibleNode, c: ColorFunctions): string {\n const parts: string[] = [];\n \n // Add name (if present)\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n \n // Add role-specific formatting\n const roleText = formatRoleNVDA(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n \n // Add states\n const stateText = formatStatesNVDA(node);\n if (stateText) {\n parts.push(c.stateName(stateText));\n }\n \n // Add value (for form controls)\n if (node.value) {\n const valueText = node.value.text || String(node.value.current);\n if (valueText) {\n parts.push(valueText);\n }\n }\n \n // Add description (if present)\n if (node.description) {\n parts.push(c.description(node.description));\n }\n \n return parts.join(', ');\n}\n\n/**\n * Formats the role portion of an NVDA announcement.\n * \n * @param node - Node to format\n * @returns Role text or empty string\n */\nfunction formatRoleNVDA(node: AccessibleNode): string {\n const role = node.role;\n \n switch (role) {\n case 'button':\n return 'button';\n \n case 'link':\n return 'link';\n \n case 'heading':\n if (node.state.level) {\n return `heading level ${node.state.level}`;\n }\n return 'heading';\n \n case 'textbox':\n return 'edit';\n \n case 'checkbox':\n return 'checkbox';\n \n case 'radio':\n return 'radio button';\n \n case 'combobox':\n return 'combo box';\n \n case 'listbox':\n return 'list box';\n \n case 'option':\n return 'option';\n \n case 'list':\n return 'list';\n \n case 'listitem':\n return 'list item';\n \n case 'navigation':\n return 'navigation landmark';\n \n case 'main':\n return 'main landmark';\n \n case 'banner':\n return 'banner landmark';\n \n case 'contentinfo':\n return 'content information landmark';\n \n case 'region':\n return 'region landmark';\n \n case 'complementary':\n return 'complementary landmark';\n \n case 'form':\n return 'form landmark';\n \n case 'search':\n return 'search landmark';\n \n case 'img':\n return 'graphic';\n \n case 'article':\n return 'article';\n \n case 'generic':\n // Generic containers are typically not announced\n return '';\n \n case 'staticText':\n case 'paragraph':\n case 'cell':\n case 'term':\n case 'definition':\n case 'caption':\n return '';\n \n case 'blockquote':\n return 'block quote';\n \n case 'code':\n return 'code';\n \n case 'table':\n return 'table';\n \n case 'row':\n return 'row';\n \n case 'columnheader':\n return 'column header';\n \n case 'rowheader':\n return 'row header';\n \n case 'figure':\n return 'figure';\n \n case 'dialog':\n return 'dialog';\n \n case 'meter':\n return 'meter';\n \n case 'progressbar':\n return 'progress bar';\n \n case 'status':\n return 'status';\n \n case 'group':\n return node.name ? 'grouping' : '';\n \n case 'document':\n return 'document';\n \n case 'application':\n return 'embedded object';\n \n case 'separator':\n return 'separator';\n \n default:\n return role;\n }\n}\n\n/**\n * Formats the state portion of an NVDA announcement.\n * \n * @param node - Node to format\n * @returns State text or empty string\n */\nfunction formatStatesNVDA(node: AccessibleNode): string {\n const states: string[] = [];\n \n // Expanded/collapsed state\n if (node.state.expanded !== undefined) {\n states.push(node.state.expanded ? 'expanded' : 'collapsed');\n }\n \n // Checked state (checkbox/radio)\n if (node.state.checked !== undefined) {\n if (node.state.checked === 'mixed') {\n states.push('half checked');\n } else {\n states.push(node.state.checked ? 'checked' : 'not checked');\n }\n }\n \n // Pressed state (toggle button)\n if (node.state.pressed !== undefined) {\n if (node.state.pressed === 'mixed') {\n states.push('half pressed');\n } else {\n states.push(node.state.pressed ? 'pressed' : 'not pressed');\n }\n }\n \n // Selected state\n if (node.state.selected !== undefined) {\n states.push(node.state.selected ? 'selected' : 'not selected');\n }\n \n // Disabled state\n if (node.state.disabled) {\n states.push('unavailable');\n }\n \n // Invalid state\n if (node.state.invalid) {\n states.push('invalid entry');\n }\n \n // Required state\n if (node.state.required) {\n states.push('required');\n }\n \n // Read-only state\n if (node.state.readonly) {\n states.push('read only');\n }\n \n // Busy state\n if (node.state.busy) {\n states.push('busy');\n }\n \n // Current state\n if (node.state.current) {\n if (node.state.current === 'page') {\n states.push('current page');\n } else if (node.state.current === 'step') {\n states.push('current step');\n } else if (node.state.current === 'location') {\n states.push('current location');\n } else if (node.state.current === 'date') {\n states.push('current date');\n } else if (node.state.current === 'time') {\n states.push('current time');\n } else if (node.state.current === 'true') {\n states.push('current');\n }\n }\n \n // Grabbed state (drag and drop)\n if (node.state.grabbed !== undefined) {\n states.push(node.state.grabbed ? 'grabbed' : 'not grabbed');\n }\n \n return states.join(', ');\n}\n","/**\n * JAWS screen reader announcement renderer.\n * \n * Generates heuristic announcement text approximating JAWS output.\n * This is NOT a perfect emulation - real JAWS behavior varies by version,\n * settings, verbosity level, and context. Use for development guidance only.\n */\n\nimport type { AccessibleNode, AnnouncementModel } from '../model/types.js';\nimport { createColors, type ColorFunctions } from '../cli/colors.js';\n\n/**\n * Renders an announcement model as JAWS-style announcement text.\n * \n * @param model - Announcement model to render\n * @param colorize - Whether to apply ANSI color codes to the output\n * @returns JAWS-style announcement text\n */\nexport function renderJAWS(model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const announcements: string[] = [];\n renderNodeJAWS(model.root, announcements, c);\n return announcements.join('\\n');\n}\n\n/**\n * Recursively renders a node and its children as JAWS announcements.\n * \n * @param node - Node to render\n * @param announcements - Array to collect announcement strings\n * @param c - Color functions for formatting\n */\nfunction renderNodeJAWS(node: AccessibleNode, announcements: string[], c: ColorFunctions): void {\n const announcement = formatNodeJAWS(node, c);\n if (announcement) {\n announcements.push(announcement);\n }\n \n // Recursively render children\n for (const child of node.children) {\n renderNodeJAWS(child, announcements, c);\n }\n}\n\n/**\n * Formats a single node as a JAWS announcement.\n * \n * @param node - Node to format\n * @param c - Color functions for formatting\n * @returns Formatted announcement string or empty string if node should not be announced\n */\nfunction formatNodeJAWS(node: AccessibleNode, c: ColorFunctions): string {\n const parts: string[] = [];\n \n // Add name (if present)\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n \n // Add role-specific formatting\n const roleText = formatRoleJAWS(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n \n // Add states\n const stateText = formatStatesJAWS(node);\n if (stateText) {\n parts.push(c.stateName(stateText));\n }\n \n // Add value (for form controls)\n if (node.value) {\n const valueText = node.value.text || String(node.value.current);\n if (valueText) {\n parts.push(valueText);\n }\n }\n \n // Add description (if present)\n if (node.description) {\n parts.push(c.description(node.description));\n }\n \n return parts.join(', ');\n}\n\n/**\n * Formats the role portion of a JAWS announcement.\n * \n * @param node - Node to format\n * @returns Role text or empty string\n */\nfunction formatRoleJAWS(node: AccessibleNode): string {\n const role = node.role;\n \n switch (role) {\n case 'button':\n return 'button';\n \n case 'link':\n // JAWS uses \"clickable\" for links\n return 'clickable';\n \n case 'heading':\n if (node.state.level) {\n return `heading ${node.state.level}`;\n }\n return 'heading';\n \n case 'textbox':\n return 'edit';\n \n case 'checkbox':\n return 'check box';\n \n case 'radio':\n return 'radio button';\n \n case 'combobox':\n // JAWS uses \"combo box\" (two words)\n return 'combo box';\n \n case 'listbox':\n return 'list box';\n \n case 'option':\n return 'option';\n \n case 'list':\n return 'list';\n \n case 'listitem':\n return 'list item';\n \n case 'navigation':\n return 'navigation region';\n \n case 'main':\n return 'main region';\n \n case 'banner':\n return 'banner region';\n \n case 'contentinfo':\n return 'content information region';\n \n case 'region':\n return 'region';\n \n case 'img':\n return 'graphic';\n \n case 'article':\n return 'article';\n \n case 'complementary':\n return 'complementary region';\n \n case 'form':\n return 'form';\n \n case 'search':\n return 'search region';\n \n case 'generic':\n // Generic containers typically not announced\n return '';\n \n case 'staticText':\n case 'paragraph':\n case 'term':\n case 'definition':\n case 'caption':\n return '';\n \n case 'blockquote':\n return 'block quote';\n \n case 'code':\n return 'code';\n \n case 'table': {\n const rows = node.children.filter(c => c.role === 'row');\n const rowCount = rows.length;\n const colCount = rows.length > 0 ? rows[0].children.length : 0;\n return `table with ${rowCount} rows and ${colCount} columns`;\n }\n \n case 'row': {\n const pos = node.state.posinset ?? 0;\n return `row ${pos}`;\n }\n \n case 'cell': {\n const pos = node.state.posinset ?? 0;\n return `column ${pos}`;\n }\n \n case 'columnheader':\n return 'column header';\n \n case 'rowheader':\n return 'row header';\n \n case 'figure':\n return 'figure';\n \n case 'dialog':\n return 'dialog';\n \n case 'meter':\n return 'meter';\n \n case 'progressbar':\n return 'progress bar';\n \n case 'status':\n return 'status';\n \n case 'group':\n return node.name ? 'group' : '';\n \n case 'document':\n return 'frame';\n \n case 'application':\n return 'embedded object';\n \n case 'separator':\n return 'separator';\n \n default:\n return role;\n }\n}\n\n/**\n * Formats the state portion of a JAWS announcement.\n * \n * @param node - Node to format\n * @returns State text or empty string\n */\nfunction formatStatesJAWS(node: AccessibleNode): string {\n const states: string[] = [];\n \n // Expanded/collapsed\n if (node.state.expanded !== undefined) {\n states.push(node.state.expanded ? 'expanded' : 'collapsed');\n }\n \n // Checked state (checkbox, radio)\n if (node.state.checked !== undefined) {\n if (node.state.checked === 'mixed') {\n states.push('partially checked');\n } else if (node.state.checked) {\n states.push('checked');\n } else {\n states.push('not checked');\n }\n }\n \n // Pressed state (toggle button)\n if (node.state.pressed !== undefined) {\n if (node.state.pressed === 'mixed') {\n states.push('partially pressed');\n } else if (node.state.pressed) {\n states.push('pressed');\n } else {\n states.push('not pressed');\n }\n }\n \n // Selected state\n if (node.state.selected !== undefined) {\n states.push(node.state.selected ? 'selected' : 'not selected');\n }\n \n // Disabled state\n if (node.state.disabled) {\n states.push('unavailable');\n }\n \n // Invalid state\n if (node.state.invalid) {\n states.push('invalid entry');\n }\n \n // Required state\n if (node.state.required) {\n states.push('required');\n }\n \n // Read-only state\n if (node.state.readonly) {\n states.push('read only');\n }\n \n // Busy state\n if (node.state.busy) {\n states.push('busy');\n }\n \n // Current state\n if (node.state.current) {\n switch (node.state.current) {\n case 'page':\n states.push('current page');\n break;\n case 'step':\n states.push('current step');\n break;\n case 'location':\n states.push('current location');\n break;\n case 'date':\n states.push('current date');\n break;\n case 'time':\n states.push('current time');\n break;\n case 'true':\n states.push('current');\n break;\n }\n }\n \n // Grabbed state (drag and drop)\n if (node.state.grabbed !== undefined) {\n states.push(node.state.grabbed ? 'grabbed' : 'not grabbed');\n }\n \n return states.join(', ');\n}\n","/**\n * VoiceOver screen reader announcement renderer.\n * \n * Generates heuristic announcement text approximating VoiceOver output.\n * This is NOT a perfect emulation - real VoiceOver behavior varies by version,\n * settings, and context. Use for development guidance only.\n */\n\nimport type { AccessibleNode, AccessibleRole, AnnouncementModel } from '../model/types.js';\nimport { createColors, type ColorFunctions } from '../cli/colors.js';\n\n/**\n * Renders an announcement model as VoiceOver-style announcement text.\n * \n * @param model - Announcement model to render\n * @param colorize - Whether to apply ANSI color codes to the output\n * @returns VoiceOver-style announcement text\n */\nexport function renderVoiceOver(model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const announcements: string[] = [];\n renderNodeVoiceOver(model.root, announcements, c);\n return announcements.join('\\n');\n}\n\n/**\n * Recursively renders a node and its children as VoiceOver announcements.\n * \n * @param node - Node to render\n * @param announcements - Array to collect announcement strings\n * @param c - Color functions for formatting\n */\nfunction renderNodeVoiceOver(node: AccessibleNode, announcements: string[], c: ColorFunctions): void {\n const announcement = formatNodeVoiceOver(node, c);\n if (announcement) {\n announcements.push(announcement);\n }\n \n // Recursively render children\n for (const child of node.children) {\n renderNodeVoiceOver(child, announcements, c);\n }\n}\n\n/**\n * Formats a single node as a VoiceOver announcement.\n * \n * @param node - Node to format\n * @param c - Color functions for formatting\n * @returns Formatted announcement string or empty string if node should not be announced\n */\nfunction formatNodeVoiceOver(node: AccessibleNode, c: ColorFunctions): string {\n const parts: string[] = [];\n \n // VoiceOver often announces role before name for some elements\n const roleFirst = shouldAnnounceRoleFirst(node.role);\n \n if (roleFirst) {\n // Add role first\n const roleText = formatRoleVoiceOver(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n \n // Then name\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n } else {\n // Add name first\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n \n // Then role\n const roleText = formatRoleVoiceOver(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n }\n \n // Add states\n const stateText = formatStatesVoiceOver(node);\n if (stateText) {\n parts.push(c.stateName(stateText));\n }\n \n // Add value (for form controls)\n if (node.value) {\n const valueText = node.value.text || String(node.value.current);\n if (valueText) {\n parts.push(valueText);\n }\n }\n \n // Add description (if present)\n if (node.description) {\n parts.push(c.description(node.description));\n }\n \n return parts.join(', ');\n}\n\n/**\n * Determines if role should be announced before name.\n * \n * VoiceOver announces role first for headings and some landmarks.\n * \n * @param role - Role to check\n * @returns true if role should be announced first\n */\nfunction shouldAnnounceRoleFirst(role: AccessibleRole): boolean {\n return role === 'heading' || \n role === 'navigation' ||\n role === 'main' ||\n role === 'banner' ||\n role === 'contentinfo' ||\n role === 'complementary' ||\n role === 'region' ||\n role === 'form' ||\n role === 'search' ||\n role === 'blockquote' ||\n role === 'figure' ||\n role === 'dialog' ||\n role === 'group' ||\n role === 'document';\n}\n\n/**\n * Formats the role portion of a VoiceOver announcement.\n * \n * @param node - Node to format\n * @returns Role text or empty string\n */\nfunction formatRoleVoiceOver(node: AccessibleNode): string {\n const role = node.role;\n \n switch (role) {\n case 'button':\n return 'button';\n \n case 'link':\n return 'link';\n \n case 'heading':\n if (node.state.level) {\n return `heading level ${node.state.level}`;\n }\n return 'heading';\n \n case 'textbox':\n return 'edit text';\n \n case 'checkbox':\n return 'checkbox';\n \n case 'radio':\n return 'radio button';\n \n case 'combobox':\n return 'combo box';\n \n case 'listbox':\n return 'list box';\n \n case 'option':\n return 'option';\n \n case 'list':\n return 'list';\n \n case 'listitem':\n return 'item';\n \n case 'navigation':\n return 'navigation';\n \n case 'main':\n return 'main';\n \n case 'banner':\n return 'banner';\n \n case 'contentinfo':\n return 'content information';\n \n case 'region':\n return 'region';\n \n case 'complementary':\n return 'complementary';\n \n case 'form':\n return 'form';\n \n case 'search':\n return 'search';\n \n case 'img':\n return 'image';\n \n case 'article':\n return 'article';\n \n case 'generic':\n // Generic containers are typically not announced\n return '';\n \n case 'staticText':\n case 'paragraph':\n case 'cell':\n case 'term':\n case 'definition':\n case 'caption':\n return '';\n \n case 'blockquote':\n return 'blockquote';\n \n case 'code':\n return 'code';\n \n case 'table': {\n const rows = node.children.filter(c => c.role === 'row');\n const rowCount = rows.length;\n const colCount = rows.length > 0 ? rows[0].children.length : 0;\n return `table, ${rowCount} rows, ${colCount} columns`;\n }\n \n case 'row':\n return 'row';\n \n case 'columnheader':\n return 'column header';\n \n case 'rowheader':\n return 'row header';\n \n case 'figure':\n return 'figure';\n \n case 'dialog':\n return 'web dialog';\n \n case 'meter':\n return 'level indicator';\n \n case 'progressbar':\n return 'progress indicator';\n \n case 'status':\n return 'status';\n \n case 'group':\n return node.name ? 'group' : '';\n \n case 'document':\n return 'frame';\n \n case 'application':\n return 'embedded object';\n \n case 'separator':\n return 'separator';\n \n default:\n return role;\n }\n}\n\n/**\n * Formats the state portion of a VoiceOver announcement.\n * \n * @param node - Node to format\n * @returns State text or empty string\n */\nfunction formatStatesVoiceOver(node: AccessibleNode): string {\n const states: string[] = [];\n \n // Expanded/collapsed state\n if (node.state.expanded !== undefined) {\n states.push(node.state.expanded ? 'expanded' : 'collapsed');\n }\n \n // Checked state (checkbox/radio)\n if (node.state.checked !== undefined) {\n if (node.state.checked === 'mixed') {\n states.push('mixed');\n } else {\n states.push(node.state.checked ? 'checked' : 'unchecked');\n }\n }\n \n // Pressed state (toggle button)\n if (node.state.pressed !== undefined) {\n if (node.state.pressed === 'mixed') {\n states.push('mixed');\n } else {\n states.push(node.state.pressed ? 'pressed' : 'not pressed');\n }\n }\n \n // Selected state\n if (node.state.selected !== undefined) {\n states.push(node.state.selected ? 'selected' : 'unselected');\n }\n \n // Disabled state\n if (node.state.disabled) {\n states.push('dimmed');\n }\n \n // Invalid state\n if (node.state.invalid) {\n states.push('invalid data');\n }\n \n // Required state\n if (node.state.required) {\n states.push('required');\n }\n \n // Read-only state\n if (node.state.readonly) {\n states.push('read only');\n }\n \n // Busy state\n if (node.state.busy) {\n states.push('busy');\n }\n \n // Current state\n if (node.state.current) {\n if (node.state.current === 'page') {\n states.push('current page');\n } else if (node.state.current === 'step') {\n states.push('current step');\n } else if (node.state.current === 'location') {\n states.push('current location');\n } else if (node.state.current === 'date') {\n states.push('current date');\n } else if (node.state.current === 'time') {\n states.push('current time');\n } else if (node.state.current === 'true') {\n states.push('current');\n }\n }\n \n // Grabbed state (drag and drop)\n if (node.state.grabbed !== undefined) {\n states.push(node.state.grabbed ? 'grabbed' : 'not grabbed');\n }\n \n return states.join(', ');\n}\n","/**\n * Developer-friendly audit report renderer.\n * \n * Generates human-readable accessibility audit reports with:\n * - Landmark structure analysis\n * - Heading hierarchy validation\n * - Interactive element inventory\n * - Common accessibility issue detection\n * - Summary statistics\n */\n\nimport type { AccessibleNode, AccessibleRole, AnnouncementModel } from '../model/types.js';\nimport { createColors } from '../cli/colors.js';\n\n/**\n * Severity level for accessibility issues.\n */\nexport type IssueSeverity = 'error' | 'warning' | 'info';\n\n/**\n * Accessibility issue detected during audit.\n */\nexport interface AccessibilityIssue {\n severity: IssueSeverity;\n message: string;\n suggestion?: string;\n element?: {\n role: AccessibleRole;\n name: string;\n };\n}\n\n/**\n * Audit report statistics.\n */\nexport interface AuditStatistics {\n totalElements: number;\n roleDistribution: Record<string, number>;\n landmarkCount: number;\n headingCount: number;\n interactiveCount: number;\n focusableCount: number;\n statesUsed: Set<string>;\n}\n\n/**\n * Complete audit report.\n */\nexport interface AuditReport {\n statistics: AuditStatistics;\n landmarks: AccessibleNode[];\n headings: AccessibleNode[];\n interactiveElements: AccessibleNode[];\n issues: AccessibilityIssue[];\n}\n\n/**\n * Renders an announcement model as a developer-friendly audit report.\n * \n * @param model - Announcement model to audit\n * @returns Formatted audit report text\n */\nexport function renderAuditReport(model: AnnouncementModel, colorize?: boolean): string {\n const report = generateAuditReport(model);\n return formatAuditReport(report, model, colorize);\n}\n\n/**\n * Generates audit report data from an announcement model.\n * \n * @param model - Announcement model to analyze\n * @returns Audit report data\n */\nexport function generateAuditReport(model: AnnouncementModel): AuditReport {\n const statistics: AuditStatistics = {\n totalElements: 0,\n roleDistribution: {},\n landmarkCount: 0,\n headingCount: 0,\n interactiveCount: 0,\n focusableCount: 0,\n statesUsed: new Set(),\n };\n \n const landmarks: AccessibleNode[] = [];\n const headings: AccessibleNode[] = [];\n const interactiveElements: AccessibleNode[] = [];\n const issues: AccessibilityIssue[] = [];\n \n // Collect data from tree\n collectAuditData(model.root, statistics, landmarks, headings, interactiveElements);\n \n // Detect issues\n detectLandmarkIssues(landmarks, issues);\n detectHeadingIssues(headings, issues);\n detectInteractiveIssues(interactiveElements, issues);\n \n return {\n statistics,\n landmarks,\n headings,\n interactiveElements,\n issues,\n };\n}\n\n/**\n * Recursively collects audit data from the accessibility tree.\n */\nfunction collectAuditData(\n node: AccessibleNode,\n statistics: AuditStatistics,\n landmarks: AccessibleNode[],\n headings: AccessibleNode[],\n interactiveElements: AccessibleNode[]\n): void {\n // Skip generic containers in statistics\n if (node.role !== 'generic') {\n statistics.totalElements++;\n \n // Update role distribution\n statistics.roleDistribution[node.role] = (statistics.roleDistribution[node.role] || 0) + 1;\n \n // Collect landmarks\n if (isLandmark(node.role)) {\n statistics.landmarkCount++;\n landmarks.push(node);\n }\n \n // Collect headings\n if (node.role === 'heading') {\n statistics.headingCount++;\n headings.push(node);\n }\n \n // Collect interactive elements\n if (isInteractive(node.role)) {\n statistics.interactiveCount++;\n interactiveElements.push(node);\n }\n \n // Count focusable elements\n if (node.focus.focusable) {\n statistics.focusableCount++;\n }\n \n // Collect states used\n Object.keys(node.state).forEach(state => {\n if (node.state[state as keyof typeof node.state] !== undefined) {\n statistics.statesUsed.add(state);\n }\n });\n }\n \n // Recurse through children\n for (const child of node.children) {\n collectAuditData(child, statistics, landmarks, headings, interactiveElements);\n }\n}\n\n/**\n * Checks if a role is a landmark.\n */\nfunction isLandmark(role: AccessibleRole): boolean {\n return [\n 'navigation',\n 'main',\n 'banner',\n 'contentinfo',\n 'region',\n 'complementary',\n 'form',\n 'search',\n ].includes(role);\n}\n\n/**\n * Checks if a role is interactive.\n */\nfunction isInteractive(role: AccessibleRole): boolean {\n return [\n 'button',\n 'link',\n 'textbox',\n 'checkbox',\n 'radio',\n 'combobox',\n 'listbox',\n 'option',\n ].includes(role);\n}\n\n/**\n * Detects issues with landmarks.\n */\nfunction detectLandmarkIssues(landmarks: AccessibleNode[], issues: AccessibilityIssue[]): void {\n if (landmarks.length === 0) {\n issues.push({\n severity: 'info',\n message: 'No landmarks found',\n suggestion: 'Consider adding semantic landmarks (main, nav, aside, etc.)',\n });\n }\n \n // Check for unnamed landmarks\n landmarks.forEach(landmark => {\n if (!landmark.name && ['navigation', 'region', 'complementary', 'form'].includes(landmark.role)) {\n issues.push({\n severity: 'warning',\n message: `${landmark.role} landmark has no accessible name`,\n suggestion: `Add aria-label=\"${landmark.role === 'navigation' ? 'Main navigation' : 'Descriptive name'}\" to the ${landmark.role} element`,\n element: {\n role: landmark.role,\n name: landmark.name,\n },\n });\n }\n });\n \n // Check for duplicate landmark roles without distinguishing names\n const landmarksByRole = new Map<string, AccessibleNode[]>();\n landmarks.forEach(landmark => {\n if (!landmarksByRole.has(landmark.role)) {\n landmarksByRole.set(landmark.role, []);\n }\n landmarksByRole.get(landmark.role)!.push(landmark);\n });\n \n landmarksByRole.forEach((nodes, role) => {\n if (nodes.length > 1) {\n const allUnnamed = nodes.every(n => !n.name);\n const allSameName = nodes.every(n => n.name === nodes[0].name);\n \n if (allUnnamed || allSameName) {\n issues.push({\n severity: 'warning',\n message: `Multiple ${role} landmarks without distinguishing names`,\n suggestion: `Add unique aria-label attributes to distinguish between ${role} landmarks`,\n });\n }\n }\n });\n}\n\n/**\n * Detects issues with heading hierarchy.\n */\nfunction detectHeadingIssues(headings: AccessibleNode[], issues: AccessibilityIssue[]): void {\n if (headings.length === 0) {\n return;\n }\n \n // Check if first heading is h1\n const firstHeading = headings[0];\n if (firstHeading.state.level && firstHeading.state.level !== 1) {\n issues.push({\n severity: 'error',\n message: `First heading is h${firstHeading.state.level} (should be h1)`,\n suggestion: `Change <h${firstHeading.state.level}> to <h1> or add h1 before it`,\n element: {\n role: firstHeading.role,\n name: firstHeading.name,\n },\n });\n }\n \n // Check for skipped levels\n for (let i = 1; i < headings.length; i++) {\n const prevLevel = headings[i - 1].state.level || 1;\n const currLevel = headings[i].state.level || 1;\n \n if (currLevel > prevLevel + 1) {\n issues.push({\n severity: 'error',\n message: `Heading hierarchy violation: h${prevLevel} followed by h${currLevel} (skipped h${prevLevel + 1})`,\n suggestion: `Change h${currLevel} to h${prevLevel + 1} or add intermediate heading levels`,\n element: {\n role: headings[i].role,\n name: headings[i].name,\n },\n });\n }\n }\n}\n\n/**\n * Detects issues with interactive elements.\n */\nfunction detectInteractiveIssues(elements: AccessibleNode[], issues: AccessibilityIssue[]): void {\n elements.forEach(element => {\n // Check for missing names\n if (!element.name) {\n issues.push({\n severity: 'error',\n message: `${element.role} has no accessible name`,\n suggestion: element.role === 'button' \n ? 'Add text content or aria-label to button'\n : element.role === 'link'\n ? 'Add text content or aria-label to link'\n : `Add aria-label to ${element.role}`,\n element: {\n role: element.role,\n name: element.name,\n },\n });\n }\n \n // Check for form inputs without labels\n if (element.role === 'textbox' && !element.name) {\n issues.push({\n severity: 'error',\n message: 'Input has no associated label',\n suggestion: 'Add <label> element or aria-label attribute',\n element: {\n role: element.role,\n name: element.name,\n },\n });\n }\n });\n}\n\n/**\n * Formats audit report as human-readable text.\n */\nfunction formatAuditReport(report: AuditReport, model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const lines: string[] = [];\n \n // Header\n lines.push(c.title('╔══════════════════════════════════════════════════════════════════════════════╗'));\n lines.push(c.title('║ ACCESSIBILITY AUDIT REPORT ║'));\n lines.push(c.title('╚══════════════════════════════════════════════════════════════════════════════╝'));\n lines.push('');\n lines.push(c.dim(`Analyzed: ${model.metadata.extractedAt}`));\n lines.push('');\n \n // Landmark structure\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.heading('📍 LANDMARK STRUCTURE'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n \n if (report.landmarks.length === 0) {\n lines.push(c.error('✗ No landmarks found'));\n } else {\n lines.push(c.success(`✓ ${report.landmarks.length} landmark(s) found`));\n lines.push('');\n report.landmarks.forEach(landmark => {\n const name = landmark.name ? `\"${landmark.name}\"` : '(unnamed)';\n lines.push(`${landmark.role} ${name}`);\n });\n }\n lines.push('');\n \n // Heading hierarchy\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.heading('📑 HEADING HIERARCHY'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n \n if (report.headings.length === 0) {\n lines.push(c.info('ℹ No headings found'));\n } else {\n const hasHierarchyIssues = report.issues.some(i => \n i.message.includes('heading') || i.message.includes('h1') || i.message.includes('h2')\n );\n lines.push(`${hasHierarchyIssues ? c.error('✗') : c.success('✓')} ${report.headings.length} heading(s) found ${hasHierarchyIssues ? '(HIERARCHY VIOLATION)' : '(proper hierarchy)'}`);\n lines.push('');\n \n report.headings.forEach(heading => {\n const level = heading.state.level || 1;\n const indent = ' '.repeat(level - 1);\n lines.push(`${indent}h${level} \"${heading.name}\"`);\n });\n }\n lines.push('');\n \n // Interactive elements\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.heading('🎯 INTERACTIVE ELEMENTS'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n \n if (report.interactiveElements.length === 0) {\n lines.push(c.info('ℹ No interactive elements found'));\n } else {\n lines.push(c.success(`✓ ${report.interactiveElements.length} interactive element(s) found`));\n lines.push('');\n \n // Group by role\n const byRole = new Map<string, AccessibleNode[]>();\n report.interactiveElements.forEach(el => {\n if (!byRole.has(el.role)) {\n byRole.set(el.role, []);\n }\n byRole.get(el.role)!.push(el);\n });\n \n byRole.forEach((elements, role) => {\n lines.push(`${role}s (${elements.length}):`);\n elements.forEach(el => {\n const name = el.name ? `\"${el.name}\"` : '(unnamed)';\n const states = Object.keys(el.state).filter(k => el.state[k as keyof typeof el.state] !== undefined);\n const stateStr = states.length > 0 ? ` [${states.join(', ')}]` : '';\n lines.push(` • ${name}${stateStr}`);\n });\n });\n }\n lines.push('');\n \n // Summary statistics\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.heading('📊 SUMMARY STATISTICS'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n lines.push(`Total accessible elements: ${report.statistics.totalElements}`);\n lines.push('');\n lines.push('Role distribution:');\n Object.entries(report.statistics.roleDistribution)\n .sort((a, b) => b[1] - a[1])\n .forEach(([role, count]) => {\n lines.push(c.dim(` • ${role}: ${count}`));\n });\n lines.push('');\n lines.push(c.dim(`Focusable elements: ${report.statistics.focusableCount}`));\n lines.push('');\n \n // Issues\n if (report.issues.length > 0) {\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.heading('⚠️ ACCESSIBILITY ISSUES'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n \n const errors = report.issues.filter(i => i.severity === 'error');\n const warnings = report.issues.filter(i => i.severity === 'warning');\n const infos = report.issues.filter(i => i.severity === 'info');\n \n if (errors.length > 0) {\n lines.push(c.error(`✗ Error (${errors.length}):`));\n errors.forEach(issue => {\n lines.push(c.error(` • ${issue.message}`));\n if (issue.suggestion) {\n lines.push(` → ${issue.suggestion}`);\n }\n });\n lines.push('');\n }\n \n if (warnings.length > 0) {\n lines.push(c.warning(`⚠ Warning (${warnings.length}):`));\n warnings.forEach(issue => {\n lines.push(c.warning(` • ${issue.message}`));\n if (issue.suggestion) {\n lines.push(` → ${issue.suggestion}`);\n }\n });\n lines.push('');\n }\n \n if (infos.length > 0) {\n lines.push(c.info(`ℹ Info (${infos.length}):`));\n infos.forEach(issue => {\n lines.push(c.info(` • ${issue.message}`));\n if (issue.suggestion) {\n lines.push(` → ${issue.suggestion}`);\n }\n });\n lines.push('');\n }\n }\n \n // Overall assessment\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push(c.success('✅ OVERALL ASSESSMENT'));\n lines.push('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━');\n lines.push('');\n \n const errorCount = report.issues.filter(i => i.severity === 'error').length;\n const warningCount = report.issues.filter(i => i.severity === 'warning').length;\n \n if (errorCount === 0 && warningCount === 0) {\n lines.push(c.success('Excellent! No critical issues found.'));\n } else if (errorCount > 0) {\n lines.push(`Critical accessibility issues found:`);\n lines.push(c.error(` ✗ ${errorCount} error(s)`));\n if (warningCount > 0) {\n lines.push(c.warning(` ⚠ ${warningCount} warning(s)`));\n }\n lines.push('');\n lines.push('Recommendation: Address errors before deployment');\n } else {\n lines.push(`Good structure with minor improvements needed:`);\n lines.push(c.warning(` ⚠ ${warningCount} warning(s)`));\n }\n \n return lines.join('\\n');\n}\n","/**\n * Semantic diff algorithm for accessibility trees.\n * \n * Compares two accessibility trees and identifies:\n * - Added nodes (present in new tree, not in old)\n * - Removed nodes (present in old tree, not in new)\n * - Changed nodes (same path, different properties)\n */\n\nimport type { AccessibleNode, AccessibleState, AccessibleValue, FocusInfo } from '../model/types.js';\nimport type { SemanticDiff, NodeChange, PropertyChange, NodePath } from './types.js';\n\n/**\n * Compare two accessibility trees and generate a semantic diff.\n * \n * @param oldTree - The original accessibility tree\n * @param newTree - The updated accessibility tree\n * @returns Semantic diff with all detected changes\n */\nexport function diffAccessibilityTrees(\n oldTree: AccessibleNode,\n newTree: AccessibleNode\n): SemanticDiff {\n const changes: NodeChange[] = [];\n \n // Build maps of path -> node for both trees\n const oldNodes = buildNodeMap(oldTree, 'root');\n const newNodes = buildNodeMap(newTree, 'root');\n \n // Find removed nodes (in old but not in new)\n for (const [path, node] of oldNodes) {\n if (!newNodes.has(path)) {\n changes.push({\n type: 'removed',\n path,\n node,\n });\n }\n }\n \n // Find added nodes (in new but not in old)\n for (const [path, node] of newNodes) {\n if (!oldNodes.has(path)) {\n changes.push({\n type: 'added',\n path,\n node,\n });\n }\n }\n \n // Find changed nodes (in both but with different properties)\n for (const [path, oldNode] of oldNodes) {\n const newNode = newNodes.get(path);\n if (newNode) {\n const propertyChanges = compareNodes(oldNode, newNode);\n if (propertyChanges.length > 0) {\n changes.push({\n type: 'changed',\n path,\n changes: propertyChanges,\n });\n }\n }\n }\n \n // Sort changes by path for deterministic output\n changes.sort((a, b) => a.path.localeCompare(b.path));\n \n // Calculate summary statistics\n const summary = {\n added: changes.filter(c => c.type === 'added').length,\n removed: changes.filter(c => c.type === 'removed').length,\n changed: changes.filter(c => c.type === 'changed').length,\n total: changes.length,\n };\n \n return { changes, summary };\n}\n\n/**\n * Build a map of path -> node for a tree.\n * \n * @param node - Root node of the tree\n * @param path - Current path (starts with 'root')\n * @returns Map of paths to nodes\n */\nfunction buildNodeMap(\n node: AccessibleNode,\n path: NodePath\n): Map<NodePath, AccessibleNode> {\n const map = new Map<NodePath, AccessibleNode>();\n \n // Add current node\n map.set(path, node);\n \n // Recursively add children\n node.children.forEach((child, index) => {\n const childPath = `${path}.children[${index}]`;\n const childMap = buildNodeMap(child, childPath);\n for (const [childPath, childNode] of childMap) {\n map.set(childPath, childNode);\n }\n });\n \n return map;\n}\n\n/**\n * Compare two nodes and identify property changes.\n * \n * @param oldNode - Original node\n * @param newNode - Updated node\n * @returns Array of property changes\n */\nfunction compareNodes(\n oldNode: AccessibleNode,\n newNode: AccessibleNode\n): PropertyChange[] {\n const changes: PropertyChange[] = [];\n \n // Compare role\n if (oldNode.role !== newNode.role) {\n changes.push({\n property: 'role',\n oldValue: oldNode.role,\n newValue: newNode.role,\n });\n }\n \n // Compare name\n if (oldNode.name !== newNode.name) {\n changes.push({\n property: 'name',\n oldValue: oldNode.name,\n newValue: newNode.name,\n });\n }\n \n // Compare description\n if (oldNode.description !== newNode.description) {\n changes.push({\n property: 'description',\n oldValue: oldNode.description,\n newValue: newNode.description,\n });\n }\n \n // Compare value\n if (!valuesEqual(oldNode.value, newNode.value)) {\n changes.push({\n property: 'value',\n oldValue: oldNode.value,\n newValue: newNode.value,\n });\n }\n \n // Compare state\n if (!statesEqual(oldNode.state, newNode.state)) {\n changes.push({\n property: 'state',\n oldValue: oldNode.state,\n newValue: newNode.state,\n });\n }\n \n // Compare focus\n if (!focusEqual(oldNode.focus, newNode.focus)) {\n changes.push({\n property: 'focus',\n oldValue: oldNode.focus,\n newValue: newNode.focus,\n });\n }\n \n return changes;\n}\n\n/**\n * Compare two AccessibleValue objects for equality.\n */\nfunction valuesEqual(\n a: AccessibleValue | undefined,\n b: AccessibleValue | undefined\n): boolean {\n if (a === undefined && b === undefined) return true;\n if (a === undefined || b === undefined) return false;\n \n return (\n a.current === b.current &&\n a.min === b.min &&\n a.max === b.max &&\n a.text === b.text\n );\n}\n\n/**\n * Compare two AccessibleState objects for equality.\n */\nfunction statesEqual(\n a: AccessibleState,\n b: AccessibleState\n): boolean {\n // Get all unique keys from both states\n const keys = new Set([...Object.keys(a), ...Object.keys(b)]);\n \n for (const key of keys) {\n const aValue = a[key as keyof AccessibleState];\n const bValue = b[key as keyof AccessibleState];\n \n if (aValue !== bValue) {\n return false;\n }\n }\n \n return true;\n}\n\n/**\n * Compare two FocusInfo objects for equality.\n */\nfunction focusEqual(\n a: FocusInfo,\n b: FocusInfo\n): boolean {\n return (\n a.focusable === b.focusable &&\n a.tabindex === b.tabindex\n );\n}\n\n/**\n * Generate a human-readable description of a change.\n * \n * @param change - The change to describe\n * @returns Human-readable description\n */\nexport function describeChange(change: NodeChange): string {\n switch (change.type) {\n case 'added':\n return `Added ${change.node?.role} \"${change.node?.name}\" at ${change.path}`;\n \n case 'removed':\n return `Removed ${change.node?.role} \"${change.node?.name}\" from ${change.path}`;\n \n case 'changed': {\n const descriptions = change.changes?.map(pc => {\n const oldVal = formatValue(pc.oldValue);\n const newVal = formatValue(pc.newValue);\n return `${pc.property}: ${oldVal} → ${newVal}`;\n }) || [];\n return `Changed at ${change.path}: ${descriptions.join(', ')}`;\n }\n \n default:\n return `Unknown change at ${change.path}`;\n }\n}\n\n/**\n * Format a value for display in change descriptions.\n */\nfunction formatValue(value: unknown): string {\n if (value === undefined) return 'undefined';\n if (value === null) return 'null';\n if (typeof value === 'string') return `\"${value}\"`;\n if (typeof value === 'object') return JSON.stringify(value);\n return String(value);\n}\n","/**\n * Formatting utilities for semantic diff output.\n * \n * Provides JSON and human-readable text formatting for diffs.\n */\n\nimport type { SemanticDiff, PropertyChange } from './types.js';\n\n/**\n * Format a semantic diff as pretty-printed JSON.\n * \n * @param diff - The semantic diff to format\n * @returns JSON string with 2-space indentation\n */\nexport function formatDiffAsJSON(diff: SemanticDiff): string {\n return JSON.stringify(diff, null, 2);\n}\n\n/**\n * Format a semantic diff as human-readable text.\n * \n * @param diff - The semantic diff to format\n * @returns Multi-line text description of changes\n */\nexport function formatDiffAsText(diff: SemanticDiff): string {\n const lines: string[] = [];\n \n // Summary header\n lines.push('=== Accessibility Tree Diff ===');\n lines.push('');\n lines.push(`Total changes: ${diff.summary.total}`);\n lines.push(` Added: ${diff.summary.added}`);\n lines.push(` Removed: ${diff.summary.removed}`);\n lines.push(` Changed: ${diff.summary.changed}`);\n lines.push('');\n \n if (diff.changes.length === 0) {\n lines.push('No changes detected.');\n return lines.join('\\n');\n }\n \n // Group changes by type\n const added = diff.changes.filter(c => c.type === 'added');\n const removed = diff.changes.filter(c => c.type === 'removed');\n const changed = diff.changes.filter(c => c.type === 'changed');\n \n // Added nodes\n if (added.length > 0) {\n lines.push('--- Added Nodes ---');\n for (const change of added) {\n lines.push(`+ ${change.path}`);\n lines.push(` Role: ${change.node?.role}`);\n lines.push(` Name: \"${change.node?.name}\"`);\n if (change.node?.description) {\n lines.push(` Description: \"${change.node.description}\"`);\n }\n lines.push('');\n }\n }\n \n // Removed nodes\n if (removed.length > 0) {\n lines.push('--- Removed Nodes ---');\n for (const change of removed) {\n lines.push(`- ${change.path}`);\n lines.push(` Role: ${change.node?.role}`);\n lines.push(` Name: \"${change.node?.name}\"`);\n if (change.node?.description) {\n lines.push(` Description: \"${change.node.description}\"`);\n }\n lines.push('');\n }\n }\n \n // Changed nodes\n if (changed.length > 0) {\n lines.push('--- Changed Nodes ---');\n for (const change of changed) {\n lines.push(`~ ${change.path}`);\n if (change.changes) {\n for (const propChange of change.changes) {\n lines.push(` ${formatPropertyChange(propChange)}`);\n }\n }\n lines.push('');\n }\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Format a single property change as text.\n */\nfunction formatPropertyChange(change: PropertyChange): string {\n const oldVal = formatValue(change.oldValue);\n const newVal = formatValue(change.newValue);\n return `${change.property}: ${oldVal} → ${newVal}`;\n}\n\n/**\n * Format a value for display.\n */\nfunction formatValue(value: unknown): string {\n if (value === undefined) return 'undefined';\n if (value === null) return 'null';\n if (typeof value === 'string') return `\"${value}\"`;\n if (typeof value === 'object') {\n // For objects, show a compact representation\n const json = JSON.stringify(value);\n if (json.length > 50) {\n return json.substring(0, 47) + '...';\n }\n return json;\n }\n return String(value);\n}\n\n/**\n * Format a semantic diff for CI/CD tools (GitHub Actions, GitLab CI, etc.).\n * \n * Uses a format that's easy to parse and diff-friendly.\n * \n * @param diff - The semantic diff to format\n * @returns CI-friendly text output\n */\nexport function formatDiffForCI(diff: SemanticDiff): string {\n const lines: string[] = [];\n \n // Machine-readable summary line\n lines.push(`DIFF_SUMMARY: added=${diff.summary.added} removed=${diff.summary.removed} changed=${diff.summary.changed} total=${diff.summary.total}`);\n lines.push('');\n \n // One line per change for easy parsing\n for (const change of diff.changes) {\n switch (change.type) {\n case 'added':\n lines.push(`ADDED: ${change.path} | role=${change.node?.role} | name=\"${change.node?.name}\"`);\n break;\n \n case 'removed':\n lines.push(`REMOVED: ${change.path} | role=${change.node?.role} | name=\"${change.node?.name}\"`);\n break;\n \n case 'changed':\n const props = change.changes?.map(pc => \n `${pc.property}:${formatValue(pc.oldValue)}->${formatValue(pc.newValue)}`\n ).join(' | ') || '';\n lines.push(`CHANGED: ${change.path} | ${props}`);\n break;\n }\n }\n \n return lines.join('\\n');\n}\n\n/**\n * Check if a diff represents a regression (accessibility got worse).\n * \n * Heuristics:\n * - Removed nodes with important roles (button, link, heading, etc.)\n * - Changed nodes that lost accessible names\n * - Changed nodes that became disabled or hidden\n * \n * @param diff - The semantic diff to analyze\n * @returns True if potential regression detected\n */\nexport function hasAccessibilityRegression(diff: SemanticDiff): boolean {\n const importantRoles = new Set([\n 'button', 'link', 'heading', 'textbox', 'checkbox', 'radio',\n 'navigation', 'main', 'banner', 'contentinfo', 'form', 'search'\n ]);\n \n // Check for removed important nodes\n for (const change of diff.changes) {\n if (change.type === 'removed' && change.node?.role && importantRoles.has(change.node.role)) {\n return true;\n }\n \n // Check for nodes that lost their accessible name\n if (change.type === 'changed' && change.changes) {\n for (const propChange of change.changes) {\n if (propChange.property === 'name') {\n const oldName = propChange.oldValue as string;\n const newName = propChange.newValue as string;\n if (oldName && !newName) {\n return true;\n }\n }\n \n // Check for nodes that became hidden or disabled\n if (propChange.property === 'state') {\n const oldState = propChange.oldValue as any;\n const newState = propChange.newValue as any;\n if (!oldState?.hidden && newState?.hidden) {\n return true;\n }\n if (!oldState?.disabled && newState?.disabled) {\n return true;\n }\n }\n }\n }\n }\n \n return false;\n}\n","/**\n * CLI orchestration - wires all components together.\n */\n\nimport { parseHTML } from '../parser/index.js';\nimport { buildAccessibilityTree, buildAccessibilityTreeWithSelector } from '../extractor/index.js';\nimport { serializeModel, deserializeModel, modelsEqual } from '../model/serialization.js';\nimport { renderNVDA } from '../renderer/nvda-renderer.js';\nimport { renderJAWS } from '../renderer/jaws-renderer.js';\nimport { renderVoiceOver } from '../renderer/voiceover-renderer.js';\nimport { renderAuditReport } from '../renderer/audit-renderer.js';\nimport { diffAccessibilityTrees, formatDiffAsJSON, formatDiffAsText } from '../diff/index.js';\nimport { isColorEnabled, createColors } from './colors.js';\nimport type { CLIOptions } from './options.js';\nimport type { AnnouncementModel } from '../model/types.js';\n\nexport interface ProcessResult {\n /** Output content to write */\n output: string;\n \n /** Exit code */\n exitCode: number;\n \n /** Warnings encountered during processing */\n warnings: string[];\n}\n\nexport interface BatchResult {\n /** File path that was processed */\n filePath: string;\n \n /** Whether processing succeeded */\n success: boolean;\n \n /** Output content (if successful) */\n output?: string;\n \n /** Error message (if failed) */\n error?: string;\n \n /** Warnings encountered */\n warnings: string[];\n}\n\nexport interface BatchProcessResult {\n /** Results for each file */\n results: BatchResult[];\n \n /** Combined output */\n output: string;\n \n /** Exit code (0 if all succeeded, 2 if any failed) */\n exitCode: number;\n \n /** All warnings */\n warnings: string[];\n}\n\n/**\n * Processes HTML input and generates output based on options.\n * \n * @param html - HTML content to process\n * @param options - CLI options\n * @param diffHTML - Optional second HTML for diff mode\n * @returns Process result with output and exit code\n */\nexport function processHTML(\n html: string,\n options: CLIOptions,\n diffHTML?: string\n): ProcessResult {\n const warnings: string[] = [];\n \n // Determine whether to colorize output:\n // Colors only when stdout is a TTY, format is not JSON, and output is not going to a file\n const colorize = isColorEnabled(process.stdout) && options.format !== 'json' && !options.output;\n \n try {\n // Handle diff mode\n if (options.diff && diffHTML) {\n return processDiff(html, diffHTML, options, warnings, colorize);\n }\n \n // Handle validation mode\n if (options.validate) {\n return processValidation(html, options, warnings);\n }\n \n // Normal processing mode\n return processNormal(html, options, warnings, colorize);\n } catch (error) {\n if (error instanceof Error) {\n return {\n output: `Error: ${error.message}`,\n exitCode: 2, // Content error\n warnings,\n };\n }\n throw error;\n }\n}\n\n/**\n * Processes HTML in normal mode (extract and render).\n */\nfunction processNormal(\n html: string,\n options: CLIOptions,\n warnings: string[],\n colorize: boolean\n): ProcessResult {\n // Parse HTML\n const doc = parseHTML(html);\n \n // Collect warnings from parser\n if (doc.warnings.length > 0) {\n warnings.push(...doc.warnings.map(w => w.message));\n }\n \n // Build accessibility tree\n let model: AnnouncementModel;\n \n if (options.selector) {\n // Use selector filtering\n const results = buildAccessibilityTreeWithSelector(doc.document.body, options.selector);\n \n if (results.length === 0) {\n return {\n output: `Error: No elements match selector: ${options.selector}`,\n exitCode: 2,\n warnings,\n };\n }\n \n // Use first matching element\n model = results[0].model;\n \n // Collect warnings\n for (const result of results) {\n if (result.warnings.length > 0) {\n warnings.push(...result.warnings.map(w => w.message));\n }\n }\n } else {\n // Build tree from body\n const result = buildAccessibilityTree(doc.document.body);\n model = result.model;\n \n if (result.warnings.length > 0) {\n warnings.push(...result.warnings.map(w => w.message));\n }\n }\n \n // Generate output based on format\n const output = formatOutput(model, options, colorize);\n \n return {\n output,\n exitCode: 0,\n warnings,\n };\n}\n\n/**\n * Processes HTML in diff mode.\n */\nfunction processDiff(\n html1: string,\n html2: string,\n options: CLIOptions,\n warnings: string[],\n _colorize: boolean\n): ProcessResult {\n // Parse both HTML files\n const doc1 = parseHTML(html1);\n const doc2 = parseHTML(html2);\n \n // Collect warnings\n warnings.push(...doc1.warnings.map(w => w.message), ...doc2.warnings.map(w => w.message));\n \n // Build accessibility trees\n const result1 = buildAccessibilityTree(doc1.document.body);\n const result2 = buildAccessibilityTree(doc2.document.body);\n \n warnings.push(...result1.warnings.map(w => w.message), ...result2.warnings.map(w => w.message));\n \n // Compute diff\n const diff = diffAccessibilityTrees(result1.model.root, result2.model.root);\n \n // Format diff output\n let output: string;\n if (options.format === 'json') {\n output = formatDiffAsJSON(diff);\n } else {\n output = formatDiffAsText(diff);\n }\n \n return {\n output,\n exitCode: 0,\n warnings,\n };\n}\n\n/**\n * Processes HTML in validation mode.\n */\nfunction processValidation(\n html: string,\n _options: CLIOptions,\n warnings: string[]\n): ProcessResult {\n // Parse and extract\n const doc = parseHTML(html);\n warnings.push(...doc.warnings.map(w => w.message));\n \n const result = buildAccessibilityTree(doc.document.body);\n warnings.push(...result.warnings.map(w => w.message));\n \n const model = result.model;\n \n // Serialize\n const serialized = serializeModel(model);\n \n // Deserialize\n const deserialized = deserializeModel(serialized);\n \n // Compare\n const isEqual = modelsEqual(model, deserialized);\n \n if (isEqual) {\n return {\n output: 'Validation passed: Model serialization is consistent',\n exitCode: 0,\n warnings,\n };\n } else {\n return {\n output: 'Validation failed: Model serialization is inconsistent',\n exitCode: 2,\n warnings,\n };\n }\n}\n\n/**\n * Formats output based on format option.\n */\nfunction formatOutput(model: AnnouncementModel, options: CLIOptions, colorize: boolean): string {\n const { format, screenReader } = options;\n \n // Handle audit format\n if (format === 'audit') {\n return renderAuditReport(model, colorize);\n }\n \n // Handle JSON format\n if (format === 'json') {\n return serializeModel(model);\n }\n \n // Handle text format\n if (format === 'text') {\n return formatScreenReaderOutput(model, screenReader, colorize);\n }\n \n // Handle both format\n if (format === 'both') {\n const json = serializeModel(model);\n const text = formatScreenReaderOutput(model, screenReader, colorize);\n const c = createColors(colorize);\n return `${c.sectionHeader('=== JSON Output ===')}\\n${json}\\n\\n${c.sectionHeader('=== Screen Reader Output ===')}\\n${text}`;\n }\n \n throw new Error(`Unknown format: ${format}`);\n}\n\n/**\n * Formats screen reader output based on selected reader(s).\n */\nfunction formatScreenReaderOutput(\n model: AnnouncementModel,\n screenReader: string,\n colorize: boolean\n): string {\n if (screenReader === 'all') {\n const nvda = renderNVDA(model, colorize);\n const jaws = renderJAWS(model, colorize);\n const voiceover = renderVoiceOver(model, colorize);\n const c = createColors(colorize);\n \n return [\n c.sectionHeader('=== NVDA ==='),\n nvda,\n '',\n c.sectionHeader('=== JAWS ==='),\n jaws,\n '',\n c.sectionHeader('=== VoiceOver ==='),\n voiceover,\n ].join('\\n');\n }\n \n switch (screenReader) {\n case 'nvda':\n return renderNVDA(model, colorize);\n case 'jaws':\n return renderJAWS(model, colorize);\n case 'voiceover':\n return renderVoiceOver(model, colorize);\n default:\n throw new Error(`Unknown screen reader: ${screenReader}`);\n }\n}\n\n/**\n * Formats warnings for display.\n */\nexport function formatWarnings(warnings: string[], colorize?: boolean): string {\n if (warnings.length === 0) {\n return '';\n }\n \n const c = createColors(colorize ?? false);\n \n const header = colorize\n ? c.warning(c.bold('=== Warnings ==='))\n : '=== Warnings ===';\n \n const lines = [\n '',\n header,\n ...warnings.map(w => colorize ? `${c.warning('⚠️')} ${w}` : `⚠️ ${w}`),\n '',\n ];\n \n return lines.join('\\n');\n}\n\n/**\n * Processes multiple HTML files in batch mode.\n * \n * @param filePaths - Array of file paths to process\n * @param options - CLI options\n * @returns Batch process result with all outputs\n */\nexport function processBatch(\n filePaths: string[],\n options: CLIOptions\n): BatchProcessResult {\n const results: BatchResult[] = [];\n const allWarnings: string[] = [];\n let anyFailed = false;\n \n // Process each file independently\n for (const filePath of filePaths) {\n try {\n // Read HTML from file\n const { readFileSync } = require('fs');\n const html = readFileSync(filePath, 'utf-8');\n \n // Process HTML\n const result = processHTML(html, options);\n \n results.push({\n filePath,\n success: result.exitCode === 0,\n output: result.output,\n warnings: result.warnings,\n });\n \n allWarnings.push(...result.warnings);\n \n if (result.exitCode !== 0) {\n anyFailed = true;\n }\n } catch (error) {\n // Continue processing other files on error\n const errorMessage = error instanceof Error ? error.message : String(error);\n \n results.push({\n filePath,\n success: false,\n error: errorMessage,\n warnings: [],\n });\n \n anyFailed = true;\n }\n }\n \n // Format combined output\n const output = formatBatchOutput(results, options);\n \n return {\n results,\n output,\n exitCode: anyFailed ? 2 : 0,\n warnings: allWarnings,\n };\n}\n\n/**\n * Formats batch processing results.\n */\nfunction formatBatchOutput(results: BatchResult[], _options: CLIOptions): string {\n const lines: string[] = [];\n \n // Add header\n lines.push('=== Batch Processing Results ===');\n lines.push('');\n \n // Add results for each file\n for (const result of results) {\n lines.push(`File: ${result.filePath}`);\n \n if (result.success) {\n lines.push('Status: ✓ Success');\n \n if (result.warnings.length > 0) {\n lines.push(`Warnings: ${result.warnings.length}`);\n }\n \n lines.push('');\n lines.push('--- Output ---');\n lines.push(result.output || '');\n } else {\n lines.push('Status: ✗ Failed');\n lines.push(`Error: ${result.error}`);\n }\n \n lines.push('');\n lines.push('---');\n lines.push('');\n }\n \n // Add summary\n const successCount = results.filter(r => r.success).length;\n const failCount = results.filter(r => !r.success).length;\n \n lines.push('=== Summary ===');\n lines.push(`Total files: ${results.length}`);\n lines.push(`Successful: ${successCount}`);\n lines.push(`Failed: ${failCount}`);\n \n return lines.join('\\n');\n}\n"],"mappings":";;;;;;;;;AAMA,SAAS,eAAe;AACxB,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,SAAS,YAAY;;;ACuCvB,SAAS,gBAAgB,YAA6B;AAC3D,QAAM,SAAS,WAAW;AAC1B,QAAM,eAAe,WAAW;AAGhC,QAAM,eAA+B,CAAC,QAAQ,QAAQ,SAAS,MAAM;AACrE,MAAI,CAAC,aAAa,SAAS,MAAsB,GAAG;AAClD,UAAM,IAAI;AAAA,MACR,mBAAmB,MAAM,qBAAqB,aAAa,KAAK,IAAI,CAAC;AAAA,IACvE;AAAA,EACF;AAGA,QAAM,eAA+B,CAAC,QAAQ,QAAQ,aAAa,KAAK;AACxE,MAAI,CAAC,aAAa,SAAS,YAA4B,GAAG;AACxD,UAAM,IAAI;AAAA,MACR,0BAA0B,YAAY,qBAAqB,aAAa,KAAK,IAAI,CAAC;AAAA,IACpF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,QAAQ,WAAW;AAAA,IACnB;AAAA,IACA;AAAA,IACA,UAAU,WAAW;AAAA,IACrB,UAAU,WAAW,YAAY;AAAA,IACjC,MAAM,WAAW;AAAA,IACjB,OAAO,WAAW,SAAS;AAAA,EAC7B;AACF;AAQO,SAAS,WAAW,OAAwC;AAEjE,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,QACL,OAAO;AAAA,QACP,SAAS;AAAA,QACT,QAAQ,CAAC;AAAA,MACX;AAAA,IACF;AAGA,QAAI,MAAM,SAAS,GAAG,GAAG;AACvB,UAAI,MAAM,WAAW,GAAG;AACtB,eAAO,EAAE,OAAO,QAAW,SAAS,KAAK;AAAA,MAC3C;AACA,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAGA,QAAI,MAAM,WAAW,GAAG;AACtB,aAAO;AAAA,QACL,OAAO,MAAM,CAAC;AAAA,QACd,SAAS;AAAA,MACX;AAAA,IACF;AAEA,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,QAAQ;AAAA,IACV;AAAA,EACF;AAGA,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,UAAU,KAAK;AACjB,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAQO,SAAS,cAAc,aAAgC;AAC5D,QAAM,YAAY,YAAY,UAAU,YAAY,OAAO,SAAS;AAEpE,MAAI,CAAC,YAAY,SAAS,CAAC,YAAY,WAAW,CAAC,WAAW;AAC5D,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,iBACd,SACA,aACM;AACN,MAAI,QAAQ,MAAM;AAChB,QAAI,YAAY,SAAS;AACvB,YAAM,IAAI,MAAM,2CAA2C;AAAA,IAC7D;AAEA,QAAI,CAAC,YAAY,OAAO;AACtB,YAAM,IAAI,MAAM,kCAAkC;AAAA,IACpD;AAEA,QAAI,YAAY,UAAU,YAAY,OAAO,SAAS,GAAG;AACvD,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,EACF;AACF;AASO,SAAS,kBACd,SACA,aACM;AACN,MAAI,QAAQ,OAAO;AACjB,QAAI,YAAY,SAAS;AACvB,YAAM,IAAI,MAAM,4CAA4C;AAAA,IAC9D;AAEA,QAAI,QAAQ,MAAM;AAChB,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAEA,QAAI,CAAC,YAAY,UAAU,YAAY,OAAO,WAAW,GAAG;AAC1D,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC5D;AAAA,EACF;AACF;;;AC1MA,SAAS,cAAc,qBAAqB;AAC5C,SAAS,aAAa;AAKf,IAAM,cAAN,cAA0B,MAAM;AAAA,EACrC,YACE,SACgB,MACA,MAChB;AACA,UAAM,OAAO;AAHG;AACA;AAGhB,SAAK,OAAO;AAAA,EACd;AACF;AASO,SAAS,iBAAiB,UAA0B;AACzD,MAAI;AACF,WAAO,aAAa,UAAU,OAAO;AAAA,EACvC,SAAS,OAAY;AACnB,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,mBAAmB,QAAQ;AAAA,QAC3B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,sBAAsB,QAAQ;AAAA,QAC9B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,oCAAoC,QAAQ;AAAA,QAC5C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR,wBAAwB,QAAQ,KAAK,MAAM,OAAO;AAAA,MAClD,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAQA,eAAsB,oBAAqC;AACzD,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAmB,CAAC;AAE1B,UAAM,GAAG,QAAQ,CAAC,UAAkB;AAClC,aAAO,KAAK,KAAK;AAAA,IACnB,CAAC;AAED,UAAM,GAAG,OAAO,MAAM;AACpB,YAAM,UAAU,OAAO,OAAO,MAAM,EAAE,SAAS,OAAO;AACtD,cAAQ,OAAO;AAAA,IACjB,CAAC;AAED,UAAM,GAAG,SAAS,CAAC,UAAiB;AAClC,aAAO,IAAI;AAAA,QACT,8BAA8B,MAAM,OAAO;AAAA,QAC3C;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAGD,UAAM,OAAO;AAAA,EACf,CAAC;AACH;AASO,SAAS,kBAAkB,UAAkB,SAAuB;AACzE,MAAI;AACF,kBAAc,UAAU,SAAS,OAAO;AAAA,EAC1C,SAAS,OAAY;AACnB,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,sBAAsB,QAAQ;AAAA,QAC9B;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,4BAA4B,QAAQ;AAAA,QACpC;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,QAAI,MAAM,SAAS,UAAU;AAC3B,YAAM,IAAI;AAAA,QACR,oCAAoC,QAAQ;AAAA,QAC5C;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,MACR,yBAAyB,QAAQ,KAAK,MAAM,OAAO;AAAA,MACnD,MAAM;AAAA,MACN;AAAA,IACF;AAAA,EACF;AACF;AAOO,SAAS,oBAAoB,SAAuB;AACzD,UAAQ,IAAI,OAAO;AACrB;AASO,SAAS,SACd,UACA,SAC0B;AAC1B,MAAI,SAAS;AACX,WAAO,kBAAkB;AAAA,EAC3B;AAEA,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,YAAY,2BAA2B;AAAA,EACnD;AAEA,SAAO,iBAAiB,QAAQ;AAClC;AAQO,SAAS,YAAY,SAAiB,YAA2B;AACtE,MAAI,YAAY;AACd,sBAAkB,YAAY,OAAO;AAAA,EACvC,OAAO;AACL,wBAAoB,OAAO;AAAA,EAC7B;AACF;;;AC/KA,SAAS,aAAa;AAKf,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,SAAiC,OAAe;AAC1D,UAAM,OAAO;AAD8B;AAE3C,SAAK,OAAO;AAAA,EACd;AACF;AAgCO,SAAS,UAAU,MAA2B;AACnD,QAAM,WAA6B,CAAC;AAEpC,MAAI;AAEF,UAAM,MAAM,IAAI,MAAM,MAAM;AAAA,MAC1B,aAAa;AAAA;AAAA,MAEb,sBAAsB;AAAA,MACtB,cAAc;AAAA,IAChB,CAAC;AAED,UAAM,WAAW,IAAI,OAAO;AAI5B,QAAI,CAAC,SAAS,iBAAiB;AAC7B,eAAS,KAAK;AAAA,QACZ,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAGA,QAAI,CAAC,SAAS,MAAM;AAClB,eAAS,KAAK;AAAA,QACZ,SAAS;AAAA,MACX,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,MACL;AAAA,MACA;AAAA,IACF;AAAA,EACF,SAAS,OAAO;AAEd,UAAM,IAAI;AAAA,MACR,yBAAyB,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC;AAAA,MAC/E,iBAAiB,QAAQ,QAAQ;AAAA,IACnC;AAAA,EACF;AACF;;;AC1CO,SAAS,sBACd,SACA,UAAwB,oBAAI,IAAI,GACT;AACvB,QAAM,WAAqC,CAAC;AAG5C,MAAI,QAAQ,IAAI,OAAO,GAAG;AACxB,aAAS,KAAK;AAAA,MACZ,SAAS;AAAA,MACT;AAAA,IACF,CAAC;AACD,WAAO,EAAE,MAAM,IAAI,SAAS;AAAA,EAC9B;AAEA,UAAQ,IAAI,OAAO;AAGnB,QAAM,aAAa,QAAQ,aAAa,iBAAiB;AACzD,MAAI,YAAY;AACd,UAAM,OAAO,0BAA0B,SAAS,YAAY,SAAS,QAAQ;AAE7E,WAAO,EAAE,MAAM,SAAS;AAAA,EAC1B;AAGA,QAAM,YAAY,QAAQ,aAAa,YAAY;AACnD,MAAI,aAAa,UAAU,KAAK,GAAG;AACjC,WAAO,EAAE,MAAM,UAAU,KAAK,GAAG,SAAS;AAAA,EAC5C;AAGA,MAAI,cAAc,OAAO,GAAG;AAC1B,UAAM,YAAY,qBAAqB,OAAO;AAC9C,QAAI,WAAW;AACb,aAAO,EAAE,MAAM,WAAW,SAAS;AAAA,IACrC;AAAA,EACF;AAGA,MAAI,QAAQ,QAAQ,YAAY,MAAM,OAAO;AAC3C,UAAM,MAAM,QAAQ,aAAa,KAAK;AACtC,QAAI,QAAQ,MAAM;AAChB,aAAO,EAAE,MAAM,IAAI,KAAK,GAAG,SAAS;AAAA,IACtC;AAAA,EACF;AAGA,MAAI,wBAAwB,OAAO,GAAG;AACpC,UAAM,WAAW,uBAAuB,SAAS,OAAO;AACxD,QAAI,UAAU;AACZ,aAAO,EAAE,MAAM,UAAU,SAAS;AAAA,IACpC;AAAA,EACF;AAGA,QAAM,QAAQ,QAAQ,aAAa,OAAO;AAC1C,MAAI,SAAS,MAAM,KAAK,GAAG;AACzB,WAAO,EAAE,MAAM,MAAM,KAAK,GAAG,SAAS;AAAA,EACxC;AAGA,SAAO,EAAE,MAAM,IAAI,SAAS;AAC9B;AAWA,SAAS,0BACP,SACA,YACA,SACA,UACQ;AACR,QAAM,WAAW,QAAQ;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,WAAW,KAAK,EAAE,MAAM,KAAK;AACzC,QAAM,QAAkB,CAAC;AAEzB,aAAW,MAAM,KAAK;AACpB,QAAI,CAAC,GAAI;AAET,UAAM,oBAAoB,SAAS,eAAe,EAAE;AACpD,QAAI,CAAC,mBAAmB;AACtB,eAAS,KAAK;AAAA,QACZ,SAAS,+CAA+C,EAAE;AAAA,QAC1D;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAIA,UAAM,SAAS,sBAAsB,mBAAmB,IAAI,IAAI,OAAO,CAAC;AACxE,aAAS,KAAK,GAAG,OAAO,QAAQ;AAGhC,UAAM,OAAO,OAAO,QAAQ,eAAe,iBAAiB;AAC5D,QAAI,MAAM;AACR,YAAM,KAAK,IAAI;AAAA,IACjB;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,GAAG,EAAE,KAAK;AAC9B;AAQA,SAAS,qBAAqB,SAA0B;AACtD,QAAM,WAAW,QAAQ;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAGA,QAAM,KAAK,QAAQ,aAAa,IAAI;AACpC,MAAI,IAAI;AACN,UAAM,QAAQ,SAAS,cAAc,cAAc,EAAE,IAAI;AACzD,QAAI,OAAO;AACT,aAAO,eAAe,KAAK;AAAA,IAC7B;AAAA,EACF;AAGA,QAAM,cAAc,QAAQ,QAAQ,OAAO;AAC3C,MAAI,aAAa;AACf,WAAO,eAAe,WAAW;AAAA,EACnC;AAEA,SAAO;AACT;AASA,SAAS,uBAAuB,SAAkB,UAAgC;AAChF,SAAO,eAAe,OAAO;AAC/B;AAQA,SAAS,eAAe,SAA0B;AAEhD,MAAI,QAAQ,aAAa,aAAa,MAAM,QAAQ;AAClD,WAAO;AAAA,EACT;AAEA,MAAI,OAAO;AAEX,aAAW,QAAQ,MAAM,KAAK,QAAQ,UAAU,GAAG;AACjD,QAAI,KAAK,aAAa,GAAG;AACvB,cAAQ,KAAK,eAAe;AAAA,IAC9B,WAAW,KAAK,aAAa,GAAG;AAC9B,YAAM,eAAe;AAGrB,UAAI,aAAa,aAAa,aAAa,MAAM,QAAQ;AACvD;AAAA,MACF;AAEA,cAAQ,eAAe,YAAY;AAAA,IACrC;AAAA,EACF;AAEA,SAAO,KAAK,KAAK;AACnB;AAQA,SAAS,cAAc,SAA2B;AAChD,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAC5C,SACE,YAAY,WACZ,YAAY,cACZ,YAAY,YACZ,YAAY;AAEhB;AAWA,SAAS,wBAAwB,SAA2B;AAC1D,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAC5C,QAAM,OAAO,QAAQ,aAAa,MAAM;AAGxC,QAAM,kBAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAAM;AAAA,IAC9B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,gBAAgB,SAAS,OAAO,GAAG;AACrC,WAAO;AAAA,EACT;AAGA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,MAAI,QAAQ,aAAa,SAAS,IAAI,GAAG;AACvC,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAaO,SAAS,6BACd,SAC8B;AAC9B,QAAM,WAAqC,CAAC;AAG5C,QAAM,cAAc,QAAQ,aAAa,kBAAkB;AAC3D,MAAI,aAAa;AACf,UAAM,cAAc;AAAA,MAClB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,QAAI,aAAa;AACf,aAAO,EAAE,aAAa,SAAS;AAAA,IACjC;AAAA,EACF;AAGA,QAAM,QAAQ,QAAQ,aAAa,OAAO;AAC1C,MAAI,SAAS,MAAM,KAAK,GAAG;AACzB,WAAO,EAAE,aAAa,MAAM,KAAK,GAAG,SAAS;AAAA,EAC/C;AAGA,SAAO,EAAE,aAAa,IAAI,SAAS;AACrC;AAUA,SAAS,kCACP,SACA,aACA,UACQ;AACR,QAAM,WAAW,QAAQ;AACzB,MAAI,CAAC,UAAU;AACb,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,YAAY,KAAK,EAAE,MAAM,KAAK;AAC1C,QAAM,eAAyB,CAAC;AAEhC,aAAW,MAAM,KAAK;AACpB,QAAI,CAAC,GAAI;AAET,UAAM,oBAAoB,SAAS,eAAe,EAAE;AACpD,QAAI,CAAC,mBAAmB;AACtB,eAAS,KAAK;AAAA,QACZ,SAAS,gDAAgD,EAAE;AAAA,QAC3D;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAGA,UAAM,OAAO,eAAe,iBAAiB;AAC7C,QAAI,MAAM;AACR,mBAAa,KAAK,IAAI;AAAA,IACxB;AAAA,EACF;AAEA,SAAO,aAAa,KAAK,GAAG,EAAE,KAAK;AACrC;;;ACzLO,IAAM,kBAA6C;AAAA;AAAA,EAExD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,wBAAsC;AAAA,EACjD,OAAO;AAAA,EACP,OAAO;AACT;;;ACrOA,IAAM,oBAAoD;AAAA;AAAA,EAExD,UAAU;AAAA,EACV,KAAK;AAAA;AAAA;AAAA,EAGL,SAAS;AAAA;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA;AAAA,EAGV,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAGN,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,UAAU;AAAA;AAAA,EACV,UAAU;AAAA;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,WAAW;AAAA;AAAA;AAAA,EAGX,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAGN,OAAO;AAAA;AAAA,EAGP,WAAW;AAAA;AAAA,EAGX,KAAK;AAAA,EACL,cAAc;AAAA,EACd,QAAQ;AAAA,EACR,OAAO;AAAA;AAAA,EAGP,SAAS;AAAA,EACT,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA;AAAA;AAAA,EAGN,MAAM;AAAA,EACN,MAAM;AAAA,EACN,MAAM;AAAA;AAAA,EAGN,UAAU;AAAA,EACV,cAAc;AAAA;AAAA,EAGd,WAAW;AAAA,EACX,WAAW;AAAA;AAAA,EAGX,UAAU;AAAA,EACV,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA;AAAA,EAGV,YAAY;AAAA,EACZ,UAAU;AAAA;AAAA,EAGV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,SAAS;AAAA;AAAA,EAGT,MAAM;AAAA;AAAA,EAGN,WAAW;AACb;AAKA,IAAM,sBAAsD;AAAA,EAC1D,UAAU;AAAA,EACV,UAAU;AAAA,EACV,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,OAAO;AAAA,EACP,OAAO;AAAA,EACP,UAAU;AACZ;AAaO,SAAS,YAAY,SAAyC;AACnE,QAAM,WAAqC,CAAC;AAG5C,QAAM,eAAe,QAAQ,aAAa,MAAM;AAChD,MAAI,cAAc;AAChB,UAAM,OAAO,yBAAyB,cAAc,SAAS,QAAQ;AACrE,QAAI,MAAM;AACR,aAAO,EAAE,MAAM,SAAS;AAAA,IAC1B;AAAA,EAEF;AAGA,QAAM,eAAe,oBAAoB,SAAS,QAAQ;AAC1D,SAAO,EAAE,MAAM,cAAc,SAAS;AACxC;AAUA,SAAS,yBACP,UACA,SACA,UACuB;AACvB,QAAM,OAAO,SAAS,KAAK,EAAE,YAAY;AAGzC,MAAI,SAAS,kBAAkB,SAAS,QAAQ;AAC9C,WAAO;AAAA,EACT;AAGA,MAAI,gBAAgB,SAAS,IAAsB,GAAG;AACpD,WAAO;AAAA,EACT;AAGA,WAAS,KAAK;AAAA,IACZ,SAAS,iCAAiC,QAAQ;AAAA,IAClD;AAAA,EACF,CAAC;AAED,SAAO;AACT;AASA,SAAS,oBACP,SACA,WACuB;AACvB,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAG5C,MAAI,YAAY,SAAS;AACvB,WAAO,iBAAiB,OAA2B;AAAA,EACrD;AAGA,MAAI,YAAY,KAAK;AACnB,WAAO,QAAQ,aAAa,MAAM,IAAI,SAAS;AAAA,EACjD;AAGA,MAAI,YAAY,UAAU;AACxB,WAAO,mBAAmB,OAAO,IAAI,WAAW;AAAA,EAClD;AAEA,MAAI,YAAY,UAAU;AACxB,WAAO,mBAAmB,OAAO,IAAI,gBAAgB;AAAA,EACvD;AAGA,MAAI,YAAY,MAAM;AACpB,UAAM,QAAQ,QAAQ,aAAa,OAAO;AAC1C,WAAO,UAAU,QAAQ,cAAc;AAAA,EACzC;AAGA,MAAI,YAAY,WAAW;AAGzB,WAAO,QAAQ,aAAa,YAAY,KAAK,QAAQ,aAAa,iBAAiB,IAC/E,WACA;AAAA,EACN;AAGA,QAAM,eAAe,kBAAkB,OAAO;AAC9C,SAAO,gBAAgB;AACzB;AAQA,SAAS,iBAAiB,OAAyC;AACjE,QAAM,QAAQ,MAAM,aAAa,MAAM,KAAK,QAAQ,YAAY;AAChE,SAAO,oBAAoB,IAAI,KAAK;AACtC;AAWA,SAAS,mBAAmB,SAA2B;AACrD,MAAI,SAAS,QAAQ;AAErB,SAAO,QAAQ;AACb,UAAM,UAAU,OAAO,QAAQ,YAAY;AAC3C,QAAI,YAAY,aAAa,YAAY,WAAW;AAClD,aAAO;AAAA,IACT;AACA,aAAS,OAAO;AAAA,EAClB;AAEA,SAAO;AACT;AAaO,SAAS,aAAa,SAA2B;AAEtD,MAAI,QAAQ,aAAa,aAAa,MAAM,QAAQ;AAClD,WAAO;AAAA,EACT;AAGA,QAAM,OAAO,QAAQ,aAAa,MAAM;AACxC,MAAI,SAAS,kBAAkB,SAAS,QAAQ;AAC9C,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,YAAY,OAAO;AACtC,SAAO,WAAW,SAAS;AAC7B;;;AC1QO,SAAS,aAAa,SAAyC;AACpE,QAAM,WAAqC,CAAC;AAC5C,QAAM,QAAyB,CAAC;AAGhC,QAAM,WAAW,wBAAwB,SAAS,iBAAiB,QAAQ;AAC3E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAGA,QAAM,UAAU,yBAAyB,SAAS,gBAAgB,QAAQ;AAC1E,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,QAAM,UAAU,yBAAyB,SAAS,gBAAgB,QAAQ;AAC1E,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,QAAM,WAAW,wBAAwB,SAAS,iBAAiB,QAAQ;AAC3E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAGA,QAAM,WAAW,wBAAwB,SAAS,iBAAiB,QAAQ;AAC3E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAGA,QAAM,UAAU,wBAAwB,SAAS,gBAAgB,QAAQ;AACzE,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,QAAM,WAAW,wBAAwB,SAAS,iBAAiB,QAAQ;AAC3E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAGA,QAAM,WAAW,wBAAwB,SAAS,iBAAiB,QAAQ;AAC3E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAGA,QAAM,OAAO,wBAAwB,SAAS,aAAa,QAAQ;AACnE,MAAI,SAAS,QAAW;AACtB,UAAM,OAAO;AAAA,EACf;AAGA,QAAM,UAAU,wBAAwB,SAAS,QAAQ;AACzD,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,QAAM,UAAU,wBAAwB,SAAS,gBAAgB,QAAQ;AACzE,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,QAAM,SAAS,wBAAwB,SAAS,eAAe,QAAQ;AACvE,MAAI,WAAW,QAAW;AACxB,UAAM,SAAS;AAAA,EACjB;AAGA,QAAM,QAAQ,sBAAsB,SAAS,QAAQ;AACrD,MAAI,UAAU,QAAW;AACvB,UAAM,QAAQ;AAAA,EAChB;AAGA,QAAM,WAAW,uBAAuB,SAAS,iBAAiB,QAAQ;AAC1E,MAAI,aAAa,QAAW;AAC1B,UAAM,WAAW;AAAA,EACnB;AAEA,QAAM,UAAU,uBAAuB,SAAS,gBAAgB,QAAQ;AACxE,MAAI,YAAY,QAAW;AACzB,UAAM,UAAU;AAAA,EAClB;AAGA,sBAAoB,SAAS,OAAO,QAAQ;AAE5C,SAAO,EAAE,OAAO,SAAS;AAC3B;AAQO,SAAS,aAAa,SAAyC;AACpE,QAAM,WAAqC,CAAC;AAG5C,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAE5C,MAAI,YAAY,SAAS;AACvB,WAAO,kBAAkB,SAA6B,QAAQ;AAAA,EAChE;AAEA,MAAI,YAAY,YAAY;AAC1B,WAAO,qBAAqB,SAAgC,QAAQ;AAAA,EACtE;AAEA,MAAI,YAAY,UAAU;AACxB,WAAO,mBAAmB,SAA8B,QAAQ;AAAA,EAClE;AAGA,QAAM,WAAW,QAAQ,aAAa,eAAe;AACrD,MAAI,aAAa,MAAM;AACrB,UAAM,UAAU,WAAW,QAAQ;AACnC,QAAI,CAAC,MAAM,OAAO,GAAG;AACnB,YAAM,WAAW,QAAQ,aAAa,eAAe;AACrD,YAAM,WAAW,QAAQ,aAAa,eAAe;AACrD,YAAM,YAAY,QAAQ,aAAa,gBAAgB;AAEvD,aAAO;AAAA,QACL,OAAO;AAAA,UACL;AAAA,UACA,KAAK,aAAa,OAAO,WAAW,QAAQ,IAAI;AAAA,UAChD,KAAK,aAAa,OAAO,WAAW,QAAQ,IAAI;AAAA,UAChD,MAAM,aAAa;AAAA,QACrB;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAW,SAAS;AACtC;AAUA,SAAS,wBACP,SACA,UACA,UACqB;AACrB,QAAM,QAAQ,QAAQ,aAAa,QAAQ;AAC3C,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,YAAY,EAAE,KAAK;AAC5C,MAAI,eAAe,QAAQ;AACzB,WAAO;AAAA,EACT;AACA,MAAI,eAAe,SAAS;AAC1B,WAAO;AAAA,EACT;AAEA,WAAS,KAAK;AAAA,IACZ,SAAS,WAAW,QAAQ,YAAY,KAAK;AAAA,IAC7C;AAAA,EACF,CAAC;AACD,SAAO;AACT;AAUA,SAAS,yBACP,SACA,UACA,UAC+B;AAC/B,QAAM,QAAQ,QAAQ,aAAa,QAAQ;AAC3C,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,YAAY,EAAE,KAAK;AAC5C,MAAI,eAAe,QAAQ;AACzB,WAAO;AAAA,EACT;AACA,MAAI,eAAe,SAAS;AAC1B,WAAO;AAAA,EACT;AACA,MAAI,eAAe,SAAS;AAC1B,WAAO;AAAA,EACT;AAEA,WAAS,KAAK;AAAA,IACZ,SAAS,WAAW,QAAQ,YAAY,KAAK;AAAA,IAC7C;AAAA,EACF,CAAC;AACD,SAAO;AACT;AASA,SAAS,wBACP,SACA,UAC6E;AAC7E,QAAM,QAAQ,QAAQ,aAAa,cAAc;AACjD,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,YAAY,EAAE,KAAK;AAC5C,QAAM,cAAc,CAAC,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,OAAO;AAEhF,MAAI,YAAY,SAAS,UAAU,GAAG;AACpC,WAAO,eAAe,UAAU,QAAS;AAAA,EAC3C;AAEA,WAAS,KAAK;AAAA,IACZ,SAAS,gCAAgC,KAAK,uBAAuB,YAAY,KAAK,IAAI,CAAC;AAAA,IAC3F;AAAA,EACF,CAAC;AACD,SAAO;AACT;AASA,SAAS,sBACP,SACA,UACoB;AAEpB,QAAM,YAAY,QAAQ,aAAa,YAAY;AACnD,MAAI,cAAc,MAAM;AACtB,UAAM,QAAQ,SAAS,WAAW,EAAE;AACpC,QAAI,CAAC,MAAM,KAAK,KAAK,SAAS,KAAK,SAAS,GAAG;AAC7C,aAAO;AAAA,IACT;AACA,aAAS,KAAK;AAAA,MACZ,SAAS,8BAA8B,SAAS;AAAA,MAChD;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAGA,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAC5C,QAAM,QAAQ,QAAQ,MAAM,YAAY;AACxC,MAAI,OAAO;AACT,WAAO,SAAS,MAAM,CAAC,GAAG,EAAE;AAAA,EAC9B;AAEA,SAAO;AACT;AAUA,SAAS,uBACP,SACA,UACA,UACoB;AACpB,QAAM,QAAQ,QAAQ,aAAa,QAAQ;AAC3C,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AAEA,QAAM,MAAM,SAAS,OAAO,EAAE;AAC9B,MAAI,MAAM,GAAG,KAAK,MAAM,GAAG;AACzB,aAAS,KAAK;AAAA,MACZ,SAAS,WAAW,QAAQ,YAAY,KAAK;AAAA,MAC7C;AAAA,IACF,CAAC;AACD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AASA,SAAS,oBACP,SACA,OACA,WACM;AACN,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAG5C,MAAI,YAAY,SAAS;AACvB,UAAM,QAAQ;AACd,UAAM,OAAO,MAAM,KAAK,YAAY;AAEpC,QAAI,SAAS,cAAc,SAAS,SAAS;AAE3C,UAAI,MAAM,YAAY,QAAW;AAC/B,cAAM,UAAU,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAGA,MAAI,cAAc,SAAS;AACzB,UAAM,cAAc;AAEpB,QAAI,MAAM,aAAa,UAAa,YAAY,UAAU;AACxD,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAGA,MAAI,cAAc,SAAS;AACzB,UAAM,cAAc;AAEpB,QAAI,MAAM,aAAa,UAAa,YAAY,UAAU;AACxD,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAGA,MAAI,cAAc,SAAS;AACzB,UAAM,cAAc;AAEpB,QAAI,MAAM,aAAa,UAAa,YAAY,UAAU;AACxD,YAAM,WAAW;AAAA,IACnB;AAAA,EACF;AACF;AAKA,SAAS,kBACP,OACA,UACuB;AACvB,QAAM,OAAO,MAAM,KAAK,YAAY;AAGpC,MAAI,SAAS,cAAc,SAAS,SAAS;AAC3C,WAAO,EAAE,OAAO,QAAW,SAAS;AAAA,EACtC;AAGA,MAAI,SAAS,YAAY,SAAS,YAAY,SAAS,SAAS;AAC9D,WAAO,EAAE,OAAO,QAAW,SAAS;AAAA,EACtC;AAGA,QAAM,QAAQ,MAAM;AACpB,MAAI,OAAO;AACT,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAW,SAAS;AACtC;AAKA,SAAS,qBACP,UACA,UACuB;AACvB,QAAM,QAAQ,SAAS;AACvB,MAAI,OAAO;AACT,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS;AAAA,QACT,MAAM;AAAA,MACR;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAW,SAAS;AACtC;AAKA,SAAS,mBACP,QACA,UACuB;AACvB,QAAM,QAAQ,OAAO;AACrB,QAAM,iBAAiB,OAAO,QAAQ,OAAO,aAAa;AAC1D,QAAM,OAAO,gBAAgB,eAAe;AAE5C,MAAI,OAAO;AACT,WAAO;AAAA,MACL,OAAO;AAAA,QACL,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,QAAW,SAAS;AACtC;;;ACxdA,IAAM,8BAA8B;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAUO,SAAS,iBAAiB,SAA6B;AAC5D,QAAM,eAAe,QAAQ,aAAa,UAAU;AACpD,QAAM,WAAW,iBAAiB,OAAO,SAAS,cAAc,EAAE,IAAI;AAGtE,QAAM,YAAY,YAAY,SAAS,QAAQ;AAG/C,SAAO;AAAA,IACL;AAAA,IACA,GAAI,iBAAiB,QAAQ,CAAC,MAAM,QAAS,KAAK,EAAE,SAAS;AAAA,EAC/D;AACF;AAcA,SAAS,YAAY,SAAkB,UAAuC;AAC5E,QAAM,UAAU,QAAQ,QAAQ,YAAY;AAG5C,MAAI,WAAW,OAAO,GAAG;AACvB,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,UAAa,CAAC,MAAM,QAAQ,GAAG;AAC9C,WAAO;AAAA,EACT;AAGA,MAAI,oBAAoB,SAAS,OAAO,GAAG;AACzC,WAAO;AAAA,EACT;AAIA,SAAO;AACT;AASA,SAAS,oBAAoB,SAAkB,SAA0B;AAEvE,MAAI,YAAY,OAAO,YAAY,QAAQ;AACzC,WAAO,QAAQ,aAAa,MAAM;AAAA,EACpC;AAGA,MAAI,4BAA4B,SAAS,OAAO,GAAG;AACjD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAQA,SAAS,WAAW,SAA2B;AAE7C,MAAI,cAAc,SAAS;AACzB,UAAM,cAAc;AACpB,QAAI,YAAY,UAAU;AACxB,aAAO;AAAA,IACT;AAAA,EACF;AAGA,QAAM,eAAe,QAAQ,aAAa,eAAe;AACzD,MAAI,iBAAiB,QAAQ;AAC3B,WAAO;AAAA,EACT;AAEA,SAAO;AACT;;;ACzFO,IAAM,gBAAN,cAA4B,MAAM;AAAA,EACvC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAWA,SAAS,SAAS,SAA2B;AAE3C,MAAI,QAAQ,aAAa,aAAa,MAAM,OAAQ,QAAO;AAG3D,MAAI,OAAO,qBAAqB,YAAY;AAC1C,QAAI;AACF,YAAM,QAAQ,iBAAiB,OAAO;AACtC,UAAI,MAAM,YAAY,OAAQ,QAAO;AACrC,UAAI,MAAM,eAAe,SAAU,QAAO;AAAA,IAC5C,QAAQ;AAAA,IAER;AAAA,EACF;AAEA,SAAO;AACT;AAcA,SAAS,iBACP,MACA,UACA,UACM;AACN,MAAI,KAAK,aAAa,GAAG;AACvB,UAAM,QAAQ,KAAK,eAAe,IAAI,KAAK;AAC3C,QAAI,KAAK,SAAS,GAAG;AACnB,eAAS,KAAK;AAAA,QACZ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC;AAAA,QACR,OAAO,EAAE,WAAW,MAAM;AAAA,QAC1B,UAAU,CAAC;AAAA,MACb,CAAC;AAAA,IACH;AACA;AAAA,EACF;AACA,MAAI,KAAK,aAAa,GAAG;AACvB,UAAM,UAAU;AAChB,QAAI,SAAS,OAAO,EAAG;AACvB,QAAI,CAAC,aAAa,OAAO,GAAG;AAE1B,YAAM,gBAAgB,mCAAmC,SAAS,QAAQ;AAC1E,eAAS,KAAK,GAAG,aAAa;AAC9B;AAAA,IACF;AACA,UAAM,YAAY,mBAAmB,SAAS,QAAQ;AACtD,QAAI,UAAW,UAAS,KAAK,SAAS;AAAA,EACxC;AACF;AAYA,SAAS,mCACP,SACA,UACkB;AAClB,QAAM,WAA6B,CAAC;AAEpC,MAAI,QAAQ,YAAY;AACtB,eAAW,SAAS,MAAM,KAAK,QAAQ,WAAW,UAAU,GAAG;AAC7D,uBAAiB,OAAO,UAAU,QAAQ;AAAA,IAC5C;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,QAAQ,UAAU,GAAG;AAClD,qBAAiB,OAAO,UAAU,QAAQ;AAAA,EAC5C;AACA,SAAO;AACT;AAYO,SAAS,uBACd,aACA,YACiB;AACjB,QAAM,WAA+B,CAAC;AAGtC,MAAI,SAAS,WAAW,GAAG;AACzB,UAAMC,SAA2B;AAAA,MAC/B,SAAS;AAAA,MACT,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,MAAM;AAAA,QACN,OAAO,CAAC;AAAA,QACR,OAAO,EAAE,WAAW,MAAM;AAAA,QAC1B,UAAU,CAAC;AAAA,MACb;AAAA,MACA,UAAU;AAAA,QACR,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,QACpC,GAAI,cAAc,EAAE,WAAW;AAAA,MACjC;AAAA,IACF;AACA,WAAO,EAAE,OAAAA,QAAO,SAAS;AAAA,EAC3B;AAGA,QAAM,WAAW,mBAAmB,aAAa,QAAQ;AAGzD,QAAM,iBAAiB,YAAY,uBAAuB,aAAa,QAAQ;AAG/E,QAAM,QAA2B;AAAA,IAC/B,SAAS;AAAA,IACT,MAAM;AAAA,IACN,UAAU;AAAA,MACR,cAAa,oBAAI,KAAK,GAAE,YAAY;AAAA,MACpC,GAAI,cAAc,EAAE,WAAW;AAAA,IACjC;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,SAAS;AAC3B;AAcO,SAAS,mCACd,aACA,UACA,YACmB;AACnB,QAAM,WAAW,YAAY;AAC7B,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,cAAc,+BAA+B;AAAA,EACzD;AAGA,MAAI;AACJ,MAAI;AAEF,QAAI,YAAY,QAAQ,QAAQ,GAAG;AACjC,yBAAmB,CAAC,WAAW;AAAA,IACjC,OAAO;AAEL,yBAAmB,MAAM,KAAK,YAAY,iBAAiB,QAAQ,CAAC;AAAA,IACtE;AAAA,EACF,SAAS,OAAO;AACd,UAAM,IAAI,cAAc,0BAA0B,QAAQ,MAAM,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,CAAC,EAAE;AAAA,EAC1H;AAGA,MAAI,iBAAiB,WAAW,GAAG;AACjC,UAAM,IAAI,cAAc,gCAAgC,QAAQ,GAAG;AAAA,EACrE;AAGA,QAAM,UAA6B,CAAC;AACpC,aAAW,WAAW,kBAAkB;AACtC,UAAM,SAAS,uBAAuB,SAAS,UAAU;AACzD,YAAQ,KAAK,MAAM;AAAA,EACrB;AAEA,SAAO;AACT;AAcA,SAAS,mBACP,SACA,UACuB;AAEvB,MAAI,SAAS,OAAO,GAAG;AACrB,WAAO;AAAA,EACT;AAGA,MAAI,CAAC,aAAa,OAAO,GAAG;AAC1B,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,YAAY,OAAO;AACtC,WAAS,KAAK,GAAG,WAAW,SAAS,IAAI,QAAM;AAAA,IAC7C,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,EACb,EAAE,CAAC;AAGH,MAAI,CAAC,WAAW,MAAM;AACpB,WAAO;AAAA,EACT;AAGA,QAAM,aAAa,sBAAsB,OAAO;AAChD,WAAS,KAAK,GAAG,WAAW,SAAS,IAAI,QAAM;AAAA,IAC7C,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,EACb,EAAE,CAAC;AAGH,QAAM,aAAa,6BAA6B,OAAO;AACvD,WAAS,KAAK,GAAG,WAAW,SAAS,IAAI,QAAM;AAAA,IAC7C,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,EACb,EAAE,CAAC;AAGH,QAAM,cAAc,aAAa,OAAO;AACxC,WAAS,KAAK,GAAG,YAAY,SAAS,IAAI,QAAM;AAAA,IAC9C,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,EACb,EAAE,CAAC;AAGH,QAAM,cAAc,aAAa,OAAO;AACxC,WAAS,KAAK,GAAG,YAAY,SAAS,IAAI,QAAM;AAAA,IAC9C,SAAS,EAAE;AAAA,IACX,SAAS,EAAE;AAAA,EACb,EAAE,CAAC;AAGH,QAAM,YAAY,iBAAiB,OAAO;AAG1C,QAAM,WAA6B,CAAC;AAEpC,MAAI,QAAQ,YAAY;AACtB,eAAW,SAAS,MAAM,KAAK,QAAQ,WAAW,UAAU,GAAG;AAC7D,uBAAiB,OAAO,UAAU,QAAQ;AAAA,IAC5C;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,QAAQ,UAAU,GAAG;AAClD,qBAAiB,OAAO,UAAU,QAAQ;AAAA,EAC5C;AAGA,QAAM,OAAuB;AAAA,IAC3B,MAAM,WAAW;AAAA,IACjB,MAAM,WAAW;AAAA,IACjB,GAAI,WAAW,eAAe,EAAE,aAAa,WAAW,YAAY;AAAA,IACpE,GAAI,YAAY,SAAS,EAAE,OAAO,YAAY,MAAM;AAAA,IACpD,OAAO,YAAY;AAAA,IACnB,OAAO;AAAA,IACP;AAAA,EACF;AAEA,SAAO;AACT;AAaA,SAAS,uBACP,aACA,UACgB;AAEhB,QAAM,WAA6B,CAAC;AAEpC,MAAI,YAAY,YAAY;AAC1B,eAAW,SAAS,MAAM,KAAK,YAAY,WAAW,UAAU,GAAG;AACjE,uBAAiB,OAAO,UAAU,QAAQ;AAAA,IAC5C;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,YAAY,UAAU,GAAG;AACtD,qBAAiB,OAAO,UAAU,QAAQ;AAAA,EAC5C;AAGA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,MAAM;AAAA,IACN,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,MACL,WAAW;AAAA,IACb;AAAA,IACA;AAAA,EACF;AACF;;;AC9WO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EACzC,YAAY,SAAiB;AAC3B,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AASO,SAAS,aAAa,MAAsC;AACjE,MAAI,CAAC,gBAAgB,SAAS,IAAsB,GAAG;AACrD,UAAM,IAAI;AAAA,MACR,kBAAkB,IAAI,uBAAuB,gBAAgB,KAAK,IAAI,CAAC;AAAA,IACzE;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,cAAc,OAA8B;AAE1D,MAAI,MAAM,UAAU,QAAW;AAC7B,QAAI,CAAC,OAAO,UAAU,MAAM,KAAK,KAAK,MAAM,QAAQ,KAAK,MAAM,QAAQ,GAAG;AACxE,YAAM,IAAI;AAAA,QACR,0BAA0B,MAAM,KAAK;AAAA,MACvC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,aAAa,QAAW;AAChC,QAAI,CAAC,OAAO,UAAU,MAAM,QAAQ,KAAK,MAAM,WAAW,GAAG;AAC3D,YAAM,IAAI;AAAA,QACR,qBAAqB,MAAM,QAAQ;AAAA,MACrC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,YAAY,QAAW;AAC/B,QAAI,CAAC,OAAO,UAAU,MAAM,OAAO,KAAK,MAAM,UAAU,GAAG;AACzD,YAAM,IAAI;AAAA,QACR,oBAAoB,MAAM,OAAO;AAAA,MACnC;AAAA,IACF;AAAA,EACF;AAGA,MACE,MAAM,aAAa,UACnB,MAAM,YAAY,UAClB,MAAM,WAAW,MAAM,SACvB;AACA,UAAM,IAAI;AAAA,MACR,mCAAmC,MAAM,QAAQ,4BAA4B,MAAM,OAAO;AAAA,IAC5F;AAAA,EACF;AAGA,MAAI,MAAM,YAAY,QAAW;AAC/B,QAAI,OAAO,MAAM,YAAY,aAAa,MAAM,YAAY,SAAS;AACnE,YAAM,IAAI;AAAA,QACR,0BAA0B,MAAM,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,YAAY,QAAW;AAC/B,QAAI,OAAO,MAAM,YAAY,aAAa,MAAM,YAAY,SAAS;AACnE,YAAM,IAAI;AAAA,QACR,0BAA0B,MAAM,OAAO;AAAA,MACzC;AAAA,IACF;AAAA,EACF;AAGA,MAAI,MAAM,YAAY,QAAW;AAC/B,UAAM,qBAAqB,CAAC,QAAQ,QAAQ,YAAY,QAAQ,QAAQ,QAAQ,KAAK;AACrF,QAAI,CAAC,mBAAmB,SAAS,MAAM,OAAc,GAAG;AACtD,YAAM,IAAI;AAAA,QACR,0BAA0B,MAAM,OAAO,qBAAqB,mBAAmB,KAAK,IAAI,CAAC;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AACF;AASO,SAAS,sBACd,MACA,UAA+B,oBAAI,IAAI,GACjC;AAEN,MAAI,QAAQ,IAAI,IAAI,GAAG;AACrB,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,IAAI,IAAI;AAGhB,eAAa,KAAK,IAAI;AAGtB,gBAAc,KAAK,KAAK;AAGxB,aAAW,SAAS,KAAK,UAAU;AACjC,0BAAsB,OAAO,IAAI,IAAI,OAAO,CAAC;AAAA,EAC/C;AACF;AAQO,SAAS,cAAc,OAAgC;AAE5D,MAAI,CAAC,MAAM,WAAW,OAAO,MAAM,QAAQ,UAAU,YAAY,OAAO,MAAM,QAAQ,UAAU,UAAU;AACxG,UAAM,IAAI,gBAAgB,iEAAiE;AAAA,EAC7F;AAGA,MAAI,CAAC,MAAM,YAAY,CAAC,MAAM,SAAS,aAAa;AAClD,UAAM,IAAI,gBAAgB,oDAAoD;AAAA,EAChF;AAGA,QAAM,YAAY,IAAI,KAAK,MAAM,SAAS,WAAW;AACrD,MAAI,MAAM,UAAU,QAAQ,CAAC,GAAG;AAC9B,UAAM,IAAI;AAAA,MACR,kCAAkC,MAAM,SAAS,WAAW;AAAA,IAC9D;AAAA,EACF;AAGA,MAAI,CAAC,MAAM,MAAM;AACf,UAAM,IAAI,gBAAgB,8BAA8B;AAAA,EAC1D;AAEA,wBAAsB,MAAM,IAAI;AAClC;;;AC5IA,SAAS,eAA8C,KAAW;AAChE,MAAI,QAAQ,QAAQ,OAAO,QAAQ,UAAU;AAC3C,WAAO;AAAA,EACT;AAEA,MAAI,MAAM,QAAQ,GAAG,GAAG;AACtB,WAAO,IAAI,IAAI,cAAc;AAAA,EAC/B;AAEA,QAAM,SAA8B,CAAC;AACrC,QAAM,OAAO,OAAO,KAAK,GAAG,EAAE,KAAK;AAEnC,aAAW,OAAO,MAAM;AACtB,UAAM,QAAQ,IAAI,GAAG;AACrB,WAAO,GAAG,IAAI,OAAO,UAAU,YAAY,UAAU,OACjD,eAAe,KAAK,IACpB;AAAA,EACN;AAEA,SAAO;AACT;AAYO,SAAS,eACd,OACA,UAAgC,CAAC,GACzB;AACR,QAAM,EAAE,SAAS,OAAO,WAAW,KAAK,IAAI;AAG5C,MAAI,UAAU;AACZ,kBAAc,KAAK;AAAA,EACrB;AAGA,QAAM,SAAS,eAAe,KAAK;AAGnC,SAAO,SACH,KAAK,UAAU,QAAQ,MAAM,CAAC,IAC9B,KAAK,UAAU,MAAM;AAC3B;AAWO,SAAS,iBACd,MACA,UAAkC,CAAC,GAChB;AACnB,QAAM,EAAE,WAAW,KAAK,IAAI;AAG5B,QAAM,QAAQ,KAAK,MAAM,IAAI;AAG7B,MAAI,UAAU;AACZ,kBAAc,KAAK;AAAA,EACrB;AAEA,SAAO;AACT;AA8BO,SAAS,YAAY,GAAsB,GAA+B;AAG/E,QAAM,QAAQ,eAAe,GAAG,EAAE,UAAU,MAAM,CAAC;AACnD,QAAM,QAAQ,eAAe,GAAG,EAAE,UAAU,MAAM,CAAC;AACnD,SAAO,UAAU;AACnB;;;ACnJA,OAAO,QAAQ;AAwBf,IAAM,WAAW,CAAC,MAAsB;AAGjC,SAAS,eAAe,QAAsC;AACnE,SAAO,OAAO,UAAU;AAC1B;AAGO,SAAS,aAAa,SAAkC;AAC7D,MAAI,CAAC,SAAS;AACZ,WAAO;AAAA,MACL,OAAO;AAAA,MACP,SAAS;AAAA,MACT,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS;AAAA,MACT,OAAO;AAAA,MACP,KAAK;AAAA,MACL,UAAU;AAAA,MACV,WAAW;AAAA,MACX,aAAa;AAAA,MACb,eAAe;AAAA,MACf,aAAa;AAAA,MACb,MAAM;AAAA,MACN,SAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,GAAG;AAAA,IACV,SAAS,GAAG;AAAA,IACZ,MAAM,GAAG;AAAA,IACT,SAAS,GAAG;AAAA,IACZ,SAAS,CAAC,MAAc,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IAC1C,OAAO,CAAC,MAAc,GAAG,KAAK,GAAG,KAAK,CAAC,CAAC;AAAA,IACxC,KAAK,GAAG;AAAA,IACR,UAAU,GAAG;AAAA,IACb,WAAW,GAAG;AAAA,IACd,aAAa,CAAC,MAAc,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;AAAA,IAC/C,eAAe,CAAC,MAAc,GAAG,KAAK,GAAG,MAAM,CAAC,CAAC;AAAA,IACjD,aAAa,GAAG;AAAA,IAChB,MAAM,GAAG;AAAA,IACT,SAAS;AAAA,EACX;AACF;;;AClDO,SAAS,WAAW,OAA0B,UAA4B;AAC/E,QAAM,IAAI,aAAa,YAAY,KAAK;AACxC,QAAM,gBAA0B,CAAC;AACjC,iBAAe,MAAM,MAAM,eAAe,CAAC;AAC3C,SAAO,cAAc,KAAK,IAAI;AAChC;AASA,SAAS,eAAe,MAAsB,eAAyB,GAAyB;AAC9F,QAAM,eAAe,eAAe,MAAM,CAAC;AAC3C,MAAI,cAAc;AAChB,kBAAc,KAAK,YAAY;AAAA,EACjC;AAGA,aAAW,SAAS,KAAK,UAAU;AACjC,mBAAe,OAAO,eAAe,CAAC;AAAA,EACxC;AACF;AASA,SAAS,eAAe,MAAsB,GAA2B;AACvE,QAAM,QAAkB,CAAC;AAGzB,MAAI,KAAK,MAAM;AACb,UAAM,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,EACrC;AAGA,QAAM,WAAW,eAAe,IAAI;AACpC,MAAI,UAAU;AACZ,UAAM,KAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,EACjC;AAGA,QAAM,YAAY,iBAAiB,IAAI;AACvC,MAAI,WAAW;AACb,UAAM,KAAK,EAAE,UAAU,SAAS,CAAC;AAAA,EACnC;AAGA,MAAI,KAAK,OAAO;AACd,UAAM,YAAY,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,OAAO;AAC9D,QAAI,WAAW;AACb,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAGA,MAAI,KAAK,aAAa;AACpB,UAAM,KAAK,EAAE,YAAY,KAAK,WAAW,CAAC;AAAA,EAC5C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAQA,SAAS,eAAe,MAA8B;AACpD,QAAM,OAAO,KAAK;AAElB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,UAAI,KAAK,MAAM,OAAO;AACpB,eAAO,iBAAiB,KAAK,MAAM,KAAK;AAAA,MAC1C;AACA,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO,KAAK,OAAO,aAAa;AAAA,IAElC,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAQA,SAAS,iBAAiB,MAA8B;AACtD,QAAM,SAAmB,CAAC;AAG1B,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,WAAW;AAAA,EAC5D;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,cAAc;AAAA,IAC5B,OAAO;AACL,aAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,IAC5D;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,cAAc;AAAA,IAC5B,OAAO;AACL,aAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,IAC5D;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,cAAc;AAAA,EAC/D;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,UAAU;AAAA,EACxB;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,WAAW;AAAA,EACzB;AAGA,MAAI,KAAK,MAAM,MAAM;AACnB,WAAO,KAAK,MAAM;AAAA,EACpB;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,QAAI,KAAK,MAAM,YAAY,QAAQ;AACjC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,YAAY;AAC5C,aAAO,KAAK,kBAAkB;AAAA,IAChC,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,WAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,EAC5D;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;;;ACpSO,SAAS,WAAW,OAA0B,UAA4B;AAC/E,QAAM,IAAI,aAAa,YAAY,KAAK;AACxC,QAAM,gBAA0B,CAAC;AACjC,iBAAe,MAAM,MAAM,eAAe,CAAC;AAC3C,SAAO,cAAc,KAAK,IAAI;AAChC;AASA,SAAS,eAAe,MAAsB,eAAyB,GAAyB;AAC9F,QAAM,eAAe,eAAe,MAAM,CAAC;AAC3C,MAAI,cAAc;AAChB,kBAAc,KAAK,YAAY;AAAA,EACjC;AAGA,aAAW,SAAS,KAAK,UAAU;AACjC,mBAAe,OAAO,eAAe,CAAC;AAAA,EACxC;AACF;AASA,SAAS,eAAe,MAAsB,GAA2B;AACvE,QAAM,QAAkB,CAAC;AAGzB,MAAI,KAAK,MAAM;AACb,UAAM,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,EACrC;AAGA,QAAM,WAAW,eAAe,IAAI;AACpC,MAAI,UAAU;AACZ,UAAM,KAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,EACjC;AAGA,QAAM,YAAY,iBAAiB,IAAI;AACvC,MAAI,WAAW;AACb,UAAM,KAAK,EAAE,UAAU,SAAS,CAAC;AAAA,EACnC;AAGA,MAAI,KAAK,OAAO;AACd,UAAM,YAAY,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,OAAO;AAC9D,QAAI,WAAW;AACb,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAGA,MAAI,KAAK,aAAa;AACpB,UAAM,KAAK,EAAE,YAAY,KAAK,WAAW,CAAC;AAAA,EAC5C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAQA,SAAS,eAAe,MAA8B;AACpD,QAAM,OAAO,KAAK;AAElB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AACH,UAAI,KAAK,MAAM,OAAO;AACpB,eAAO,WAAW,KAAK,MAAM,KAAK;AAAA,MACpC;AACA,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK,SAAS;AACZ,YAAM,OAAO,KAAK,SAAS,OAAO,OAAK,EAAE,SAAS,KAAK;AACvD,YAAM,WAAW,KAAK;AACtB,YAAM,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,SAAS,SAAS;AAC7D,aAAO,cAAc,QAAQ,aAAa,QAAQ;AAAA,IACpD;AAAA,IAEA,KAAK,OAAO;AACV,YAAM,MAAM,KAAK,MAAM,YAAY;AACnC,aAAO,OAAO,GAAG;AAAA,IACnB;AAAA,IAEA,KAAK,QAAQ;AACX,YAAM,MAAM,KAAK,MAAM,YAAY;AACnC,aAAO,UAAU,GAAG;AAAA,IACtB;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO,KAAK,OAAO,UAAU;AAAA,IAE/B,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAQA,SAAS,iBAAiB,MAA8B;AACtD,QAAM,SAAmB,CAAC;AAG1B,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,WAAW;AAAA,EAC5D;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,mBAAmB;AAAA,IACjC,WAAW,KAAK,MAAM,SAAS;AAC7B,aAAO,KAAK,SAAS;AAAA,IACvB,OAAO;AACL,aAAO,KAAK,aAAa;AAAA,IAC3B;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,mBAAmB;AAAA,IACjC,WAAW,KAAK,MAAM,SAAS;AAC7B,aAAO,KAAK,SAAS;AAAA,IACvB,OAAO;AACL,aAAO,KAAK,aAAa;AAAA,IAC3B;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,cAAc;AAAA,EAC/D;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,aAAa;AAAA,EAC3B;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,WAAO,KAAK,eAAe;AAAA,EAC7B;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,UAAU;AAAA,EACxB;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,WAAW;AAAA,EACzB;AAGA,MAAI,KAAK,MAAM,MAAM;AACnB,WAAO,KAAK,MAAM;AAAA,EACpB;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,YAAQ,KAAK,MAAM,SAAS;AAAA,MAC1B,KAAK;AACH,eAAO,KAAK,cAAc;AAC1B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,cAAc;AAC1B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,kBAAkB;AAC9B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,cAAc;AAC1B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,cAAc;AAC1B;AAAA,MACF,KAAK;AACH,eAAO,KAAK,SAAS;AACrB;AAAA,IACJ;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,WAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,EAC5D;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;;;AC3TO,SAAS,gBAAgB,OAA0B,UAA4B;AACpF,QAAM,IAAI,aAAa,YAAY,KAAK;AACxC,QAAM,gBAA0B,CAAC;AACjC,sBAAoB,MAAM,MAAM,eAAe,CAAC;AAChD,SAAO,cAAc,KAAK,IAAI;AAChC;AASA,SAAS,oBAAoB,MAAsB,eAAyB,GAAyB;AACnG,QAAM,eAAe,oBAAoB,MAAM,CAAC;AAChD,MAAI,cAAc;AAChB,kBAAc,KAAK,YAAY;AAAA,EACjC;AAGA,aAAW,SAAS,KAAK,UAAU;AACjC,wBAAoB,OAAO,eAAe,CAAC;AAAA,EAC7C;AACF;AASA,SAAS,oBAAoB,MAAsB,GAA2B;AAC5E,QAAM,QAAkB,CAAC;AAGzB,QAAM,YAAY,wBAAwB,KAAK,IAAI;AAEnD,MAAI,WAAW;AAEb,UAAM,WAAW,oBAAoB,IAAI;AACzC,QAAI,UAAU;AACZ,YAAM,KAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,IACjC;AAGA,QAAI,KAAK,MAAM;AACb,YAAM,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,IACrC;AAAA,EACF,OAAO;AAEL,QAAI,KAAK,MAAM;AACb,YAAM,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC;AAAA,IACrC;AAGA,UAAM,WAAW,oBAAoB,IAAI;AACzC,QAAI,UAAU;AACZ,YAAM,KAAK,EAAE,SAAS,QAAQ,CAAC;AAAA,IACjC;AAAA,EACF;AAGA,QAAM,YAAY,sBAAsB,IAAI;AAC5C,MAAI,WAAW;AACb,UAAM,KAAK,EAAE,UAAU,SAAS,CAAC;AAAA,EACnC;AAGA,MAAI,KAAK,OAAO;AACd,UAAM,YAAY,KAAK,MAAM,QAAQ,OAAO,KAAK,MAAM,OAAO;AAC9D,QAAI,WAAW;AACb,YAAM,KAAK,SAAS;AAAA,IACtB;AAAA,EACF;AAGA,MAAI,KAAK,aAAa;AACpB,UAAM,KAAK,EAAE,YAAY,KAAK,WAAW,CAAC;AAAA,EAC5C;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAUA,SAAS,wBAAwB,MAA+B;AAC9D,SAAO,SAAS,aACT,SAAS,gBACT,SAAS,UACT,SAAS,YACT,SAAS,iBACT,SAAS,mBACT,SAAS,YACT,SAAS,UACT,SAAS,YACT,SAAS,gBACT,SAAS,YACT,SAAS,YACT,SAAS,WACT,SAAS;AAClB;AAQA,SAAS,oBAAoB,MAA8B;AACzD,QAAM,OAAO,KAAK;AAElB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,UAAI,KAAK,MAAM,OAAO;AACpB,eAAO,iBAAiB,KAAK,MAAM,KAAK;AAAA,MAC1C;AACA,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AAEH,aAAO;AAAA,IAET,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK,SAAS;AACZ,YAAM,OAAO,KAAK,SAAS,OAAO,OAAK,EAAE,SAAS,KAAK;AACvD,YAAM,WAAW,KAAK;AACtB,YAAM,WAAW,KAAK,SAAS,IAAI,KAAK,CAAC,EAAE,SAAS,SAAS;AAC7D,aAAO,UAAU,QAAQ,UAAU,QAAQ;AAAA,IAC7C;AAAA,IAEA,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO,KAAK,OAAO,UAAU;AAAA,IAE/B,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET,KAAK;AACH,aAAO;AAAA,IAET;AACE,aAAO;AAAA,EACX;AACF;AAQA,SAAS,sBAAsB,MAA8B;AAC3D,QAAM,SAAmB,CAAC;AAG1B,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,WAAW;AAAA,EAC5D;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,OAAO;AAAA,IACrB,OAAO;AACL,aAAO,KAAK,KAAK,MAAM,UAAU,YAAY,WAAW;AAAA,IAC1D;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,QAAI,KAAK,MAAM,YAAY,SAAS;AAClC,aAAO,KAAK,OAAO;AAAA,IACrB,OAAO;AACL,aAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,IAC5D;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,aAAa,QAAW;AACrC,WAAO,KAAK,KAAK,MAAM,WAAW,aAAa,YAAY;AAAA,EAC7D;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,QAAQ;AAAA,EACtB;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,WAAO,KAAK,cAAc;AAAA,EAC5B;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,UAAU;AAAA,EACxB;AAGA,MAAI,KAAK,MAAM,UAAU;AACvB,WAAO,KAAK,WAAW;AAAA,EACzB;AAGA,MAAI,KAAK,MAAM,MAAM;AACnB,WAAO,KAAK,MAAM;AAAA,EACpB;AAGA,MAAI,KAAK,MAAM,SAAS;AACtB,QAAI,KAAK,MAAM,YAAY,QAAQ;AACjC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,YAAY;AAC5C,aAAO,KAAK,kBAAkB;AAAA,IAChC,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,cAAc;AAAA,IAC5B,WAAW,KAAK,MAAM,YAAY,QAAQ;AACxC,aAAO,KAAK,SAAS;AAAA,IACvB;AAAA,EACF;AAGA,MAAI,KAAK,MAAM,YAAY,QAAW;AACpC,WAAO,KAAK,KAAK,MAAM,UAAU,YAAY,aAAa;AAAA,EAC5D;AAEA,SAAO,OAAO,KAAK,IAAI;AACzB;;;ACrSO,SAAS,kBAAkB,OAA0B,UAA4B;AACtF,QAAM,SAAS,oBAAoB,KAAK;AACxC,SAAO,kBAAkB,QAAQ,OAAO,QAAQ;AAClD;AAQO,SAAS,oBAAoB,OAAuC;AACzE,QAAM,aAA8B;AAAA,IAClC,eAAe;AAAA,IACf,kBAAkB,CAAC;AAAA,IACnB,eAAe;AAAA,IACf,cAAc;AAAA,IACd,kBAAkB;AAAA,IAClB,gBAAgB;AAAA,IAChB,YAAY,oBAAI,IAAI;AAAA,EACtB;AAEA,QAAM,YAA8B,CAAC;AACrC,QAAM,WAA6B,CAAC;AACpC,QAAM,sBAAwC,CAAC;AAC/C,QAAM,SAA+B,CAAC;AAGtC,mBAAiB,MAAM,MAAM,YAAY,WAAW,UAAU,mBAAmB;AAGjF,uBAAqB,WAAW,MAAM;AACtC,sBAAoB,UAAU,MAAM;AACpC,0BAAwB,qBAAqB,MAAM;AAEnD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAKA,SAAS,iBACP,MACA,YACA,WACA,UACA,qBACM;AAEN,MAAI,KAAK,SAAS,WAAW;AAC3B,eAAW;AAGX,eAAW,iBAAiB,KAAK,IAAI,KAAK,WAAW,iBAAiB,KAAK,IAAI,KAAK,KAAK;AAGzF,QAAI,WAAW,KAAK,IAAI,GAAG;AACzB,iBAAW;AACX,gBAAU,KAAK,IAAI;AAAA,IACrB;AAGA,QAAI,KAAK,SAAS,WAAW;AAC3B,iBAAW;AACX,eAAS,KAAK,IAAI;AAAA,IACpB;AAGA,QAAI,cAAc,KAAK,IAAI,GAAG;AAC5B,iBAAW;AACX,0BAAoB,KAAK,IAAI;AAAA,IAC/B;AAGA,QAAI,KAAK,MAAM,WAAW;AACxB,iBAAW;AAAA,IACb;AAGA,WAAO,KAAK,KAAK,KAAK,EAAE,QAAQ,WAAS;AACvC,UAAI,KAAK,MAAM,KAAgC,MAAM,QAAW;AAC9D,mBAAW,WAAW,IAAI,KAAK;AAAA,MACjC;AAAA,IACF,CAAC;AAAA,EACH;AAGA,aAAW,SAAS,KAAK,UAAU;AACjC,qBAAiB,OAAO,YAAY,WAAW,UAAU,mBAAmB;AAAA,EAC9E;AACF;AAKA,SAAS,WAAW,MAA+B;AACjD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,IAAI;AACjB;AAKA,SAAS,cAAc,MAA+B;AACpD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,SAAS,IAAI;AACjB;AAKA,SAAS,qBAAqB,WAA6B,QAAoC;AAC7F,MAAI,UAAU,WAAW,GAAG;AAC1B,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,SAAS;AAAA,MACT,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AAGA,YAAU,QAAQ,cAAY;AAC5B,QAAI,CAAC,SAAS,QAAQ,CAAC,cAAc,UAAU,iBAAiB,MAAM,EAAE,SAAS,SAAS,IAAI,GAAG;AAC/F,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,SAAS,GAAG,SAAS,IAAI;AAAA,QACzB,YAAY,mBAAmB,SAAS,SAAS,eAAe,oBAAoB,kBAAkB,YAAY,SAAS,IAAI;AAAA,QAC/H,SAAS;AAAA,UACP,MAAM,SAAS;AAAA,UACf,MAAM,SAAS;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAGD,QAAM,kBAAkB,oBAAI,IAA8B;AAC1D,YAAU,QAAQ,cAAY;AAC5B,QAAI,CAAC,gBAAgB,IAAI,SAAS,IAAI,GAAG;AACvC,sBAAgB,IAAI,SAAS,MAAM,CAAC,CAAC;AAAA,IACvC;AACA,oBAAgB,IAAI,SAAS,IAAI,EAAG,KAAK,QAAQ;AAAA,EACnD,CAAC;AAED,kBAAgB,QAAQ,CAAC,OAAO,SAAS;AACvC,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,aAAa,MAAM,MAAM,OAAK,CAAC,EAAE,IAAI;AAC3C,YAAM,cAAc,MAAM,MAAM,OAAK,EAAE,SAAS,MAAM,CAAC,EAAE,IAAI;AAE7D,UAAI,cAAc,aAAa;AAC7B,eAAO,KAAK;AAAA,UACV,UAAU;AAAA,UACV,SAAS,YAAY,IAAI;AAAA,UACzB,YAAY,2DAA2D,IAAI;AAAA,QAC7E,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF,CAAC;AACH;AAKA,SAAS,oBAAoB,UAA4B,QAAoC;AAC3F,MAAI,SAAS,WAAW,GAAG;AACzB;AAAA,EACF;AAGA,QAAM,eAAe,SAAS,CAAC;AAC/B,MAAI,aAAa,MAAM,SAAS,aAAa,MAAM,UAAU,GAAG;AAC9D,WAAO,KAAK;AAAA,MACV,UAAU;AAAA,MACV,SAAS,qBAAqB,aAAa,MAAM,KAAK;AAAA,MACtD,YAAY,YAAY,aAAa,MAAM,KAAK;AAAA,MAChD,SAAS;AAAA,QACP,MAAM,aAAa;AAAA,QACnB,MAAM,aAAa;AAAA,MACrB;AAAA,IACF,CAAC;AAAA,EACH;AAGA,WAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,UAAM,YAAY,SAAS,IAAI,CAAC,EAAE,MAAM,SAAS;AACjD,UAAM,YAAY,SAAS,CAAC,EAAE,MAAM,SAAS;AAE7C,QAAI,YAAY,YAAY,GAAG;AAC7B,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,SAAS,iCAAiC,SAAS,iBAAiB,SAAS,cAAc,YAAY,CAAC;AAAA,QACxG,YAAY,WAAW,SAAS,QAAQ,YAAY,CAAC;AAAA,QACrD,SAAS;AAAA,UACP,MAAM,SAAS,CAAC,EAAE;AAAA,UAClB,MAAM,SAAS,CAAC,EAAE;AAAA,QACpB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAKA,SAAS,wBAAwB,UAA4B,QAAoC;AAC/F,WAAS,QAAQ,aAAW;AAE1B,QAAI,CAAC,QAAQ,MAAM;AACjB,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,SAAS,GAAG,QAAQ,IAAI;AAAA,QACxB,YAAY,QAAQ,SAAS,WACzB,6CACA,QAAQ,SAAS,SACjB,2CACA,qBAAqB,QAAQ,IAAI;AAAA,QACrC,SAAS;AAAA,UACP,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH;AAGA,QAAI,QAAQ,SAAS,aAAa,CAAC,QAAQ,MAAM;AAC/C,aAAO,KAAK;AAAA,QACV,UAAU;AAAA,QACV,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,SAAS;AAAA,UACP,MAAM,QAAQ;AAAA,UACd,MAAM,QAAQ;AAAA,QAChB;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAKA,SAAS,kBAAkB,QAAqB,OAA0B,UAA4B;AACpG,QAAM,IAAI,aAAa,YAAY,KAAK;AACxC,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,EAAE,MAAM,keAAkF,CAAC;AACtG,QAAM,KAAK,EAAE,MAAM,4FAAkF,CAAC;AACtG,QAAM,KAAK,EAAE,MAAM,keAAkF,CAAC;AACtG,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,EAAE,IAAI,aAAa,MAAM,SAAS,WAAW,EAAE,CAAC;AAC3D,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE,QAAQ,8BAAuB,CAAC;AAC7C,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE;AAEb,MAAI,OAAO,UAAU,WAAW,GAAG;AACjC,UAAM,KAAK,EAAE,MAAM,2BAAsB,CAAC;AAAA,EAC5C,OAAO;AACL,UAAM,KAAK,EAAE,QAAQ,UAAK,OAAO,UAAU,MAAM,oBAAoB,CAAC;AACtE,UAAM,KAAK,EAAE;AACb,WAAO,UAAU,QAAQ,cAAY;AACnC,YAAM,OAAO,SAAS,OAAO,IAAI,SAAS,IAAI,MAAM;AACpD,YAAM,KAAK,GAAG,SAAS,IAAI,IAAI,IAAI,EAAE;AAAA,IACvC,CAAC;AAAA,EACH;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE,QAAQ,6BAAsB,CAAC;AAC5C,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE;AAEb,MAAI,OAAO,SAAS,WAAW,GAAG;AAChC,UAAM,KAAK,EAAE,KAAK,0BAAqB,CAAC;AAAA,EAC1C,OAAO;AACL,UAAM,qBAAqB,OAAO,OAAO;AAAA,MAAK,OAC5C,EAAE,QAAQ,SAAS,SAAS,KAAK,EAAE,QAAQ,SAAS,IAAI,KAAK,EAAE,QAAQ,SAAS,IAAI;AAAA,IACtF;AACA,UAAM,KAAK,GAAG,qBAAqB,EAAE,MAAM,QAAG,IAAI,EAAE,QAAQ,QAAG,CAAC,IAAI,OAAO,SAAS,MAAM,qBAAqB,qBAAqB,0BAA0B,oBAAoB,EAAE;AACpL,UAAM,KAAK,EAAE;AAEb,WAAO,SAAS,QAAQ,aAAW;AACjC,YAAM,QAAQ,QAAQ,MAAM,SAAS;AACrC,YAAM,SAAS,KAAK,OAAO,QAAQ,CAAC;AACpC,YAAM,KAAK,GAAG,MAAM,IAAI,KAAK,KAAK,QAAQ,IAAI,GAAG;AAAA,IACnD,CAAC;AAAA,EACH;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE,QAAQ,gCAAyB,CAAC;AAC/C,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE;AAEb,MAAI,OAAO,oBAAoB,WAAW,GAAG;AAC3C,UAAM,KAAK,EAAE,KAAK,sCAAiC,CAAC;AAAA,EACtD,OAAO;AACL,UAAM,KAAK,EAAE,QAAQ,UAAK,OAAO,oBAAoB,MAAM,+BAA+B,CAAC;AAC3F,UAAM,KAAK,EAAE;AAGb,UAAM,SAAS,oBAAI,IAA8B;AACjD,WAAO,oBAAoB,QAAQ,QAAM;AACvC,UAAI,CAAC,OAAO,IAAI,GAAG,IAAI,GAAG;AACxB,eAAO,IAAI,GAAG,MAAM,CAAC,CAAC;AAAA,MACxB;AACA,aAAO,IAAI,GAAG,IAAI,EAAG,KAAK,EAAE;AAAA,IAC9B,CAAC;AAED,WAAO,QAAQ,CAAC,UAAU,SAAS;AACjC,YAAM,KAAK,GAAG,IAAI,MAAM,SAAS,MAAM,IAAI;AAC3C,eAAS,QAAQ,QAAM;AACrB,cAAM,OAAO,GAAG,OAAO,IAAI,GAAG,IAAI,MAAM;AACxC,cAAM,SAAS,OAAO,KAAK,GAAG,KAAK,EAAE,OAAO,OAAK,GAAG,MAAM,CAA0B,MAAM,MAAS;AACnG,cAAM,WAAW,OAAO,SAAS,IAAI,KAAK,OAAO,KAAK,IAAI,CAAC,MAAM;AACjE,cAAM,KAAK,YAAO,IAAI,GAAG,QAAQ,EAAE;AAAA,MACrC,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACA,QAAM,KAAK,EAAE;AAGb,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE,QAAQ,8BAAuB,CAAC;AAC7C,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,8BAA8B,OAAO,WAAW,aAAa,EAAE;AAC1E,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,oBAAoB;AAC/B,SAAO,QAAQ,OAAO,WAAW,gBAAgB,EAC9C,KAAK,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,EAC1B,QAAQ,CAAC,CAAC,MAAM,KAAK,MAAM;AAC1B,UAAM,KAAK,EAAE,IAAI,YAAO,IAAI,KAAK,KAAK,EAAE,CAAC;AAAA,EAC3C,CAAC;AACH,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,EAAE,IAAI,uBAAuB,OAAO,WAAW,cAAc,EAAE,CAAC;AAC3E,QAAM,KAAK,EAAE;AAGb,MAAI,OAAO,OAAO,SAAS,GAAG;AAC5B,UAAM,KAAK,sdAAgF;AAC3F,UAAM,KAAK,EAAE,QAAQ,oCAA0B,CAAC;AAChD,UAAM,KAAK,sdAAgF;AAC3F,UAAM,KAAK,EAAE;AAEb,UAAM,SAAS,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,OAAO;AAC/D,UAAM,WAAW,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,SAAS;AACnE,UAAM,QAAQ,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,MAAM;AAE7D,QAAI,OAAO,SAAS,GAAG;AACrB,YAAM,KAAK,EAAE,MAAM,iBAAY,OAAO,MAAM,IAAI,CAAC;AACjD,aAAO,QAAQ,WAAS;AACtB,cAAM,KAAK,EAAE,MAAM,YAAO,MAAM,OAAO,EAAE,CAAC;AAC1C,YAAI,MAAM,YAAY;AACpB,gBAAM,KAAK,cAAS,MAAM,UAAU,EAAE;AAAA,QACxC;AAAA,MACF,CAAC;AACD,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,QAAI,SAAS,SAAS,GAAG;AACvB,YAAM,KAAK,EAAE,QAAQ,mBAAc,SAAS,MAAM,IAAI,CAAC;AACvD,eAAS,QAAQ,WAAS;AACxB,cAAM,KAAK,EAAE,QAAQ,YAAO,MAAM,OAAO,EAAE,CAAC;AAC5C,YAAI,MAAM,YAAY;AACpB,gBAAM,KAAK,cAAS,MAAM,UAAU,EAAE;AAAA,QACxC;AAAA,MACF,CAAC;AACD,YAAM,KAAK,EAAE;AAAA,IACf;AAEA,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,KAAK,EAAE,KAAK,gBAAW,MAAM,MAAM,IAAI,CAAC;AAC9C,YAAM,QAAQ,WAAS;AACrB,cAAM,KAAK,EAAE,KAAK,YAAO,MAAM,OAAO,EAAE,CAAC;AACzC,YAAI,MAAM,YAAY;AACpB,gBAAM,KAAK,cAAS,MAAM,UAAU,EAAE;AAAA,QACxC;AAAA,MACF,CAAC;AACD,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE,QAAQ,2BAAsB,CAAC;AAC5C,QAAM,KAAK,sdAAgF;AAC3F,QAAM,KAAK,EAAE;AAEb,QAAM,aAAa,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,OAAO,EAAE;AACrE,QAAM,eAAe,OAAO,OAAO,OAAO,OAAK,EAAE,aAAa,SAAS,EAAE;AAEzE,MAAI,eAAe,KAAK,iBAAiB,GAAG;AAC1C,UAAM,KAAK,EAAE,QAAQ,sCAAsC,CAAC;AAAA,EAC9D,WAAW,aAAa,GAAG;AACzB,UAAM,KAAK,sCAAsC;AACjD,UAAM,KAAK,EAAE,MAAM,YAAO,UAAU,WAAW,CAAC;AAChD,QAAI,eAAe,GAAG;AACpB,YAAM,KAAK,EAAE,QAAQ,YAAO,YAAY,aAAa,CAAC;AAAA,IACxD;AACA,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,kDAAkD;AAAA,EAC/D,OAAO;AACL,UAAM,KAAK,gDAAgD;AAC3D,UAAM,KAAK,EAAE,QAAQ,YAAO,YAAY,aAAa,CAAC;AAAA,EACxD;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;;;AC/dO,SAAS,uBACd,SACA,SACc;AACd,QAAM,UAAwB,CAAC;AAG/B,QAAM,WAAW,aAAa,SAAS,MAAM;AAC7C,QAAM,WAAW,aAAa,SAAS,MAAM;AAG7C,aAAW,CAAC,MAAM,IAAI,KAAK,UAAU;AACnC,QAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,CAAC,MAAM,IAAI,KAAK,UAAU;AACnC,QAAI,CAAC,SAAS,IAAI,IAAI,GAAG;AACvB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAGA,aAAW,CAAC,MAAM,OAAO,KAAK,UAAU;AACtC,UAAM,UAAU,SAAS,IAAI,IAAI;AACjC,QAAI,SAAS;AACX,YAAM,kBAAkB,aAAa,SAAS,OAAO;AACrD,UAAI,gBAAgB,SAAS,GAAG;AAC9B,gBAAQ,KAAK;AAAA,UACX,MAAM;AAAA,UACN;AAAA,UACA,SAAS;AAAA,QACX,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAGA,UAAQ,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAGnD,QAAM,UAAU;AAAA,IACd,OAAO,QAAQ,OAAO,OAAK,EAAE,SAAS,OAAO,EAAE;AAAA,IAC/C,SAAS,QAAQ,OAAO,OAAK,EAAE,SAAS,SAAS,EAAE;AAAA,IACnD,SAAS,QAAQ,OAAO,OAAK,EAAE,SAAS,SAAS,EAAE;AAAA,IACnD,OAAO,QAAQ;AAAA,EACjB;AAEA,SAAO,EAAE,SAAS,QAAQ;AAC5B;AASA,SAAS,aACP,MACA,MAC+B;AAC/B,QAAM,MAAM,oBAAI,IAA8B;AAG9C,MAAI,IAAI,MAAM,IAAI;AAGlB,OAAK,SAAS,QAAQ,CAAC,OAAO,UAAU;AACtC,UAAM,YAAY,GAAG,IAAI,aAAa,KAAK;AAC3C,UAAM,WAAW,aAAa,OAAO,SAAS;AAC9C,eAAW,CAACC,YAAW,SAAS,KAAK,UAAU;AAC7C,UAAI,IAAIA,YAAW,SAAS;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,SAAO;AACT;AASA,SAAS,aACP,SACA,SACkB;AAClB,QAAM,UAA4B,CAAC;AAGnC,MAAI,QAAQ,SAAS,QAAQ,MAAM;AACjC,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAGA,MAAI,QAAQ,SAAS,QAAQ,MAAM;AACjC,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAGA,MAAI,QAAQ,gBAAgB,QAAQ,aAAa;AAC/C,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,YAAY,QAAQ,OAAO,QAAQ,KAAK,GAAG;AAC9C,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,YAAY,QAAQ,OAAO,QAAQ,KAAK,GAAG;AAC9C,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAGA,MAAI,CAAC,WAAW,QAAQ,OAAO,QAAQ,KAAK,GAAG;AAC7C,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,UAAU,QAAQ;AAAA,MAClB,UAAU,QAAQ;AAAA,IACpB,CAAC;AAAA,EACH;AAEA,SAAO;AACT;AAKA,SAAS,YACP,GACA,GACS;AACT,MAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAC/C,MAAI,MAAM,UAAa,MAAM,OAAW,QAAO;AAE/C,SACE,EAAE,YAAY,EAAE,WAChB,EAAE,QAAQ,EAAE,OACZ,EAAE,QAAQ,EAAE,OACZ,EAAE,SAAS,EAAE;AAEjB;AAKA,SAAS,YACP,GACA,GACS;AAET,QAAM,OAAO,oBAAI,IAAI,CAAC,GAAG,OAAO,KAAK,CAAC,GAAG,GAAG,OAAO,KAAK,CAAC,CAAC,CAAC;AAE3D,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,EAAE,GAA4B;AAC7C,UAAM,SAAS,EAAE,GAA4B;AAE7C,QAAI,WAAW,QAAQ;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,WACP,GACA,GACS;AACT,SACE,EAAE,cAAc,EAAE,aAClB,EAAE,aAAa,EAAE;AAErB;;;ACvNO,SAAS,iBAAiB,MAA4B;AAC3D,SAAO,KAAK,UAAU,MAAM,MAAM,CAAC;AACrC;AAQO,SAAS,iBAAiB,MAA4B;AAC3D,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,iCAAiC;AAC5C,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,kBAAkB,KAAK,QAAQ,KAAK,EAAE;AACjD,QAAM,KAAK,YAAY,KAAK,QAAQ,KAAK,EAAE;AAC3C,QAAM,KAAK,cAAc,KAAK,QAAQ,OAAO,EAAE;AAC/C,QAAM,KAAK,cAAc,KAAK,QAAQ,OAAO,EAAE;AAC/C,QAAM,KAAK,EAAE;AAEb,MAAI,KAAK,QAAQ,WAAW,GAAG;AAC7B,UAAM,KAAK,sBAAsB;AACjC,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB;AAGA,QAAM,QAAQ,KAAK,QAAQ,OAAO,OAAK,EAAE,SAAS,OAAO;AACzD,QAAM,UAAU,KAAK,QAAQ,OAAO,OAAK,EAAE,SAAS,SAAS;AAC7D,QAAM,UAAU,KAAK,QAAQ,OAAO,OAAK,EAAE,SAAS,SAAS;AAG7D,MAAI,MAAM,SAAS,GAAG;AACpB,UAAM,KAAK,qBAAqB;AAChC,eAAW,UAAU,OAAO;AAC1B,YAAM,KAAK,KAAK,OAAO,IAAI,EAAE;AAC7B,YAAM,KAAK,WAAW,OAAO,MAAM,IAAI,EAAE;AACzC,YAAM,KAAK,YAAY,OAAO,MAAM,IAAI,GAAG;AAC3C,UAAI,OAAO,MAAM,aAAa;AAC5B,cAAM,KAAK,mBAAmB,OAAO,KAAK,WAAW,GAAG;AAAA,MAC1D;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,uBAAuB;AAClC,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,KAAK,OAAO,IAAI,EAAE;AAC7B,YAAM,KAAK,WAAW,OAAO,MAAM,IAAI,EAAE;AACzC,YAAM,KAAK,YAAY,OAAO,MAAM,IAAI,GAAG;AAC3C,UAAI,OAAO,MAAM,aAAa;AAC5B,cAAM,KAAK,mBAAmB,OAAO,KAAK,WAAW,GAAG;AAAA,MAC1D;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAGA,MAAI,QAAQ,SAAS,GAAG;AACtB,UAAM,KAAK,uBAAuB;AAClC,eAAW,UAAU,SAAS;AAC5B,YAAM,KAAK,KAAK,OAAO,IAAI,EAAE;AAC7B,UAAI,OAAO,SAAS;AAClB,mBAAW,cAAc,OAAO,SAAS;AACvC,gBAAM,KAAK,KAAK,qBAAqB,UAAU,CAAC,EAAE;AAAA,QACpD;AAAA,MACF;AACA,YAAM,KAAK,EAAE;AAAA,IACf;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AAKA,SAAS,qBAAqB,QAAgC;AAC5D,QAAM,SAAS,YAAY,OAAO,QAAQ;AAC1C,QAAM,SAAS,YAAY,OAAO,QAAQ;AAC1C,SAAO,GAAG,OAAO,QAAQ,KAAK,MAAM,WAAM,MAAM;AAClD;AAKA,SAAS,YAAY,OAAwB;AAC3C,MAAI,UAAU,OAAW,QAAO;AAChC,MAAI,UAAU,KAAM,QAAO;AAC3B,MAAI,OAAO,UAAU,SAAU,QAAO,IAAI,KAAK;AAC/C,MAAI,OAAO,UAAU,UAAU;AAE7B,UAAM,OAAO,KAAK,UAAU,KAAK;AACjC,QAAI,KAAK,SAAS,IAAI;AACpB,aAAO,KAAK,UAAU,GAAG,EAAE,IAAI;AAAA,IACjC;AACA,WAAO;AAAA,EACT;AACA,SAAO,OAAO,KAAK;AACrB;;;AClDO,SAAS,YACd,MACA,SACA,UACe;AACf,QAAM,WAAqB,CAAC;AAI5B,QAAM,WAAW,eAAe,QAAQ,MAAM,KAAK,QAAQ,WAAW,UAAU,CAAC,QAAQ;AAEzF,MAAI;AAEF,QAAI,QAAQ,QAAQ,UAAU;AAC5B,aAAO,YAAY,MAAM,UAAU,SAAS,UAAU,QAAQ;AAAA,IAChE;AAGA,QAAI,QAAQ,UAAU;AACpB,aAAO,kBAAkB,MAAM,SAAS,QAAQ;AAAA,IAClD;AAGA,WAAO,cAAc,MAAM,SAAS,UAAU,QAAQ;AAAA,EACxD,SAAS,OAAO;AACd,QAAI,iBAAiB,OAAO;AAC1B,aAAO;AAAA,QACL,QAAQ,UAAU,MAAM,OAAO;AAAA,QAC/B,UAAU;AAAA;AAAA,QACV;AAAA,MACF;AAAA,IACF;AACA,UAAM;AAAA,EACR;AACF;AAKA,SAAS,cACP,MACA,SACA,UACA,UACe;AAEf,QAAM,MAAM,UAAU,IAAI;AAG1B,MAAI,IAAI,SAAS,SAAS,GAAG;AAC3B,aAAS,KAAK,GAAG,IAAI,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAAA,EACnD;AAGA,MAAI;AAEJ,MAAI,QAAQ,UAAU;AAEpB,UAAM,UAAU,mCAAmC,IAAI,SAAS,MAAM,QAAQ,QAAQ;AAEtF,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO;AAAA,QACL,QAAQ,sCAAsC,QAAQ,QAAQ;AAAA,QAC9D,UAAU;AAAA,QACV;AAAA,MACF;AAAA,IACF;AAGA,YAAQ,QAAQ,CAAC,EAAE;AAGnB,eAAW,UAAU,SAAS;AAC5B,UAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,iBAAS,KAAK,GAAG,OAAO,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAAA,MACtD;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,SAAS,uBAAuB,IAAI,SAAS,IAAI;AACvD,YAAQ,OAAO;AAEf,QAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,eAAS,KAAK,GAAG,OAAO,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAAA,IACtD;AAAA,EACF;AAGA,QAAM,SAAS,aAAa,OAAO,SAAS,QAAQ;AAEpD,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACF;AAKA,SAAS,YACP,OACA,OACA,SACA,UACA,WACe;AAEf,QAAM,OAAO,UAAU,KAAK;AAC5B,QAAM,OAAO,UAAU,KAAK;AAG5B,WAAS,KAAK,GAAG,KAAK,SAAS,IAAI,OAAK,EAAE,OAAO,GAAG,GAAG,KAAK,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAGxF,QAAM,UAAU,uBAAuB,KAAK,SAAS,IAAI;AACzD,QAAM,UAAU,uBAAuB,KAAK,SAAS,IAAI;AAEzD,WAAS,KAAK,GAAG,QAAQ,SAAS,IAAI,OAAK,EAAE,OAAO,GAAG,GAAG,QAAQ,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAG9F,QAAM,OAAO,uBAAuB,QAAQ,MAAM,MAAM,QAAQ,MAAM,IAAI;AAG1E,MAAI;AACJ,MAAI,QAAQ,WAAW,QAAQ;AAC7B,aAAS,iBAAiB,IAAI;AAAA,EAChC,OAAO;AACL,aAAS,iBAAiB,IAAI;AAAA,EAChC;AAEA,SAAO;AAAA,IACL;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACF;AAKA,SAAS,kBACP,MACA,UACA,UACe;AAEf,QAAM,MAAM,UAAU,IAAI;AAC1B,WAAS,KAAK,GAAG,IAAI,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAEjD,QAAM,SAAS,uBAAuB,IAAI,SAAS,IAAI;AACvD,WAAS,KAAK,GAAG,OAAO,SAAS,IAAI,OAAK,EAAE,OAAO,CAAC;AAEpD,QAAM,QAAQ,OAAO;AAGrB,QAAM,aAAa,eAAe,KAAK;AAGvC,QAAM,eAAe,iBAAiB,UAAU;AAGhD,QAAM,UAAU,YAAY,OAAO,YAAY;AAE/C,MAAI,SAAS;AACX,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF,OAAO;AACL,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,UAAU;AAAA,MACV;AAAA,IACF;AAAA,EACF;AACF;AAKA,SAAS,aAAa,OAA0B,SAAqB,UAA2B;AAC9F,QAAM,EAAE,QAAQ,aAAa,IAAI;AAGjC,MAAI,WAAW,SAAS;AACtB,WAAO,kBAAkB,OAAO,QAAQ;AAAA,EAC1C;AAGA,MAAI,WAAW,QAAQ;AACrB,WAAO,eAAe,KAAK;AAAA,EAC7B;AAGA,MAAI,WAAW,QAAQ;AACrB,WAAO,yBAAyB,OAAO,cAAc,QAAQ;AAAA,EAC/D;AAGA,MAAI,WAAW,QAAQ;AACrB,UAAM,OAAO,eAAe,KAAK;AACjC,UAAM,OAAO,yBAAyB,OAAO,cAAc,QAAQ;AACnE,UAAM,IAAI,aAAa,QAAQ;AAC/B,WAAO,GAAG,EAAE,cAAc,qBAAqB,CAAC;AAAA,EAAK,IAAI;AAAA;AAAA,EAAO,EAAE,cAAc,8BAA8B,CAAC;AAAA,EAAK,IAAI;AAAA,EAC1H;AAEA,QAAM,IAAI,MAAM,mBAAmB,MAAM,EAAE;AAC7C;AAKA,SAAS,yBACP,OACA,cACA,UACQ;AACR,MAAI,iBAAiB,OAAO;AAC1B,UAAM,OAAO,WAAW,OAAO,QAAQ;AACvC,UAAM,OAAO,WAAW,OAAO,QAAQ;AACvC,UAAM,YAAY,gBAAgB,OAAO,QAAQ;AACjD,UAAM,IAAI,aAAa,QAAQ;AAE/B,WAAO;AAAA,MACL,EAAE,cAAc,cAAc;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,EAAE,cAAc,cAAc;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,EAAE,cAAc,mBAAmB;AAAA,MACnC;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACb;AAEA,UAAQ,cAAc;AAAA,IACpB,KAAK;AACH,aAAO,WAAW,OAAO,QAAQ;AAAA,IACnC,KAAK;AACH,aAAO,WAAW,OAAO,QAAQ;AAAA,IACnC,KAAK;AACH,aAAO,gBAAgB,OAAO,QAAQ;AAAA,IACxC;AACE,YAAM,IAAI,MAAM,0BAA0B,YAAY,EAAE;AAAA,EAC5D;AACF;AAKO,SAAS,eAAe,UAAoB,UAA4B;AAC7E,MAAI,SAAS,WAAW,GAAG;AACzB,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,aAAa,YAAY,KAAK;AAExC,QAAM,SAAS,WACX,EAAE,QAAQ,EAAE,KAAK,kBAAkB,CAAC,IACpC;AAEJ,QAAM,QAAQ;AAAA,IACZ;AAAA,IACA;AAAA,IACA,GAAG,SAAS,IAAI,OAAK,WAAW,GAAG,EAAE,QAAQ,cAAI,CAAC,KAAK,CAAC,KAAK,iBAAO,CAAC,EAAE;AAAA,IACvE;AAAA,EACF;AAEA,SAAO,MAAM,KAAK,IAAI;AACxB;AASO,SAAS,aACd,WACA,SACoB;AACpB,QAAM,UAAyB,CAAC;AAChC,QAAM,cAAwB,CAAC;AAC/B,MAAI,YAAY;AAGhB,aAAW,YAAY,WAAW;AAChC,QAAI;AAEF,YAAM,EAAE,cAAAC,cAAa,IAAI,UAAQ,IAAI;AACrC,YAAM,OAAOA,cAAa,UAAU,OAAO;AAG3C,YAAM,SAAS,YAAY,MAAM,OAAO;AAExC,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,SAAS,OAAO,aAAa;AAAA,QAC7B,QAAQ,OAAO;AAAA,QACf,UAAU,OAAO;AAAA,MACnB,CAAC;AAED,kBAAY,KAAK,GAAG,OAAO,QAAQ;AAEnC,UAAI,OAAO,aAAa,GAAG;AACzB,oBAAY;AAAA,MACd;AAAA,IACF,SAAS,OAAO;AAEd,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAE1E,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,SAAS;AAAA,QACT,OAAO;AAAA,QACP,UAAU,CAAC;AAAA,MACb,CAAC;AAED,kBAAY;AAAA,IACd;AAAA,EACF;AAGA,QAAM,SAAS,kBAAkB,SAAS,OAAO;AAEjD,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,UAAU,YAAY,IAAI;AAAA,IAC1B,UAAU;AAAA,EACZ;AACF;AAKA,SAAS,kBAAkB,SAAwB,UAA8B;AAC/E,QAAM,QAAkB,CAAC;AAGzB,QAAM,KAAK,kCAAkC;AAC7C,QAAM,KAAK,EAAE;AAGb,aAAW,UAAU,SAAS;AAC5B,UAAM,KAAK,SAAS,OAAO,QAAQ,EAAE;AAErC,QAAI,OAAO,SAAS;AAClB,YAAM,KAAK,wBAAmB;AAE9B,UAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,cAAM,KAAK,aAAa,OAAO,SAAS,MAAM,EAAE;AAAA,MAClD;AAEA,YAAM,KAAK,EAAE;AACb,YAAM,KAAK,gBAAgB;AAC3B,YAAM,KAAK,OAAO,UAAU,EAAE;AAAA,IAChC,OAAO;AACL,YAAM,KAAK,uBAAkB;AAC7B,YAAM,KAAK,UAAU,OAAO,KAAK,EAAE;AAAA,IACrC;AAEA,UAAM,KAAK,EAAE;AACb,UAAM,KAAK,KAAK;AAChB,UAAM,KAAK,EAAE;AAAA,EACf;AAGA,QAAM,eAAe,QAAQ,OAAO,OAAK,EAAE,OAAO,EAAE;AACpD,QAAM,YAAY,QAAQ,OAAO,OAAK,CAAC,EAAE,OAAO,EAAE;AAElD,QAAM,KAAK,iBAAiB;AAC5B,QAAM,KAAK,gBAAgB,QAAQ,MAAM,EAAE;AAC3C,QAAM,KAAK,eAAe,YAAY,EAAE;AACxC,QAAM,KAAK,WAAW,SAAS,EAAE;AAEjC,SAAO,MAAM,KAAK,IAAI;AACxB;;;AnBxaA,IAAMC,cAAa,cAAc,YAAY,GAAG;AAChD,IAAMC,aAAY,QAAQD,WAAU;AACpC,IAAM,cAAc,KAAK;AAAA,EACvBE,cAAa,KAAKD,YAAW,iBAAiB,GAAG,OAAO;AAC1D;AAEA,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,WAAW,EAChB,YAAY,4EAA4E,EACxF,QAAQ,YAAY,SAAS,iBAAiB,4BAA4B,EAC1E,WAAW,cAAc,0BAA0B;AAGtD,QACG,SAAS,cAAc,oCAAoC,EAC3D,OAAO,uBAAuB,oCAAoC,EAClE;AAAA,EACC;AAAA,EACA;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC;AAAA,EACC;AAAA,EACA;AACF,EACC,OAAO,OAAO,OAAO,eAAe;AACnC,MAAI;AAEF,UAAM,UAAU,gBAAgB,UAAU;AAC1C,UAAM,cAAc,WAAW,KAAK;AAGpC,kBAAc,WAAW;AAGzB,qBAAiB,SAAS,WAAW;AAGrC,sBAAkB,SAAS,WAAW;AAGtC,QAAI,QAAQ,SAAS,YAAY,UAAU,YAAY,OAAO,SAAS,GAAG;AACxE,YAAME,UAAS,aAAa,YAAY,QAAQ,OAAO;AAGvD,kBAAYA,QAAO,QAAQ,QAAQ,MAAM;AAGzC,UAAIA,QAAO,SAAS,SAAS,GAAG;AAC9B,gBAAQ,MAAM,eAAeA,QAAO,UAAU,eAAe,QAAQ,MAAM,CAAC,CAAC;AAAA,MAC/E;AAGA,cAAQ,KAAKA,QAAO,QAAQ;AAC5B;AAAA,IACF;AAGA,UAAM,aAAa,SAAS,YAAY,OAAO,YAAY,OAAO;AAClE,UAAM,OAAO,MAAM,QAAQ,QAAQ,UAAU;AAG7C,QAAI;AACJ,QAAI,QAAQ,MAAM;AAChB,iBAAW,SAAS,QAAQ,MAAM,KAAK;AAAA,IACzC;AAGA,UAAM,SAAS,YAAY,MAAM,SAAS,QAAQ;AAGlD,gBAAY,OAAO,QAAQ,QAAQ,MAAM;AAGzC,QAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,cAAQ,MAAM,eAAe,OAAO,UAAU,eAAe,QAAQ,MAAM,CAAC,CAAC;AAAA,IAC/E;AAGA,YAAQ,KAAK,OAAO,QAAQ;AAAA,EAC9B,SAAS,OAAO;AACd,QAAI,iBAAiB,aAAa;AAChC,cAAQ,MAAM,UAAU,MAAM,OAAO,EAAE;AACvC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,QAAI,iBAAiB,OAAO;AAC1B,cAAQ,MAAM,UAAU,MAAM,OAAO,EAAE;AACvC,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM;AAAA,EACR;AACF,CAAC;AAGH,QAAQ,YAAY,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CA8B5B;AAED,QAAQ,MAAM;","names":["readFileSync","model","childPath","readFileSync","__filename","__dirname","readFileSync","result"]}
|