@reticular/speakable 1.3.0 → 1.5.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 +124 -5
- package/dist/index.d.ts +768 -1
- package/dist/index.js +2831 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +340 -0
- package/dist/mcp.js.map +1 -1
- package/package.json +11 -2
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp.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/cli/colors.ts","../src/renderer/nvda-renderer.ts","../src/renderer/jaws-renderer.ts","../src/renderer/voiceover-renderer.ts","../src/renderer/narrator-renderer.ts","../src/renderer/audit-renderer.ts","../src/diff/diff-algorithm.ts","../src/diff/formatter.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Speakable MCP Server\n *\n * Model Context Protocol server that exposes Speakable's accessibility\n * analysis engine as tools for AI assistants.\n *\n * Tools:\n * - analyze_html: Predict screen reader output for HTML\n * - audit_html: Generate accessibility audit report\n * - diff_html: Compare two HTML snippets for accessibility changes\n *\n * Usage:\n * npx @reticular/speakable --mcp\n * # or directly:\n * speakable-mcp\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseHTML } from './parser/index.js';\nimport { buildAccessibilityTree, buildAccessibilityTreeWithSelector } from './extractor/index.js';\nimport { renderNVDA } from './renderer/nvda-renderer.js';\nimport { renderJAWS } from './renderer/jaws-renderer.js';\nimport { renderVoiceOver } from './renderer/voiceover-renderer.js';\nimport { renderNarrator } from './renderer/narrator-renderer.js';\nimport { renderAuditReport } from './renderer/audit-renderer.js';\nimport { diffAccessibilityTrees, formatDiffAsText } from './diff/index.js';\nimport type { AnnouncementModel } from './model/types.js';\n\n// --- Helpers ---\n\ntype ScreenReader = 'nvda' | 'jaws' | 'voiceover' | 'narrator' | 'all';\n\nfunction renderOutput(model: AnnouncementModel, screenReader: ScreenReader): string {\n if (screenReader === 'all') {\n return [\n '--- NVDA ---',\n renderNVDA(model),\n '',\n '--- JAWS ---',\n renderJAWS(model),\n '',\n '--- VoiceOver ---',\n renderVoiceOver(model),\n '',\n '--- Narrator ---',\n renderNarrator(model),\n ].join('\\n');\n }\n\n switch (screenReader) {\n case 'nvda': return renderNVDA(model);\n case 'jaws': return renderJAWS(model);\n case 'voiceover': return renderVoiceOver(model);\n case 'narrator': return renderNarrator(model);\n }\n}\n\nfunction analyzeHTML(html: string, screenReader: ScreenReader, selector?: string) {\n const { document, warnings: parseWarnings } = parseHTML(html);\n const body = document.body;\n\n if (!body) {\n return { output: '', warnings: ['Document has no body element.'], model: null };\n }\n\n const warnings: string[] = parseWarnings.map((w: { message: string }) => w.message);\n\n if (selector) {\n const results = buildAccessibilityTreeWithSelector(body, selector);\n for (const r of results) {\n warnings.push(...r.warnings.map((w: { message: string }) => w.message));\n }\n\n const outputs = results.map((r, i) => {\n const prefix = results.length > 1 ? `=== Element ${i + 1} ===\\n` : '';\n return prefix + renderOutput(r.model, screenReader);\n });\n\n return { output: outputs.join('\\n\\n'), warnings, model: results[0]?.model || null };\n }\n\n const { model, warnings: treeWarnings } = buildAccessibilityTree(body);\n warnings.push(...treeWarnings.map((w: { message: string }) => w.message));\n\n return { output: renderOutput(model, screenReader), warnings, model };\n}\n\n// --- MCP Server ---\n\nconst server = new McpServer({\n name: 'speakable',\n version: '1.0.0',\n});\n\n// Tool: analyze_html\nserver.tool(\n 'analyze_html',\n 'Predict how screen readers (NVDA, JAWS, VoiceOver, Narrator) will announce HTML content. Returns the predicted speech output line by line.',\n {\n html: z.string().describe('The HTML content to analyze'),\n screen_reader: z.enum(['nvda', 'jaws', 'voiceover', 'narrator', 'all']).default('all').describe('Which screen reader to simulate (default: all)'),\n selector: z.string().optional().describe('Optional CSS selector to focus analysis on specific elements'),\n },\n async ({ html, screen_reader, selector }) => {\n try {\n const { output, warnings } = analyzeHTML(html, screen_reader, selector);\n const warningText = warnings.length > 0 ? `\\n\\nWarnings:\\n${warnings.join('\\n')}` : '';\n return {\n content: [{ type: 'text', text: output + warningText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// Tool: audit_html\nserver.tool(\n 'audit_html',\n 'Generate an accessibility audit report for HTML content. Reports landmark structure, heading hierarchy, interactive elements, missing names, and issues with severity levels.',\n {\n html: z.string().describe('The HTML content to audit'),\n selector: z.string().optional().describe('Optional CSS selector to focus audit on specific elements'),\n },\n async ({ html, selector }) => {\n try {\n const { document, warnings: parseWarnings } = parseHTML(html);\n const body = document.body;\n\n if (!body) {\n return {\n content: [{ type: 'text', text: 'Error: Document has no body element.' }],\n isError: true,\n };\n }\n\n let model: AnnouncementModel;\n const warnings: string[] = parseWarnings.map((w: { message: string }) => w.message);\n\n if (selector) {\n const results = buildAccessibilityTreeWithSelector(body, selector);\n for (const r of results) {\n warnings.push(...r.warnings.map((w: { message: string }) => w.message));\n }\n if (results.length === 0) {\n return {\n content: [{ type: 'text', text: `No elements found matching selector: ${selector}` }],\n };\n }\n model = results[0].model;\n } else {\n const result = buildAccessibilityTree(body);\n warnings.push(...result.warnings.map((w: { message: string }) => w.message));\n model = result.model;\n }\n\n const audit = renderAuditReport(model);\n const warningText = warnings.length > 0 ? `\\n\\nParser warnings:\\n${warnings.join('\\n')}` : '';\n\n return {\n content: [{ type: 'text', text: audit + warningText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// Tool: diff_html\nserver.tool(\n 'diff_html',\n 'Compare two HTML versions and report accessibility changes. Shows added, removed, and changed nodes in the accessibility tree — useful for detecting regressions.',\n {\n before_html: z.string().describe('The original (before) HTML content'),\n after_html: z.string().describe('The updated (after) HTML content'),\n selector: z.string().optional().describe('Optional CSS selector to focus diff on specific elements'),\n },\n async ({ before_html, after_html, selector }) => {\n try {\n const beforeDoc = parseHTML(before_html);\n const afterDoc = parseHTML(after_html);\n\n if (!beforeDoc.document.body || !afterDoc.document.body) {\n return {\n content: [{ type: 'text', text: 'Error: One or both documents have no body element.' }],\n isError: true,\n };\n }\n\n let beforeModel: AnnouncementModel;\n let afterModel: AnnouncementModel;\n\n if (selector) {\n const beforeResults = buildAccessibilityTreeWithSelector(beforeDoc.document.body, selector);\n const afterResults = buildAccessibilityTreeWithSelector(afterDoc.document.body, selector);\n if (beforeResults.length === 0 || afterResults.length === 0) {\n return {\n content: [{ type: 'text', text: `No elements found matching selector: ${selector}` }],\n };\n }\n beforeModel = beforeResults[0].model;\n afterModel = afterResults[0].model;\n } else {\n beforeModel = buildAccessibilityTree(beforeDoc.document.body).model;\n afterModel = buildAccessibilityTree(afterDoc.document.body).model;\n }\n\n const diff = diffAccessibilityTrees(beforeModel.root, afterModel.root);\n\n if (diff.changes.length === 0) {\n return {\n content: [{ type: 'text', text: 'No accessibility changes detected between the two versions.' }],\n };\n }\n\n const summary = `+${diff.summary.added} added -${diff.summary.removed} removed ~${diff.summary.changed} changed\\n\\n`;\n const diffText = formatDiffAsText(diff);\n\n return {\n content: [{ type: 'text', text: summary + diffText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// --- Start server ---\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error('Speakable MCP server error:', error);\n process.exit(1);\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 * Maximum input size in bytes (10 MB).\n * Prevents denial-of-service from extremely large inputs.\n */\nconst MAX_INPUT_SIZE = 10 * 1024 * 1024;\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 or input exceeds size limit\n */\nexport function parseHTML(html: string): ParseResult {\n const warnings: ParsingWarning[] = [];\n\n // Input size validation\n const inputSize = Buffer.byteLength(html, 'utf-8');\n if (inputSize > MAX_INPUT_SIZE) {\n throw new ParsingError(\n `Input exceeds maximum size of ${MAX_INPUT_SIZE / (1024 * 1024)} MB (received ${(inputSize / (1024 * 1024)).toFixed(1)} MB). ` +\n `Use CSS selectors to analyze specific sections of large documents.`\n );\n }\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","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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n // Skip child that repeats parent name — recurse into grandchildren\n for (const grandchild of child.children) {\n renderNodeNVDA(grandchild, announcements, c);\n }\n continue;\n }\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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n for (const grandchild of child.children) {\n renderNodeJAWS(grandchild, announcements, c);\n }\n continue;\n }\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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n for (const grandchild of child.children) {\n renderNodeVoiceOver(grandchild, announcements, c);\n }\n continue;\n }\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 * Windows Narrator screen reader announcement renderer.\n * \n * Generates heuristic announcement text approximating Windows Narrator output.\n * This is NOT a perfect emulation - real Narrator 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 Narrator-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 Narrator-style announcement text\n */\nexport function renderNarrator(model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const announcements: string[] = [];\n renderNodeNarrator(model.root, announcements, c);\n return announcements.join('\\n');\n}\n\n/**\n * Recursively renders a node and its children as Narrator 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 renderNodeNarrator(node: AccessibleNode, announcements: string[], c: ColorFunctions): void {\n const announcement = formatNodeNarrator(node, c);\n if (announcement) {\n announcements.push(announcement);\n }\n\n // Recursively render children, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n // Skip child that repeats parent name — recurse into grandchildren\n for (const grandchild of child.children) {\n renderNodeNarrator(grandchild, announcements, c);\n }\n continue;\n }\n renderNodeNarrator(child, announcements, c);\n }\n}\n\n/**\n * Formats a single node as a Narrator 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 formatNodeNarrator(node: AccessibleNode, c: ColorFunctions): string {\n const parts: string[] = [];\n\n const roleFirst = shouldAnnounceRoleFirst(node.role);\n\n if (roleFirst) {\n // Role-first: role, name, state, value, description\n const roleText = formatRoleNarrator(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n } else {\n // Name-first: name, role, state, value, description\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n\n const roleText = formatRoleNarrator(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n }\n\n // Add states\n const stateText = formatStatesNarrator(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 * Narrator announces role first for links, headings, landmarks,\n * and structural containers.\n * \n * @param role - Role to check\n * @returns true if role should be announced first\n */\nfunction shouldAnnounceRoleFirst(role: AccessibleRole): boolean {\n const roleFirstRoles: AccessibleRole[] = [\n 'link',\n 'heading',\n 'navigation',\n 'main',\n 'banner',\n 'contentinfo',\n 'complementary',\n 'region',\n 'form',\n 'search',\n 'blockquote',\n 'figure',\n 'dialog',\n 'group',\n 'document',\n ];\n return roleFirstRoles.includes(role);\n}\n\n/**\n * Formats the role portion of a Narrator announcement.\n * \n * @param node - Node to format\n * @returns Role text or empty string\n */\nfunction formatRoleNarrator(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 'check box';\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';\n\n case 'main':\n return 'main';\n\n case 'banner':\n return 'banner';\n\n case 'contentinfo':\n return 'content info';\n\n case 'complementary':\n return 'complementary';\n\n case 'form':\n return 'form';\n\n case 'search':\n return 'search';\n\n case 'region':\n return 'region';\n\n case 'img':\n return 'image';\n\n case 'article':\n return 'article';\n\n case 'generic':\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 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 '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 'document';\n\n case 'application':\n return 'application';\n\n case 'separator':\n return 'separator';\n\n default:\n return role;\n }\n}\n\n/**\n * Formats the state portion of a Narrator announcement.\n * \n * @param node - Node to format\n * @returns State text or empty string\n */\nfunction formatStatesNarrator(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('partially selected');\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('partially 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('disabled');\n }\n\n // Invalid state\n if (node.state.invalid) {\n states.push('invalid');\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"],"mappings":"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","names":["model","shouldAnnounceRoleFirst","childPath"]}
|
|
1
|
+
{"version":3,"sources":["../src/mcp.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/cli/colors.ts","../src/renderer/nvda-renderer.ts","../src/renderer/jaws-renderer.ts","../src/renderer/voiceover-renderer.ts","../src/renderer/narrator-renderer.ts","../src/renderer/audit-renderer.ts","../src/diff/diff-algorithm.ts","../src/diff/formatter.ts","../src/runtime/verbosity-analyzer.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * Speakable MCP Server\n *\n * Model Context Protocol server that exposes Speakable's accessibility\n * analysis engine as tools for AI assistants.\n *\n * Tools:\n * - analyze_html: Predict screen reader output for HTML\n * - audit_html: Generate accessibility audit report\n * - diff_html: Compare two HTML snippets for accessibility changes\n *\n * Usage:\n * npx @reticular/speakable --mcp\n * # or directly:\n * speakable-mcp\n */\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport { z } from 'zod';\nimport { parseHTML } from './parser/index.js';\nimport { buildAccessibilityTree, buildAccessibilityTreeWithSelector } from './extractor/index.js';\nimport { renderNVDA } from './renderer/nvda-renderer.js';\nimport { renderJAWS } from './renderer/jaws-renderer.js';\nimport { renderVoiceOver } from './renderer/voiceover-renderer.js';\nimport { renderNarrator } from './renderer/narrator-renderer.js';\nimport { renderAuditReport } from './renderer/audit-renderer.js';\nimport { diffAccessibilityTrees, formatDiffAsText } from './diff/index.js';\nimport { analyzeVerbosity, formatVerbosityReport } from './runtime/verbosity-analyzer.js';\nimport type { AnnouncementModel } from './model/types.js';\nimport type { AccessibilityEvent } from './runtime/types.js';\n\n// --- Helpers ---\n\ntype ScreenReader = 'nvda' | 'jaws' | 'voiceover' | 'narrator' | 'all';\n\nfunction renderOutput(model: AnnouncementModel, screenReader: ScreenReader): string {\n if (screenReader === 'all') {\n return [\n '--- NVDA ---',\n renderNVDA(model),\n '',\n '--- JAWS ---',\n renderJAWS(model),\n '',\n '--- VoiceOver ---',\n renderVoiceOver(model),\n '',\n '--- Narrator ---',\n renderNarrator(model),\n ].join('\\n');\n }\n\n switch (screenReader) {\n case 'nvda': return renderNVDA(model);\n case 'jaws': return renderJAWS(model);\n case 'voiceover': return renderVoiceOver(model);\n case 'narrator': return renderNarrator(model);\n }\n}\n\nfunction analyzeHTML(html: string, screenReader: ScreenReader, selector?: string) {\n const { document, warnings: parseWarnings } = parseHTML(html);\n const body = document.body;\n\n if (!body) {\n return { output: '', warnings: ['Document has no body element.'], model: null };\n }\n\n const warnings: string[] = parseWarnings.map((w: { message: string }) => w.message);\n\n if (selector) {\n const results = buildAccessibilityTreeWithSelector(body, selector);\n for (const r of results) {\n warnings.push(...r.warnings.map((w: { message: string }) => w.message));\n }\n\n const outputs = results.map((r, i) => {\n const prefix = results.length > 1 ? `=== Element ${i + 1} ===\\n` : '';\n return prefix + renderOutput(r.model, screenReader);\n });\n\n return { output: outputs.join('\\n\\n'), warnings, model: results[0]?.model || null };\n }\n\n const { model, warnings: treeWarnings } = buildAccessibilityTree(body);\n warnings.push(...treeWarnings.map((w: { message: string }) => w.message));\n\n return { output: renderOutput(model, screenReader), warnings, model };\n}\n\n// --- MCP Server ---\n\nconst server = new McpServer({\n name: 'speakable',\n version: '1.0.0',\n});\n\n// Tool: analyze_html\nserver.tool(\n 'analyze_html',\n 'Predict how screen readers (NVDA, JAWS, VoiceOver, Narrator) will announce HTML content. Returns the predicted speech output line by line.',\n {\n html: z.string().describe('The HTML content to analyze'),\n screen_reader: z.enum(['nvda', 'jaws', 'voiceover', 'narrator', 'all']).default('all').describe('Which screen reader to simulate (default: all)'),\n selector: z.string().optional().describe('Optional CSS selector to focus analysis on specific elements'),\n },\n async ({ html, screen_reader, selector }) => {\n try {\n const { output, warnings } = analyzeHTML(html, screen_reader, selector);\n const warningText = warnings.length > 0 ? `\\n\\nWarnings:\\n${warnings.join('\\n')}` : '';\n return {\n content: [{ type: 'text', text: output + warningText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// Tool: audit_html\nserver.tool(\n 'audit_html',\n 'Generate an accessibility audit report for HTML content. Reports landmark structure, heading hierarchy, interactive elements, missing names, and issues with severity levels.',\n {\n html: z.string().describe('The HTML content to audit'),\n selector: z.string().optional().describe('Optional CSS selector to focus audit on specific elements'),\n },\n async ({ html, selector }) => {\n try {\n const { document, warnings: parseWarnings } = parseHTML(html);\n const body = document.body;\n\n if (!body) {\n return {\n content: [{ type: 'text', text: 'Error: Document has no body element.' }],\n isError: true,\n };\n }\n\n let model: AnnouncementModel;\n const warnings: string[] = parseWarnings.map((w: { message: string }) => w.message);\n\n if (selector) {\n const results = buildAccessibilityTreeWithSelector(body, selector);\n for (const r of results) {\n warnings.push(...r.warnings.map((w: { message: string }) => w.message));\n }\n if (results.length === 0) {\n return {\n content: [{ type: 'text', text: `No elements found matching selector: ${selector}` }],\n };\n }\n model = results[0].model;\n } else {\n const result = buildAccessibilityTree(body);\n warnings.push(...result.warnings.map((w: { message: string }) => w.message));\n model = result.model;\n }\n\n const audit = renderAuditReport(model);\n const warningText = warnings.length > 0 ? `\\n\\nParser warnings:\\n${warnings.join('\\n')}` : '';\n\n return {\n content: [{ type: 'text', text: audit + warningText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// Tool: diff_html\nserver.tool(\n 'diff_html',\n 'Compare two HTML versions and report accessibility changes. Shows added, removed, and changed nodes in the accessibility tree — useful for detecting regressions.',\n {\n before_html: z.string().describe('The original (before) HTML content'),\n after_html: z.string().describe('The updated (after) HTML content'),\n selector: z.string().optional().describe('Optional CSS selector to focus diff on specific elements'),\n },\n async ({ before_html, after_html, selector }) => {\n try {\n const beforeDoc = parseHTML(before_html);\n const afterDoc = parseHTML(after_html);\n\n if (!beforeDoc.document.body || !afterDoc.document.body) {\n return {\n content: [{ type: 'text', text: 'Error: One or both documents have no body element.' }],\n isError: true,\n };\n }\n\n let beforeModel: AnnouncementModel;\n let afterModel: AnnouncementModel;\n\n if (selector) {\n const beforeResults = buildAccessibilityTreeWithSelector(beforeDoc.document.body, selector);\n const afterResults = buildAccessibilityTreeWithSelector(afterDoc.document.body, selector);\n if (beforeResults.length === 0 || afterResults.length === 0) {\n return {\n content: [{ type: 'text', text: `No elements found matching selector: ${selector}` }],\n };\n }\n beforeModel = beforeResults[0].model;\n afterModel = afterResults[0].model;\n } else {\n beforeModel = buildAccessibilityTree(beforeDoc.document.body).model;\n afterModel = buildAccessibilityTree(afterDoc.document.body).model;\n }\n\n const diff = diffAccessibilityTrees(beforeModel.root, afterModel.root);\n\n if (diff.changes.length === 0) {\n return {\n content: [{ type: 'text', text: 'No accessibility changes detected between the two versions.' }],\n };\n }\n\n const summary = `+${diff.summary.added} added -${diff.summary.removed} removed ~${diff.summary.changed} changed\\n\\n`;\n const diffText = formatDiffAsText(diff);\n\n return {\n content: [{ type: 'text', text: summary + diffText }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// Tool: analyze_verbosity\nserver.tool(\n 'analyze_verbosity',\n 'Detect redundant and duplicate screen reader announcements in a sequence of accessibility events. Identifies patterns like simultaneous aria-selected + live region updates that cause VoiceOver to read the same content 2-3 times. Provides specific remediation steps and affected screen readers.',\n {\n events: z.array(z.object({\n type: z.string().describe('Event type: STATE_CHANGED, ANNOUNCEMENT, FOCUS_CHANGED, ACCESSIBLE_NAME_CHANGED, etc.'),\n timestamp: z.number().describe('Milliseconds since session start'),\n target: z.object({\n role: z.string().describe('ARIA role of the target element'),\n accessibleName: z.string().describe('Computed accessible name'),\n selector: z.string().describe('CSS selector for the element'),\n }),\n payload: z.record(z.unknown()).describe('Event payload (kind field discriminates type)'),\n })).describe('Chronologically ordered accessibility events (from runtime engine or manual capture)'),\n interaction_frame_window: z.number().optional().describe('Time window (ms) to group related events into a single interaction (default: 150)'),\n },\n async ({ events, interaction_frame_window }) => {\n try {\n const config = interaction_frame_window ? { interactionFrameWindow: interaction_frame_window } : undefined;\n const report = analyzeVerbosity(events as AccessibilityEvent[], config);\n const output = formatVerbosityReport(report);\n return {\n content: [{ type: 'text', text: output }],\n };\n } catch (error) {\n return {\n content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}` }],\n isError: true,\n };\n }\n }\n);\n\n// --- Start server ---\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n\nmain().catch((error) => {\n console.error('Speakable MCP server error:', error);\n process.exit(1);\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 * Maximum input size in bytes (10 MB).\n * Prevents denial-of-service from extremely large inputs.\n */\nconst MAX_INPUT_SIZE = 10 * 1024 * 1024;\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 or input exceeds size limit\n */\nexport function parseHTML(html: string): ParseResult {\n const warnings: ParsingWarning[] = [];\n\n // Input size validation\n const inputSize = Buffer.byteLength(html, 'utf-8');\n if (inputSize > MAX_INPUT_SIZE) {\n throw new ParsingError(\n `Input exceeds maximum size of ${MAX_INPUT_SIZE / (1024 * 1024)} MB (received ${(inputSize / (1024 * 1024)).toFixed(1)} MB). ` +\n `Use CSS selectors to analyze specific sections of large documents.`\n );\n }\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","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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n // Skip child that repeats parent name — recurse into grandchildren\n for (const grandchild of child.children) {\n renderNodeNVDA(grandchild, announcements, c);\n }\n continue;\n }\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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n for (const grandchild of child.children) {\n renderNodeJAWS(grandchild, announcements, c);\n }\n continue;\n }\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, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n for (const grandchild of child.children) {\n renderNodeVoiceOver(grandchild, announcements, c);\n }\n continue;\n }\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 * Windows Narrator screen reader announcement renderer.\n * \n * Generates heuristic announcement text approximating Windows Narrator output.\n * This is NOT a perfect emulation - real Narrator 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 Narrator-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 Narrator-style announcement text\n */\nexport function renderNarrator(model: AnnouncementModel, colorize?: boolean): string {\n const c = createColors(colorize ?? false);\n const announcements: string[] = [];\n renderNodeNarrator(model.root, announcements, c);\n return announcements.join('\\n');\n}\n\n/**\n * Recursively renders a node and its children as Narrator 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 renderNodeNarrator(node: AccessibleNode, announcements: string[], c: ColorFunctions): void {\n const announcement = formatNodeNarrator(node, c);\n if (announcement) {\n announcements.push(announcement);\n }\n\n // Recursively render children, collapsing redundant same-name children\n for (const child of node.children) {\n if (child.name && child.name === node.name && node.children.length === 1) {\n // Skip child that repeats parent name — recurse into grandchildren\n for (const grandchild of child.children) {\n renderNodeNarrator(grandchild, announcements, c);\n }\n continue;\n }\n renderNodeNarrator(child, announcements, c);\n }\n}\n\n/**\n * Formats a single node as a Narrator 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 formatNodeNarrator(node: AccessibleNode, c: ColorFunctions): string {\n const parts: string[] = [];\n\n const roleFirst = shouldAnnounceRoleFirst(node.role);\n\n if (roleFirst) {\n // Role-first: role, name, state, value, description\n const roleText = formatRoleNarrator(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n } else {\n // Name-first: name, role, state, value, description\n if (node.name) {\n parts.push(c.elementName(node.name));\n }\n\n const roleText = formatRoleNarrator(node);\n if (roleText) {\n parts.push(c.roleName(roleText));\n }\n }\n\n // Add states\n const stateText = formatStatesNarrator(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 * Narrator announces role first for links, headings, landmarks,\n * and structural containers.\n * \n * @param role - Role to check\n * @returns true if role should be announced first\n */\nfunction shouldAnnounceRoleFirst(role: AccessibleRole): boolean {\n const roleFirstRoles: AccessibleRole[] = [\n 'link',\n 'heading',\n 'navigation',\n 'main',\n 'banner',\n 'contentinfo',\n 'complementary',\n 'region',\n 'form',\n 'search',\n 'blockquote',\n 'figure',\n 'dialog',\n 'group',\n 'document',\n ];\n return roleFirstRoles.includes(role);\n}\n\n/**\n * Formats the role portion of a Narrator announcement.\n * \n * @param node - Node to format\n * @returns Role text or empty string\n */\nfunction formatRoleNarrator(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 'check box';\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';\n\n case 'main':\n return 'main';\n\n case 'banner':\n return 'banner';\n\n case 'contentinfo':\n return 'content info';\n\n case 'complementary':\n return 'complementary';\n\n case 'form':\n return 'form';\n\n case 'search':\n return 'search';\n\n case 'region':\n return 'region';\n\n case 'img':\n return 'image';\n\n case 'article':\n return 'article';\n\n case 'generic':\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 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 '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 'document';\n\n case 'application':\n return 'application';\n\n case 'separator':\n return 'separator';\n\n default:\n return role;\n }\n}\n\n/**\n * Formats the state portion of a Narrator announcement.\n * \n * @param node - Node to format\n * @returns State text or empty string\n */\nfunction formatStatesNarrator(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('partially selected');\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('partially 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('disabled');\n }\n\n // Invalid state\n if (node.state.invalid) {\n states.push('invalid');\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 * Verbosity Analyzer\n *\n * Detects redundant and duplicate announcement patterns in accessibility\n * event timelines. While the heuristic analyzer catches \"too many announcements\n * in a time window,\" this module performs deeper semantic analysis to identify\n * WHY announcements are being duplicated, and provides specific remediation\n * guidance.\n *\n * Detected patterns:\n *\n * 1. **Redundant state + live region** — When aria-selected/aria-checked changes\n * on an element AND a live region announces the same state change, screen\n * readers (especially VoiceOver) will read both.\n *\n * 2. **ActiveDescendant + state change on same element** — When\n * aria-activedescendant moves to an element AND that element's state changes\n * in the same interaction frame, VoiceOver reads the element twice.\n *\n * 3. **Name change + live region echo** — When an element's accessible name\n * changes and a live region repeats that same content.\n *\n * 4. **Focus + activedescendant conflict** — When real DOM focus moves AND\n * aria-activedescendant changes in the same frame, causing double-read.\n *\n * 5. **Multiple state changes on one element** — When several ARIA attributes\n * change simultaneously on a single element, each triggering a separate read.\n *\n * @module runtime/verbosity-analyzer\n */\n\nimport type { AccessibilityEvent, StateChangedPayload, AnnouncementPayload } from './types.js';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/**\n * Severity of a verbosity issue.\n * - \"high\": Users will definitely hear duplicate content (e.g., VoiceOver triple-read)\n * - \"medium\": Users will likely hear repeated info depending on screen reader settings\n * - \"low\": Potential redundancy that may only affect certain screen readers\n */\nexport type VerbositySeverity = 'high' | 'medium' | 'low';\n\n/**\n * Category of the verbosity pattern detected.\n */\nexport type VerbosityPattern =\n | 'redundant-state-and-live-region'\n | 'activedescendant-plus-state-change'\n | 'name-change-plus-live-region'\n | 'focus-plus-activedescendant'\n | 'multiple-state-changes-same-element'\n | 'rapid-identical-announcements';\n\n/**\n * A single verbosity finding with context and remediation guidance.\n */\nexport interface VerbosityFinding {\n /** Pattern category */\n pattern: VerbosityPattern;\n /** Severity level */\n severity: VerbositySeverity;\n /** Human-readable description of the problem */\n description: string;\n /** Specific remediation steps */\n remediation: string[];\n /** Which screen readers are most affected */\n affectedReaders: string[];\n /** The events that triggered this finding */\n relatedEvents: AccessibilityEvent[];\n /** Timestamp window where the duplicate occurred */\n timeWindow: { start: number; end: number };\n /** CSS selector of the element involved */\n elementSelector: string;\n}\n\n/**\n * Complete verbosity analysis report for a timeline.\n */\nexport interface VerbosityReport {\n /** All findings sorted by severity (high first) */\n findings: VerbosityFinding[];\n /** Summary counts by severity */\n summary: {\n high: number;\n medium: number;\n low: number;\n total: number;\n };\n /** Overall verbosity score (0-100, lower is better) */\n score: number;\n}\n\n/**\n * Configuration for the verbosity analyzer.\n */\nexport interface VerbosityConfig {\n /** Time window (ms) to group related events into a single interaction frame (default: 150) */\n interactionFrameWindow: number;\n /** Minimum text similarity ratio to consider live region content redundant (default: 0.6) */\n textSimilarityThreshold: number;\n}\n\nconst DEFAULT_CONFIG: VerbosityConfig = {\n interactionFrameWindow: 150,\n textSimilarityThreshold: 0.6,\n};\n\n// ---------------------------------------------------------------------------\n// Text Similarity\n// ---------------------------------------------------------------------------\n\n/**\n * Computes a simple word-overlap similarity ratio between two strings.\n * Returns a value between 0 and 1.\n */\nfunction textSimilarity(a: string, b: string): number {\n if (!a || !b) return 0;\n const wordsA = new Set(a.toLowerCase().split(/\\s+/).filter(Boolean));\n const wordsB = new Set(b.toLowerCase().split(/\\s+/).filter(Boolean));\n if (wordsA.size === 0 || wordsB.size === 0) return 0;\n\n let overlap = 0;\n for (const word of wordsA) {\n if (wordsB.has(word)) overlap++;\n }\n\n const maxSize = Math.max(wordsA.size, wordsB.size);\n return overlap / maxSize;\n}\n\n// ---------------------------------------------------------------------------\n// Interaction Frame Grouping\n// ---------------------------------------------------------------------------\n\ninterface InteractionFrame {\n start: number;\n end: number;\n events: AccessibilityEvent[];\n}\n\n/**\n * Groups events into interaction frames based on temporal proximity.\n * Events within `windowMs` of each other are considered part of the\n * same user interaction.\n */\nfunction groupIntoFrames(events: AccessibilityEvent[], windowMs: number): InteractionFrame[] {\n if (events.length === 0) return [];\n\n const frames: InteractionFrame[] = [];\n let currentFrame: InteractionFrame = {\n start: events[0].timestamp,\n end: events[0].timestamp,\n events: [events[0]],\n };\n\n for (let i = 1; i < events.length; i++) {\n const event = events[i];\n if (event.timestamp - currentFrame.end <= windowMs) {\n currentFrame.events.push(event);\n currentFrame.end = event.timestamp;\n } else {\n frames.push(currentFrame);\n currentFrame = {\n start: event.timestamp,\n end: event.timestamp,\n events: [event],\n };\n }\n }\n\n frames.push(currentFrame);\n return frames;\n}\n\n// ---------------------------------------------------------------------------\n// Pattern Detection\n// ---------------------------------------------------------------------------\n\nfunction detectRedundantStateAndLiveRegion(\n frame: InteractionFrame,\n _config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n const stateChanges = frame.events.filter((e) => e.type === 'STATE_CHANGED');\n const announcements = frame.events.filter((e) => e.type === 'ANNOUNCEMENT');\n\n for (const stateEvent of stateChanges) {\n const payload = stateEvent.payload as StateChangedPayload;\n\n // Only relevant for state attributes that screen readers announce\n const announcedAttributes = [\n 'aria-selected', 'aria-checked', 'aria-pressed', 'aria-expanded',\n 'aria-disabled', 'aria-invalid', 'aria-current',\n ];\n if (!announcedAttributes.includes(payload.attribute)) continue;\n\n for (const announcement of announcements) {\n const annoPayload = announcement.payload as AnnouncementPayload;\n const annoText = annoPayload.text.toLowerCase();\n const elementName = stateEvent.target.accessibleName.toLowerCase();\n\n // Check if the live region text contains the element's name\n // (which indicates it's providing feedback about the same element\n // whose state just changed, meaning the SR will announce both)\n const nameInAnnouncement = elementName.length > 0 && annoText.includes(elementName);\n\n // Also check for state-related words that echo what the SR already announces\n const stateEchoWords = ['selected', 'deselected', 'checked', 'unchecked', 'expanded', 'collapsed', 'pressed'];\n const hasStateEcho = stateEchoWords.some((word) => annoText.includes(word));\n\n if (nameInAnnouncement && hasStateEcho) {\n findings.push({\n pattern: 'redundant-state-and-live-region',\n severity: 'high',\n description:\n `The ${payload.attribute} state change on \"${stateEvent.target.accessibleName}\" ` +\n `(${stateEvent.target.role}) is already announced by the screen reader, but a live ` +\n `region also announces similar content (\"${annoPayload.text}\"). ` +\n `This causes VoiceOver to read the information 2-3 times.`,\n remediation: [\n `Remove the live region announcement when ${payload.attribute} changes on the active element, ` +\n `since the screen reader already announces state transitions on the focused/active item.`,\n `If you need the live region for summary info (e.g., \"3 of 5 selected\"), ` +\n `debounce it with a 150ms+ delay and ensure the text does NOT repeat the option name.`,\n `Use a summary-only pattern in the live region: \"3 of 5 selected\" instead of ` +\n `\"JavaScript selected. 3 of 5 selected.\" The element name is already announced ` +\n `via the state change.`,\n `Consider removing the live region entirely and relying on aria-selected/aria-checked ` +\n `state changes for per-item feedback.`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'VoiceOver (iOS)'],\n relatedEvents: [stateEvent, announcement],\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: stateEvent.target.selector,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction detectActiveDescendantPlusStateChange(\n frame: InteractionFrame,\n _config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n // Look for STATE_CHANGED events where attribute is aria-activedescendant\n const activedescendantChanges = frame.events.filter(\n (e) => e.type === 'STATE_CHANGED' &&\n (e.payload as StateChangedPayload).attribute === 'aria-activedescendant'\n );\n\n const otherStateChanges = frame.events.filter(\n (e) => e.type === 'STATE_CHANGED' &&\n (e.payload as StateChangedPayload).attribute !== 'aria-activedescendant'\n );\n\n for (const adChange of activedescendantChanges) {\n const adPayload = adChange.payload as StateChangedPayload;\n const newValue = String(adPayload.newValue);\n const previousValue = String(adPayload.previousValue ?? '');\n\n // If activedescendant is being re-set to the SAME value, that's always a bug.\n // If it's moving to a DIFFERENT element, we only flag it if a state change\n // occurs on that same target within the frame (which causes double-read on VoiceOver).\n const isSameElement = newValue === previousValue;\n\n for (const stateChange of otherStateChanges) {\n const statePayload = stateChange.payload as StateChangedPayload;\n\n // Check if the state change is on the element that activedescendant points to\n const targetMatchesAD = stateChange.target.selector.includes(newValue) ||\n stateChange.target.selector === adChange.target.selector;\n\n if (!targetMatchesAD) continue;\n\n if (isSameElement) {\n // Definite bug: re-setting activedescendant to same element AND changing its state\n findings.push({\n pattern: 'activedescendant-plus-state-change',\n severity: 'high',\n description:\n `aria-activedescendant was re-set to the same value (\"${newValue}\") ` +\n `AND ${statePayload.attribute} changed on that element within ${frame.end - frame.start}ms. ` +\n `VoiceOver reads the element once for the activedescendant update, then again for the state change.`,\n remediation: [\n `When toggling selection on the already-active option, do NOT re-set aria-activedescendant ` +\n `to the same value. Only update it when the user navigates to a different option.`,\n `Batch DOM attribute changes: set aria-selected BEFORE updating aria-activedescendant, ` +\n `or skip the activedescendant update entirely when the active item hasn't changed.`,\n `For click interactions on options, avoid calling both setActiveDescendant() and ` +\n `toggleSelection() if the clicked item is already the active descendant.`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'VoiceOver (iOS)', 'Narrator'],\n relatedEvents: [adChange, stateChange],\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: stateChange.target.selector,\n });\n } else {\n // Moving to a different element + changing state is borderline.\n // Only flag as low severity since VoiceOver announcing the navigation\n // AND the state is sometimes the desired UX (click = navigate + select).\n findings.push({\n pattern: 'activedescendant-plus-state-change',\n severity: 'low',\n description:\n `aria-activedescendant moved to \"${stateChange.target.accessibleName}\" ` +\n `AND ${statePayload.attribute} changed on that element within ${frame.end - frame.start}ms. ` +\n `VoiceOver may announce the option name twice (once for navigation, once for state).`,\n remediation: [\n `If this is a click-to-select interaction, consider separating the activedescendant ` +\n `update and the state change by a microtask (Promise.resolve()) so VoiceOver ` +\n `processes them as separate assertions.`,\n `Alternatively, accept this as expected behavior for click interactions where ` +\n `navigation and selection happen simultaneously.`,\n ],\n affectedReaders: ['VoiceOver (macOS)'],\n relatedEvents: [adChange, stateChange],\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: stateChange.target.selector,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction detectNameChangePlusLiveRegion(\n frame: InteractionFrame,\n config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n const nameChanges = frame.events.filter((e) => e.type === 'ACCESSIBLE_NAME_CHANGED');\n const announcements = frame.events.filter((e) => e.type === 'ANNOUNCEMENT');\n\n for (const nameEvent of nameChanges) {\n for (const announcement of announcements) {\n const annoPayload = announcement.payload as AnnouncementPayload;\n const similarity = textSimilarity(nameEvent.target.accessibleName, annoPayload.text);\n\n if (similarity >= config.textSimilarityThreshold) {\n findings.push({\n pattern: 'name-change-plus-live-region',\n severity: 'medium',\n description:\n `The accessible name of \"${nameEvent.target.accessibleName}\" (${nameEvent.target.role}) ` +\n `changed AND a live region announced similar content (\"${annoPayload.text}\"). ` +\n `Screen readers may announce both the name change and the live region.`,\n remediation: [\n `Choose one announcement channel: either update the element's accessible name ` +\n `(which the screen reader reads if the element is focused) OR use a live region, not both.`,\n `If the element is focused, prefer the name change. If it's not focused, prefer the live region.`,\n `Add a 200ms+ debounce to the live region update to let the name change announce first.`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'NVDA', 'JAWS'],\n relatedEvents: [nameEvent, announcement],\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: nameEvent.target.selector,\n });\n }\n }\n }\n\n return findings;\n}\n\nfunction detectFocusPlusActiveDescendant(\n frame: InteractionFrame,\n _config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n const focusEvents = frame.events.filter((e) => e.type === 'FOCUS_CHANGED');\n const adChanges = frame.events.filter(\n (e) => e.type === 'STATE_CHANGED' &&\n (e.payload as StateChangedPayload).attribute === 'aria-activedescendant'\n );\n\n if (focusEvents.length > 0 && adChanges.length > 0) {\n findings.push({\n pattern: 'focus-plus-activedescendant',\n severity: 'medium',\n description:\n `Both real DOM focus moved AND aria-activedescendant changed within ${frame.end - frame.start}ms. ` +\n `Screen readers may announce the focused element AND then re-announce via activedescendant, ` +\n `causing a double-read.`,\n remediation: [\n `Choose one focus management strategy: either move real DOM focus to options (roving tabindex) ` +\n `OR use aria-activedescendant on the container. Do not mix both.`,\n `If using aria-activedescendant, keep DOM focus on the container (listbox/combobox) ` +\n `and only change the activedescendant attribute.`,\n `If using roving tabindex, set tabindex=\"0\" on the active item and tabindex=\"-1\" on others, ` +\n `and move focus directly via element.focus().`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'NVDA', 'JAWS', 'Narrator'],\n relatedEvents: [...focusEvents, ...adChanges],\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: focusEvents[0].target.selector,\n });\n }\n\n return findings;\n}\n\nfunction detectMultipleStateChangesSameElement(\n frame: InteractionFrame,\n _config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n const stateChanges = frame.events.filter((e) => e.type === 'STATE_CHANGED');\n\n // Group by target selector\n const bySelector = new Map<string, AccessibilityEvent[]>();\n for (const event of stateChanges) {\n const existing = bySelector.get(event.target.selector) || [];\n existing.push(event);\n bySelector.set(event.target.selector, existing);\n }\n\n for (const [selector, events] of bySelector) {\n if (events.length >= 3) {\n const attributes = events.map((e) => (e.payload as StateChangedPayload).attribute);\n findings.push({\n pattern: 'multiple-state-changes-same-element',\n severity: 'medium',\n description:\n `${events.length} ARIA attributes changed simultaneously on \"${events[0].target.accessibleName}\" ` +\n `(${events[0].target.role}): ${attributes.join(', ')}. ` +\n `Some screen readers announce each attribute change individually, ` +\n `causing a verbose multi-part announcement.`,\n remediation: [\n `Batch attribute changes into a single DOM mutation frame by setting all attributes ` +\n `before the next microtask. Use requestAnimationFrame() or Promise.resolve() to group them.`,\n `Evaluate which attributes actually need to be communicated. For example, ` +\n `if aria-selected changes, the screen reader already announces it; additional ` +\n `aria-checked or aria-pressed changes may be redundant.`,\n `Consider using a single composite state (e.g., just aria-selected for listbox options) ` +\n `rather than multiple state attributes.`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'Narrator'],\n relatedEvents: events,\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: selector,\n });\n }\n }\n\n return findings;\n}\n\nfunction detectRapidIdenticalAnnouncements(\n frame: InteractionFrame,\n _config: VerbosityConfig\n): VerbosityFinding[] {\n const findings: VerbosityFinding[] = [];\n\n const announcements = frame.events.filter((e) => e.type === 'ANNOUNCEMENT');\n\n // Check for identical or near-identical announcement text\n const seen = new Map<string, AccessibilityEvent[]>();\n for (const event of announcements) {\n const text = (event.payload as AnnouncementPayload).text.toLowerCase().trim();\n const existing = seen.get(text) || [];\n existing.push(event);\n seen.set(text, existing);\n }\n\n for (const [text, events] of seen) {\n if (events.length >= 2) {\n findings.push({\n pattern: 'rapid-identical-announcements',\n severity: 'high',\n description:\n `The same live region content (\"${text}\") was announced ${events.length} times ` +\n `within ${frame.end - frame.start}ms. Users will hear the same information repeated.`,\n remediation: [\n `Debounce live region updates. Clear the live region text content first, ` +\n `then set the new value after a 100-200ms delay.`,\n `If updating a live region's textContent to the same value, the screen reader ` +\n `may ignore it OR re-read it depending on implementation. Clear to empty string first.`,\n `Avoid updating the live region inside a loop or rapid event handler. ` +\n `Compute the final state and announce once.`,\n ],\n affectedReaders: ['VoiceOver (macOS)', 'VoiceOver (iOS)', 'NVDA', 'Narrator'],\n relatedEvents: events,\n timeWindow: { start: frame.start, end: frame.end },\n elementSelector: events[0].target.selector,\n });\n }\n }\n\n return findings;\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Analyzes a timeline of accessibility events for verbosity issues.\n *\n * Groups events into interaction frames (events within a short time window\n * of each other), then checks each frame for patterns that cause screen\n * readers to announce redundant or duplicate content.\n *\n * @param events - Chronologically ordered accessibility events\n * @param config - Optional configuration overrides\n * @returns A VerbosityReport with all findings and a score\n */\nexport function analyzeVerbosity(\n events: AccessibilityEvent[],\n config?: Partial<VerbosityConfig>\n): VerbosityReport {\n const cfg: VerbosityConfig = { ...DEFAULT_CONFIG, ...config };\n\n // Group events into interaction frames\n const frames = groupIntoFrames(events, cfg.interactionFrameWindow);\n\n // Run all detectors on each frame\n const findings: VerbosityFinding[] = [];\n\n for (const frame of frames) {\n findings.push(...detectRedundantStateAndLiveRegion(frame, cfg));\n findings.push(...detectActiveDescendantPlusStateChange(frame, cfg));\n findings.push(...detectNameChangePlusLiveRegion(frame, cfg));\n findings.push(...detectFocusPlusActiveDescendant(frame, cfg));\n findings.push(...detectMultipleStateChangesSameElement(frame, cfg));\n findings.push(...detectRapidIdenticalAnnouncements(frame, cfg));\n }\n\n // Sort by severity (high first)\n const severityOrder: Record<VerbositySeverity, number> = { high: 0, medium: 1, low: 2 };\n findings.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);\n\n // Compute summary\n const summary = {\n high: findings.filter((f) => f.severity === 'high').length,\n medium: findings.filter((f) => f.severity === 'medium').length,\n low: findings.filter((f) => f.severity === 'low').length,\n total: findings.length,\n };\n\n // Score: 100 (perfect) minus weighted deductions\n const deductions = summary.high * 25 + summary.medium * 10 + summary.low * 3;\n const score = Math.max(0, 100 - deductions);\n\n return { findings, summary, score };\n}\n\n/**\n * Formats a verbosity report as human-readable text output.\n */\nexport function formatVerbosityReport(report: VerbosityReport): string {\n const lines: string[] = [];\n\n lines.push('');\n lines.push('=== VERBOSITY ANALYSIS REPORT ===');\n lines.push('');\n lines.push(`Score: ${report.score}/100 ${report.score >= 80 ? '(Good)' : report.score >= 50 ? '(Needs attention)' : '(Critical verbosity issues)'}`);\n lines.push(`Findings: ${report.summary.total} (${report.summary.high} high, ${report.summary.medium} medium, ${report.summary.low} low)`);\n lines.push('');\n\n if (report.findings.length === 0) {\n lines.push('No verbosity issues detected. Announcements appear clean.');\n return lines.join('\\n');\n }\n\n for (let i = 0; i < report.findings.length; i++) {\n const finding = report.findings[i];\n const severityIcon = finding.severity === 'high' ? '\\u2718' : finding.severity === 'medium' ? '\\u26A0' : '\\u2139';\n\n lines.push(`${severityIcon} [${finding.severity.toUpperCase()}] ${finding.pattern}`);\n lines.push(` Element: ${finding.elementSelector}`);\n lines.push(` Window: ${finding.timeWindow.start}ms - ${finding.timeWindow.end}ms`);\n lines.push(` ${finding.description}`);\n lines.push('');\n lines.push(' Affected: ' + finding.affectedReaders.join(', '));\n lines.push('');\n lines.push(' Remediation:');\n for (const step of finding.remediation) {\n lines.push(` - ${step}`);\n }\n lines.push('');\n\n if (i < report.findings.length - 1) {\n lines.push(' ' + '\\u2500'.repeat(60));\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["model","shouldAnnounceRoleFirst","childPath"]}
|