@reticular/speakable 1.6.0 → 1.7.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/model/types.ts","../../src/extractor/aria-name.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/browser/analyze.ts","../../src/runtime/selector.ts","../../src/runtime/observers/focus-observer.ts","../../src/runtime/observers/mutation-observer.ts","../../src/runtime/observers/live-region-observer.ts","../../src/runtime/observers/dialog-observer.ts","../../src/runtime/engine.ts","../../src/runtime/interactions.ts","../../src/runtime/heuristics.ts","../../src/version.ts","../../src/runtime/timeline-generator.ts","../../src/browser/capture.ts"],"sourcesContent":["/**\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 * 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 * 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 return collectAccessibleChildren(element, warnings);\n}\n\n/**\n * Centralized, slot-aware child collection for an element.\n *\n * Behavior:\n * - If the element has an open shadow root, traverse the shadow tree. When a\n * `<slot>` is encountered, resolve its assigned (projected light-DOM) nodes\n * via `assignedNodes({ flatten: true })` and process them in place, so\n * slotted content appears in shadow-tree order. If a slot has no assigned\n * nodes, its default content is used. Slotted light-DOM nodes are therefore\n * emitted exactly once (at the slot position), never again from the host's\n * light DOM.\n * - If the element has no shadow root, traverse the light-DOM childNodes as\n * before.\n *\n * `assignedNodes`/`shadowRoot` are feature-detected so environments with\n * limited shadow DOM support (e.g. jsdom) degrade gracefully.\n *\n * @param element - Element whose accessible children to collect\n * @param warnings - Array to collect warnings\n * @returns Flat array of AccessibleNodes\n */\nfunction collectAccessibleChildren(\n element: Element,\n warnings: TreeBuildWarning[]\n): AccessibleNode[] {\n const children: AccessibleNode[] = [];\n\n // Open shadow root present: traverse the shadow tree only. Slots pull in the\n // projected light-DOM nodes, so we must NOT also walk the host's light DOM.\n if (element.shadowRoot) {\n for (const child of Array.from(element.shadowRoot.childNodes)) {\n processShadowNode(child, children, warnings);\n }\n return children;\n }\n\n // No shadow root. If this is a custom element (tag contains a hyphen) with\n // no light-DOM children, it likely has a *closed* shadow root whose content\n // we cannot traverse. Emit a warning so partial coverage is not mistaken for\n // full coverage, then continue (never throw).\n if (\n element.localName &&\n element.localName.includes('-') &&\n element.childNodes.length === 0\n ) {\n warnings.push({\n message: `Custom element <${element.localName}> has no accessible children and may have a closed shadow root; its content could not be analyzed.`,\n element,\n });\n }\n\n // Plain light-DOM traversal.\n for (const child of Array.from(element.childNodes)) {\n processChildNode(child, children, warnings);\n }\n return children;\n}\n\n/**\n * Processes a node encountered while traversing a shadow tree.\n *\n * Behaves like `processChildNode`, except that `<slot>` elements are expanded\n * into their assigned (projected) light-DOM nodes, or their default content\n * when nothing is assigned.\n */\nfunction processShadowNode(\n node: Node,\n children: AccessibleNode[],\n warnings: TreeBuildWarning[]\n): void {\n if (node.nodeType === 1) {\n const element = node as Element;\n if (element.localName === 'slot') {\n const slot = element as HTMLSlotElement;\n let assigned: Node[] = [];\n // Feature-detect assignedNodes (unavailable in some DOM implementations).\n if (typeof slot.assignedNodes === 'function') {\n try {\n assigned = Array.from(slot.assignedNodes({ flatten: true }));\n } catch {\n assigned = [];\n }\n }\n if (assigned.length > 0) {\n // Projected light-DOM content: process at the slot's position.\n for (const assignedNode of assigned) {\n processChildNode(assignedNode, children, warnings);\n }\n } else {\n // No assigned nodes: fall back to the slot's default content.\n for (const child of Array.from(slot.childNodes)) {\n processShadowNode(child, children, warnings);\n }\n }\n return;\n }\n }\n // Non-slot nodes traverse normally (including nested shadow roots via\n // processChildNode -> buildNodeRecursive/collectAccessibleChildren).\n processChildNode(node, children, warnings);\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 (slot-aware; shadow DOM handled centrally)\n const children = collectAccessibleChildren(element, warnings);\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 (slot-aware; shadow DOM handled centrally)\n const children = collectAccessibleChildren(rootElement, warnings);\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 * Transport-agnostic static accessibility analysis.\n *\n * Wraps the core Speakable engine (tree-builder + per-reader renderers +\n * audit) to produce differentiated screen reader output predictions from a\n * live DOM element. This is the single source of truth consumed by the\n * Storybook addon, the iframe harness, and the browser extension.\n */\n\nimport { buildAccessibilityTree } from '../extractor/tree-builder.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 { generateAuditReport } from '../renderer/audit-renderer.js';\nimport type { AccessibleNode } from '../model/types.js';\n\nexport interface AuditFinding {\n severity: 'error' | 'warning' | 'info';\n message: string;\n selector: string;\n}\n\nexport interface AnalysisResult {\n nvda: string[];\n jaws: string[];\n voiceover: string[];\n narrator: string[];\n audit: AuditFinding[];\n stats: {\n totalElements: number;\n interactiveElements: number;\n landmarks: number;\n headings: number;\n };\n /** Tree-build and upgrade warnings surfaced to the user. */\n warnings: string[];\n}\n\n// Roles that count as landmarks\nconst LANDMARK_ROLES = new Set([\n 'navigation', 'main', 'banner', 'contentinfo',\n 'complementary', 'region', 'form', 'search',\n]);\n\n// Roles that count as interactive\nconst INTERACTIVE_ROLES = new Set([\n 'button', 'link', 'textbox', 'checkbox', 'radio',\n 'combobox', 'listbox', 'option',\n]);\n\n/**\n * Count tree stats by walking the AccessibleNode tree.\n */\nfunction countStats(node: AccessibleNode): AnalysisResult['stats'] {\n const stats = { totalElements: 0, interactiveElements: 0, landmarks: 0, headings: 0 };\n\n function walk(n: AccessibleNode) {\n if (n.role !== 'generic' && n.role !== 'staticText') {\n stats.totalElements++;\n }\n if (INTERACTIVE_ROLES.has(n.role)) stats.interactiveElements++;\n if (LANDMARK_ROLES.has(n.role)) stats.landmarks++;\n if (n.role === 'heading') stats.headings++;\n for (const child of n.children) walk(child);\n }\n\n walk(node);\n return stats;\n}\n\n/**\n * Convert core audit issues to the panel's AuditFinding format.\n */\nfunction convertAuditFindings(\n model: ReturnType<typeof buildAccessibilityTree>['model']\n): AuditFinding[] {\n const report = generateAuditReport(model);\n return report.issues.map(issue => ({\n severity: issue.severity,\n message: issue.message,\n selector: issue.element\n ? `${issue.element.role}${issue.element.name ? ` \"${issue.element.name}\"` : ''}`\n : issue.suggestion || '',\n }));\n}\n\n/**\n * An empty, well-formed result for empty/detached/invalid input.\n */\nfunction emptyResult(extraWarnings: string[] = []): AnalysisResult {\n return {\n nvda: [],\n jaws: [],\n voiceover: [],\n narrator: [],\n audit: [],\n stats: { totalElements: 0, interactiveElements: 0, landmarks: 0, headings: 0 },\n warnings: [...extraWarnings],\n };\n}\n\n/**\n * Analyze a live DOM element using the core Speakable engine.\n *\n * Reuses buildAccessibilityTree + the four renderers + generateAuditReport.\n * Never throws on empty or detached input — returns a well-formed empty result.\n *\n * @param root - DOM element to analyze\n * @param extraWarnings - Optional warnings to fold in (e.g. upgrade timeouts)\n * @returns Differentiated per-reader analysis result\n */\nexport function analyzeElement(root: Element | null | undefined, extraWarnings: string[] = []): AnalysisResult {\n if (!root) {\n return emptyResult(extraWarnings);\n }\n\n let built: ReturnType<typeof buildAccessibilityTree>;\n try {\n built = buildAccessibilityTree(root);\n } catch (err) {\n return emptyResult([\n ...extraWarnings,\n `Analysis failed: ${err instanceof Error ? err.message : String(err)}`,\n ]);\n }\n\n const { model, warnings: treeWarnings } = built;\n\n // Render per-reader output (colorize=false to get plain text)\n const nvda = renderNVDA(model, false).split('\\n').filter(Boolean);\n const jaws = renderJAWS(model, false).split('\\n').filter(Boolean);\n const voiceover = renderVoiceOver(model, false).split('\\n').filter(Boolean);\n const narrator = renderNarrator(model, false).split('\\n').filter(Boolean);\n\n const audit = convertAuditFindings(model);\n const stats = countStats(model.root);\n\n const warnings = [\n ...extraWarnings,\n ...treeWarnings.map(w => w.message),\n ];\n\n return { nvda, jaws, voiceover, narrator, audit, stats, warnings };\n}\n\n/**\n * Analyze a live DOM element after awaiting custom-element upgrade.\n *\n * Waits for web components under `root` to upgrade/render (bounded by\n * `upgradeTimeoutMs`), then runs `analyzeElement`, folding any upgrade\n * warnings into `result.warnings`. Use this in real-browser surfaces\n * (harness, extension, addon) where components may hydrate asynchronously.\n */\nexport async function analyzeElementWithUpgrade(\n root: Element | null | undefined,\n upgradeTimeoutMs?: number\n): Promise<AnalysisResult> {\n // Imported lazily to keep the sync `analyzeElement` path dependency-free.\n const { awaitCustomElementsReady } = await import('./upgrade.js');\n const target = root ?? undefined;\n const scope: Document | Element | undefined =\n target && target.ownerDocument ? target.ownerDocument : target;\n const upgradeWarnings = scope\n ? await awaitCustomElementsReady(scope, upgradeTimeoutMs)\n : [];\n return analyzeElement(root, upgradeWarnings.map(w => w.message));\n}\n","/**\n * Stable CSS Selector Generation\n *\n * Generates unique, deterministic CSS selectors for DOM elements.\n * The selector strategy prioritizes stability and readability:\n *\n * 1. If the element has an ID, return `#id`\n * 2. Walk up from the element to the document root, building a path\n * 3. At each level, try tag name alone, then tag+classes, then tag:nth-child(n)\n * 4. Stop building the path when the partial selector already uniquely identifies the element\n */\n\n/**\n * Generate a stable CSS selector that uniquely identifies the given element\n * within its document.\n *\n * The selector is deterministic: given the same DOM structure, the same element\n * will always produce the same selector string.\n */\nexport function generateSelector(element: Element): string {\n // If the element has an ID, use it directly (IDs are unique within a document)\n if (element.id) {\n return `#${escapeCSSIdentifier(element.id)}`;\n }\n\n const document = element.ownerDocument;\n if (!document) {\n return getTagName(element);\n }\n\n // Build path segments from element up to document root\n const segments: string[] = [];\n let current: Element | null = element;\n\n while (current && current !== document.documentElement) {\n const segment = buildSegment(current, document);\n segments.unshift(segment);\n\n // Check if the current partial path already uniquely identifies the element\n const partialSelector = segments.join(' > ');\n try {\n const matches = document.querySelectorAll(partialSelector);\n if (matches.length === 1 && matches[0] === element) {\n return partialSelector;\n }\n } catch {\n // If querySelectorAll fails (invalid selector), continue building path\n }\n\n current = current.parentElement;\n }\n\n // Include html root if needed\n if (segments.length === 0) {\n return getTagName(element);\n }\n\n const fullSelector = segments.join(' > ');\n\n // Final uniqueness check - if still not unique, shouldn't happen for well-formed DOM\n // but return what we have as it's the most specific path we can build\n return fullSelector;\n}\n\n/**\n * Build a selector segment for a single element in the path.\n * Tries strategies in order of preference: tag alone, tag+classes, tag:nth-child.\n */\nfunction buildSegment(element: Element, _document: Document): string {\n const tag = getTagName(element);\n const parent = element.parentElement;\n\n // Strategy 1: Tag name alone is unique among siblings\n if (parent) {\n const siblingsWithSameTag = Array.from(parent.children).filter(\n (child) => getTagName(child) === tag\n );\n if (siblingsWithSameTag.length === 1) {\n return tag;\n }\n } else {\n // No parent - tag alone is our best option at root level\n return tag;\n }\n\n // Strategy 2: Tag + class combination is unique among siblings\n const classes = getStableClasses(element);\n if (classes.length > 0) {\n const tagWithClasses = `${tag}.${classes.join('.')}`;\n if (parent) {\n const siblingsMatchingClasses = Array.from(parent.children).filter(\n (child) => {\n if (getTagName(child) !== tag) return false;\n return classes.every((cls) => child.classList.contains(cls));\n }\n );\n if (siblingsMatchingClasses.length === 1) {\n return tagWithClasses;\n }\n }\n }\n\n // Strategy 3: nth-child fallback (always unique among siblings)\n const index = getNthChildIndex(element);\n return `${tag}:nth-child(${index})`;\n}\n\n/**\n * Get the lowercase tag name for an element.\n */\nfunction getTagName(element: Element): string {\n return element.tagName.toLowerCase();\n}\n\n/**\n * Get sorted, stable class names for an element.\n * Filters out classes that look dynamic (contain random characters/hashes).\n * Sorting ensures deterministic output regardless of class order in markup.\n */\nfunction getStableClasses(element: Element): string[] {\n const classes = Array.from(element.classList);\n if (classes.length === 0) return [];\n\n // Filter out classes that look like generated hashes (e.g., CSS modules)\n const stableClasses = classes.filter((cls) => !looksLikeDynamicClass(cls));\n\n // Sort for determinism\n return stableClasses.sort().map(escapeCSSIdentifier);\n}\n\n/**\n * Heuristic to detect dynamic/generated class names.\n * Classes with patterns like hex hashes, random strings, or auto-generated\n * suffixes are considered unstable.\n */\nfunction looksLikeDynamicClass(className: string): boolean {\n // Classes that are purely hex strings of 5+ chars\n if (/^[a-f0-9]{5,}$/i.test(className)) return true;\n\n // Classes ending with a hash-like suffix (e.g., \"button_a1b2c3\")\n if (/[_-][a-f0-9]{5,}$/i.test(className)) return true;\n\n // CSS module style hashes (e.g., \"styles__button___2xF3d\")\n if (/_{2,}[A-Za-z0-9]{4,}$/.test(className)) return true;\n\n return false;\n}\n\n/**\n * Get the 1-based nth-child index of an element among its parent's children.\n */\nfunction getNthChildIndex(element: Element): number {\n const parent = element.parentElement;\n if (!parent) return 1;\n\n const children = Array.from(parent.children);\n const index = children.indexOf(element);\n return index + 1;\n}\n\n/**\n * Escape special characters in a CSS identifier.\n * Handles characters that have special meaning in CSS selectors.\n */\nfunction escapeCSSIdentifier(value: string): string {\n // If the value is empty, return it as-is\n if (!value) return value;\n\n let result = '';\n for (let i = 0; i < value.length; i++) {\n const char = value[i];\n const code = char.charCodeAt(0);\n\n // If it starts with a digit, escape it\n if (i === 0 && code >= 0x30 && code <= 0x39) {\n result += `\\\\3${char} `;\n continue;\n }\n\n // Characters that need escaping in CSS identifiers\n if (\n char === '!' ||\n char === '\"' ||\n char === '#' ||\n char === '$' ||\n char === '%' ||\n char === '&' ||\n char === \"'\" ||\n char === '(' ||\n char === ')' ||\n char === '*' ||\n char === '+' ||\n char === ',' ||\n char === '.' ||\n char === '/' ||\n char === ':' ||\n char === ';' ||\n char === '<' ||\n char === '=' ||\n char === '>' ||\n char === '?' ||\n char === '@' ||\n char === '[' ||\n char === '\\\\' ||\n char === ']' ||\n char === '^' ||\n char === '`' ||\n char === '{' ||\n char === '|' ||\n char === '}' ||\n char === '~' ||\n char === ' '\n ) {\n result += `\\\\${char}`;\n continue;\n }\n\n result += char;\n }\n\n return result;\n}\n","/**\n * Focus Observer\n *\n * Observes focus changes on a document and emits FOCUS_CHANGED accessibility\n * events. Tracks the previously focused element to populate the previousTarget\n * field in each event.\n *\n * @module runtime/observers/focus-observer\n */\n\nimport type { AccessibilityEvent, EventTarget as A11yEventTarget } from '../types';\nimport { generateSelector } from '../selector';\n\n// ---------------------------------------------------------------------------\n// Accessible Name Computation (self-contained)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the accessible name for an element.\n * Checks aria-label, then aria-labelledby (resolves referenced element textContent),\n * then falls back to the element's own textContent.\n */\nfunction computeAccessibleName(element: Element, document: Document): string {\n // 1. aria-label takes precedence\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.trim()) {\n return ariaLabel.trim();\n }\n\n // 2. aria-labelledby: resolve referenced element(s) text content\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy && labelledBy.trim()) {\n const ids = labelledBy.trim().split(/\\s+/);\n const parts: string[] = [];\n for (const id of ids) {\n const referenced = document.getElementById(id);\n if (referenced && referenced.textContent) {\n parts.push(referenced.textContent.trim());\n }\n }\n const combined = parts.join(' ');\n if (combined) {\n return combined;\n }\n }\n\n // 3. Fall back to element's own textContent\n const textContent = element.textContent;\n if (textContent && textContent.trim()) {\n return textContent.trim();\n }\n\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Implicit Role Mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Determine the ARIA role of an element.\n * Checks the explicit `role` attribute first, then falls back to implicit\n * role mapping based on tag name and attributes.\n */\nfunction getElementRole(element: Element): string {\n // Explicit role takes priority\n const explicitRole = element.getAttribute('role');\n if (explicitRole && explicitRole.trim()) {\n return explicitRole.trim();\n }\n\n // Implicit role mapping\n const tagName = element.tagName.toLowerCase();\n\n switch (tagName) {\n case 'button':\n return 'button';\n case 'a':\n return element.hasAttribute('href') ? 'link' : 'generic';\n case 'input': {\n const type = (element.getAttribute('type') || 'text').toLowerCase();\n switch (type) {\n case 'button':\n case 'submit':\n case 'reset':\n case 'image':\n return 'button';\n case 'checkbox':\n return 'checkbox';\n case 'radio':\n return 'radio';\n case 'range':\n return 'slider';\n case 'search':\n return 'searchbox';\n default:\n return 'textbox';\n }\n }\n case 'textarea':\n return 'textbox';\n case 'select':\n return element.hasAttribute('multiple') ? 'listbox' : 'combobox';\n case 'nav':\n return 'navigation';\n case 'main':\n return 'main';\n case 'header':\n return 'banner';\n case 'footer':\n return 'contentinfo';\n case 'aside':\n return 'complementary';\n case 'form':\n return 'form';\n case 'section':\n return element.hasAttribute('aria-label') || element.hasAttribute('aria-labelledby')\n ? 'region'\n : 'generic';\n case 'article':\n return 'article';\n case 'dialog':\n return 'dialog';\n case 'table':\n return 'table';\n case 'ul':\n case 'ol':\n return 'list';\n case 'li':\n return 'listitem';\n case 'img':\n return element.getAttribute('alt') === '' ? 'presentation' : 'img';\n case 'h1':\n case 'h2':\n case 'h3':\n case 'h4':\n case 'h5':\n case 'h6':\n return 'heading';\n case 'option':\n return 'option';\n case 'progress':\n return 'progressbar';\n case 'output':\n return 'status';\n case 'menu':\n return 'menu';\n default:\n return 'generic';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Focus Observer\n// ---------------------------------------------------------------------------\n\n/** Callback type for emitting accessibility events from the observer. */\nexport type FocusEventEmitter = (event: AccessibilityEvent) => void;\n\nexport interface FocusObserverOptions {\n /** The document to observe focus changes on */\n document: Document;\n /** Callback to emit accessibility events */\n onEvent: FocusEventEmitter;\n /** Function to get the current timestamp (ms since session start) */\n getTimestamp: () => number;\n}\n\nexport interface FocusObserver {\n /** Start listening for focus changes */\n start(): void;\n /** Stop listening for focus changes */\n stop(): void;\n /** Whether the observer is currently active */\n readonly isActive: boolean;\n}\n\n/**\n * Creates a FocusObserver that listens to focusin events on the document\n * and emits FOCUS_CHANGED accessibility events.\n */\nexport function createFocusObserver(options: FocusObserverOptions): FocusObserver {\n const { document: doc, onEvent, getTimestamp } = options;\n\n let active = false;\n let previousTarget: A11yEventTarget | null = null;\n\n function buildEventTarget(element: Element): A11yEventTarget {\n return {\n role: getElementRole(element),\n accessibleName: computeAccessibleName(element, doc),\n selector: generateSelector(element),\n };\n }\n\n function handleFocusIn(event: Event): void {\n if (!active) return;\n\n const target = event.target;\n if (!target || !(target instanceof doc.defaultView!.Element)) {\n return;\n }\n\n const currentTarget = buildEventTarget(target);\n\n const a11yEvent: AccessibilityEvent = {\n type: 'FOCUS_CHANGED',\n timestamp: getTimestamp(),\n target: currentTarget,\n payload: {\n kind: 'focus_changed',\n previousTarget: previousTarget,\n },\n };\n\n onEvent(a11yEvent);\n previousTarget = currentTarget;\n }\n\n return {\n start(): void {\n if (active) return;\n active = true;\n previousTarget = null;\n doc.addEventListener('focusin', handleFocusIn);\n },\n\n stop(): void {\n if (!active) return;\n active = false;\n doc.removeEventListener('focusin', handleFocusIn);\n },\n\n get isActive(): boolean {\n return active;\n },\n };\n}\n","/**\n * Mutation Observer for Accessibility-Relevant Attribute Changes\n *\n * Wraps MutationObserver to detect changes to:\n * - `role` attribute → emits ROLE_CHANGED events\n * - `aria-label`, `aria-labelledby` → emits ACCESSIBLE_NAME_CHANGED events\n * - `aria-expanded`, `aria-selected`, `aria-checked`, `aria-disabled`, `aria-hidden` → emits STATE_CHANGED events\n *\n * Filters out irrelevant mutations (text content in non-live regions, style changes).\n * Uses `attributeOldValue: true` to capture previous values for diff reporting.\n *\n * @module runtime/observers/mutation-observer\n */\n\nimport type {\n AccessibilityEvent,\n EventTarget as A11yEventTarget,\n RoleChangedPayload,\n AccessibleNameChangedPayload,\n StateChangedPayload,\n} from '../types';\nimport { generateSelector } from '../selector';\n\n// ---------------------------------------------------------------------------\n// Observed attribute sets\n// ---------------------------------------------------------------------------\n\n/** Attribute that triggers ROLE_CHANGED */\nconst ROLE_ATTRIBUTE = 'role';\n\n/** Attributes that trigger ACCESSIBLE_NAME_CHANGED */\nconst NAME_ATTRIBUTES = new Set(['aria-label', 'aria-labelledby']);\n\n/** Attributes that trigger STATE_CHANGED */\nconst STATE_ATTRIBUTES = new Set([\n 'aria-expanded',\n 'aria-selected',\n 'aria-checked',\n 'aria-disabled',\n 'aria-hidden',\n]);\n\n/** All observed attributes combined (for MutationObserver attributeFilter) */\nconst OBSERVED_ATTRIBUTES = [\n ROLE_ATTRIBUTE,\n 'aria-label',\n 'aria-labelledby',\n 'aria-expanded',\n 'aria-selected',\n 'aria-checked',\n 'aria-disabled',\n 'aria-hidden',\n];\n\n// ---------------------------------------------------------------------------\n// Accessible Name Computation (self-contained)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the accessible name for an element.\n * Checks aria-label, then aria-labelledby (resolves referenced element textContent),\n * then falls back to the element's own textContent.\n */\nfunction computeAccessibleName(element: Element, document: Document): string {\n // 1. aria-label takes precedence\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.trim()) {\n return ariaLabel.trim();\n }\n\n // 2. aria-labelledby: resolve referenced element(s) text content\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy && labelledBy.trim()) {\n const ids = labelledBy.trim().split(/\\s+/);\n const parts: string[] = [];\n for (const id of ids) {\n const referenced = document.getElementById(id);\n if (referenced && referenced.textContent) {\n parts.push(referenced.textContent.trim());\n }\n }\n const combined = parts.join(' ');\n if (combined) {\n return combined;\n }\n }\n\n // 3. Fall back to element's own textContent\n const textContent = element.textContent;\n if (textContent && textContent.trim()) {\n return textContent.trim();\n }\n\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Implicit Role Mapping\n// ---------------------------------------------------------------------------\n\n/**\n * Determine the ARIA role of an element.\n * Checks the explicit `role` attribute first, then falls back to implicit\n * role mapping based on tag name and attributes.\n */\nfunction getElementRole(element: Element): string {\n // Explicit role takes priority\n const explicitRole = element.getAttribute('role');\n if (explicitRole && explicitRole.trim()) {\n return explicitRole.trim();\n }\n\n // Implicit role mapping\n const tagName = element.tagName.toLowerCase();\n\n switch (tagName) {\n case 'button':\n return 'button';\n case 'a':\n return element.hasAttribute('href') ? 'link' : 'generic';\n case 'input': {\n const type = (element.getAttribute('type') || 'text').toLowerCase();\n switch (type) {\n case 'button':\n case 'submit':\n case 'reset':\n case 'image':\n return 'button';\n case 'checkbox':\n return 'checkbox';\n case 'radio':\n return 'radio';\n case 'range':\n return 'slider';\n case 'search':\n return 'searchbox';\n default:\n return 'textbox';\n }\n }\n case 'textarea':\n return 'textbox';\n case 'select':\n return element.hasAttribute('multiple') ? 'listbox' : 'combobox';\n case 'nav':\n return 'navigation';\n case 'main':\n return 'main';\n case 'header':\n return 'banner';\n case 'footer':\n return 'contentinfo';\n case 'aside':\n return 'complementary';\n case 'form':\n return 'form';\n case 'section':\n return element.hasAttribute('aria-label') || element.hasAttribute('aria-labelledby')\n ? 'region'\n : 'generic';\n case 'article':\n return 'article';\n case 'dialog':\n return 'dialog';\n case 'table':\n return 'table';\n case 'ul':\n case 'ol':\n return 'list';\n case 'li':\n return 'listitem';\n case 'img':\n return element.getAttribute('alt') === '' ? 'presentation' : 'img';\n case 'h1':\n case 'h2':\n case 'h3':\n case 'h4':\n case 'h5':\n case 'h6':\n return 'heading';\n case 'option':\n return 'option';\n case 'progress':\n return 'progressbar';\n case 'output':\n return 'status';\n case 'menu':\n return 'menu';\n default:\n return 'generic';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Mutation Observer Types\n// ---------------------------------------------------------------------------\n\n/** Callback type for emitting accessibility events from the observer. */\nexport type MutationEventEmitter = (event: AccessibilityEvent) => void;\n\nexport interface MutationObserverOptions {\n /** The document to observe attribute changes on */\n document: Document;\n /** Callback to emit accessibility events */\n onEvent: MutationEventEmitter;\n /** Function to get the current timestamp (ms since session start) */\n getTimestamp: () => number;\n}\n\nexport interface AccessibilityMutationObserver {\n /** Start observing the document for attribute mutations */\n start(): void;\n /** Stop observing and disconnect the MutationObserver */\n stop(): void;\n /** Whether the observer is currently active */\n readonly isActive: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Mutation Observer Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates an accessibility-focused MutationObserver that watches for\n * role, accessible name, and ARIA state attribute changes, emitting\n * normalized accessibility events.\n *\n * Only observes attribute mutations on the specific ARIA attributes listed.\n * Text content changes, style changes, and child list mutations are ignored.\n */\nexport function createMutationObserver(\n options: MutationObserverOptions\n): AccessibilityMutationObserver {\n const { document: doc, onEvent, getTimestamp } = options;\n\n let observer: MutationObserver | null = null;\n let active = false;\n\n function handleMutations(mutations: MutationRecord[]): void {\n if (!active) return;\n\n for (const mutation of mutations) {\n if (mutation.type !== 'attributes') {\n continue;\n }\n\n const attributeName = mutation.attributeName;\n if (!attributeName) {\n continue;\n }\n\n const target = mutation.target;\n if (!(target instanceof Element)) {\n continue;\n }\n\n // Route to the appropriate handler based on attribute category\n if (attributeName === ROLE_ATTRIBUTE) {\n handleRoleChange(target, mutation.oldValue);\n } else if (NAME_ATTRIBUTES.has(attributeName)) {\n handleNameChange(target, attributeName, mutation.oldValue);\n } else if (STATE_ATTRIBUTES.has(attributeName)) {\n handleStateChange(target, attributeName, mutation.oldValue);\n }\n // All other attributes are filtered out by the attributeFilter config\n }\n }\n\n function handleRoleChange(element: Element, oldValue: string | null): void {\n const previousRole = oldValue?.trim() || getImplicitRole(element);\n const newRole = element.getAttribute('role')?.trim() || getImplicitRole(element);\n\n // Don't emit if the effective role hasn't actually changed\n if (previousRole === newRole) {\n return;\n }\n\n const eventTarget = buildEventTarget(element);\n const payload: RoleChangedPayload = {\n kind: 'role_changed',\n previousRole,\n newRole,\n };\n\n onEvent({\n type: 'ROLE_CHANGED',\n timestamp: getTimestamp(),\n target: eventTarget,\n payload,\n });\n }\n\n function handleNameChange(\n element: Element,\n attributeName: string,\n oldValue: string | null\n ): void {\n let previousName: string;\n let newName: string;\n\n if (attributeName === 'aria-label') {\n // For aria-label changes, the old value is the previous label\n previousName = oldValue?.trim() || '';\n newName = computeAccessibleName(element, doc);\n\n // If old value was empty, try to compute what the name was from other sources\n if (!previousName && oldValue === null) {\n // aria-label was just added; previous name was from labelledby or textContent\n // We can approximate by checking other sources\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy) {\n previousName = resolveAriaLabelledBy(element, labelledBy);\n } else {\n previousName = element.textContent?.trim() || '';\n }\n }\n } else {\n // aria-labelledby changed\n // Resolve the old labelledby references for the previous name\n previousName = oldValue ? resolveAriaLabelledBy(element, oldValue) : '';\n if (!previousName && oldValue === null) {\n // aria-labelledby was just added; previous name was from aria-label or textContent\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel) {\n previousName = ariaLabel.trim();\n } else {\n previousName = element.textContent?.trim() || '';\n }\n }\n newName = computeAccessibleName(element, doc);\n }\n\n // Don't emit if the accessible name hasn't actually changed\n if (previousName === newName) {\n return;\n }\n\n const eventTarget = buildEventTarget(element);\n const payload: AccessibleNameChangedPayload = {\n kind: 'accessible_name_changed',\n previousName,\n newName,\n };\n\n onEvent({\n type: 'ACCESSIBLE_NAME_CHANGED',\n timestamp: getTimestamp(),\n target: eventTarget,\n payload,\n });\n }\n\n function handleStateChange(\n element: Element,\n attributeName: string,\n oldValue: string | null\n ): void {\n const currentValue = element.getAttribute(attributeName);\n\n // Normalize values: treat \"true\"/\"false\" as booleans\n const normalizedOld = normalizeStateValue(oldValue);\n const normalizedNew = normalizeStateValue(currentValue);\n\n // Don't emit if the state hasn't actually changed\n if (normalizedOld === normalizedNew) {\n return;\n }\n\n const eventTarget = buildEventTarget(element);\n const payload: StateChangedPayload = {\n kind: 'state_changed',\n attribute: attributeName,\n previousValue: normalizedOld,\n newValue: normalizedNew,\n };\n\n onEvent({\n type: 'STATE_CHANGED',\n timestamp: getTimestamp(),\n target: eventTarget,\n payload,\n });\n }\n\n // ---------------------------------------------------------------------------\n // Helpers\n // ---------------------------------------------------------------------------\n\n function buildEventTarget(element: Element): A11yEventTarget {\n return {\n role: getElementRole(element),\n accessibleName: computeAccessibleName(element, doc),\n selector: generateSelector(element),\n };\n }\n\n /**\n * Get the implicit role for an element based on tag name.\n * Used as fallback when the explicit role attribute is absent.\n */\n function getImplicitRole(element: Element): string {\n const tagName = element.tagName.toLowerCase();\n switch (tagName) {\n case 'button':\n return 'button';\n case 'a':\n return element.hasAttribute('href') ? 'link' : 'generic';\n case 'input': {\n const type = (element.getAttribute('type') || 'text').toLowerCase();\n switch (type) {\n case 'button':\n case 'submit':\n case 'reset':\n case 'image':\n return 'button';\n case 'checkbox':\n return 'checkbox';\n case 'radio':\n return 'radio';\n default:\n return 'textbox';\n }\n }\n default:\n return 'generic';\n }\n }\n\n function resolveAriaLabelledBy(\n element: Element,\n idRefs: string\n ): string {\n const ownerDoc = element.ownerDocument;\n if (!ownerDoc) {\n return '';\n }\n\n const ids = idRefs.trim().split(/\\s+/).filter(Boolean);\n const parts: string[] = [];\n for (const id of ids) {\n const referenced = ownerDoc.getElementById(id);\n if (referenced && referenced.textContent) {\n parts.push(referenced.textContent.trim());\n }\n }\n\n return parts.join(' ');\n }\n\n function normalizeStateValue(value: string | null): string | boolean | null {\n if (value === null) {\n return null;\n }\n if (value === 'true') {\n return true;\n }\n if (value === 'false') {\n return false;\n }\n return value;\n }\n\n // ---------------------------------------------------------------------------\n // Public interface\n // ---------------------------------------------------------------------------\n\n return {\n start(): void {\n if (active) return;\n active = true;\n\n observer = new MutationObserver(handleMutations);\n observer.observe(doc.body ?? doc.documentElement, {\n attributes: true,\n attributeOldValue: true,\n attributeFilter: OBSERVED_ATTRIBUTES,\n subtree: true,\n });\n },\n\n stop(): void {\n if (!active) return;\n active = false;\n\n if (observer) {\n observer.disconnect();\n observer = null;\n }\n },\n\n get isActive(): boolean {\n return active;\n },\n };\n}\n","/**\n * Live Region Observer\n *\n * Detects text content changes within elements marked with aria-live or\n * implicit live region roles (alert, status, log, marquee, timer).\n * Emits ANNOUNCEMENT events with politeness level and announced text.\n *\n * Handles:\n * - Elements with explicit aria-live attribute (polite/assertive)\n * - Elements with role=\"alert\" (implicit assertive)\n * - Elements with role=\"status\"/\"log\"/\"marquee\"/\"timer\" (implicit polite)\n * - aria-atomic=\"true\" (read entire region vs changed nodes only)\n * - Dynamically added live regions (watched via document-level observer)\n */\n\nimport type { AccessibilityEvent, EventTarget as A11yEventTarget } from '../types';\nimport { generateSelector } from '../selector';\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** Callback invoked when the observer detects a live region announcement. */\nexport type LiveRegionEventCallback = (event: Omit<AccessibilityEvent, 'timestamp'>) => void;\n\n/** Roles that implicitly create live regions. */\nconst IMPLICIT_LIVE_ROLES = new Set(['alert', 'status', 'log', 'marquee', 'timer']);\n\n/** Map from implicit role to politeness level. */\nconst ROLE_POLITENESS_MAP: Record<string, 'polite' | 'assertive'> = {\n alert: 'assertive',\n status: 'polite',\n log: 'polite',\n marquee: 'polite',\n timer: 'polite',\n};\n\n// ---------------------------------------------------------------------------\n// Observer Interface\n// ---------------------------------------------------------------------------\n\nexport interface LiveRegionObserver {\n /** Start observing live regions for content changes. */\n start(): void;\n /** Stop observing and clean up all mutation observers. */\n stop(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Implementation\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a live region observer that watches for content changes in\n * aria-live regions and emits ANNOUNCEMENT events.\n *\n * @param document - The document to observe\n * @param callback - Function called with AccessibilityEvent for each announcement\n * @returns LiveRegionObserver with start/stop lifecycle methods\n */\nexport function createLiveRegionObserver(\n document: Document,\n callback: LiveRegionEventCallback\n): LiveRegionObserver {\n /** MutationObserver for content changes within known live regions. */\n let contentObserver: MutationObserver | null = null;\n\n /** MutationObserver for detecting new live regions added to the document. */\n let documentObserver: MutationObserver | null = null;\n\n /** Set of currently tracked live region elements. */\n const trackedRegions = new Set<Element>();\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n /**\n * Determine if an element is a live region and return its politeness level.\n * Returns null if the element is not a live region.\n */\n function getLiveRegionPoliteness(element: Element): 'polite' | 'assertive' | null {\n // Explicit aria-live takes precedence\n const ariaLive = element.getAttribute('aria-live');\n if (ariaLive === 'assertive') return 'assertive';\n if (ariaLive === 'polite') return 'polite';\n // aria-live=\"off\" means not a live region\n if (ariaLive === 'off') return null;\n\n // Check implicit live region roles\n const role = element.getAttribute('role');\n if (role && IMPLICIT_LIVE_ROLES.has(role)) {\n return ROLE_POLITENESS_MAP[role] || 'polite';\n }\n\n // If aria-live has another value (non-standard), treat as polite\n if (ariaLive && ariaLive !== 'off') return 'polite';\n\n return null;\n }\n\n /**\n * Determine whether the live region uses atomic reading\n * (entire region text vs only changed nodes).\n */\n function isAtomic(element: Element): boolean {\n return element.getAttribute('aria-atomic') === 'true';\n }\n\n /**\n * Build the EventTarget info for a live region element.\n */\n function buildEventTarget(element: Element): A11yEventTarget {\n const role = element.getAttribute('role') || 'region';\n const accessibleName =\n element.getAttribute('aria-label') ||\n element.getAttribute('aria-labelledby') ||\n '';\n const selector = generateSelector(element);\n\n return { role, accessibleName, selector };\n }\n\n /**\n * Extract text content from a list of added nodes (text nodes and elements).\n */\n function getTextFromNodes(nodes: NodeList): string {\n const parts: string[] = [];\n nodes.forEach((node) => {\n if (node.nodeType === Node.TEXT_NODE) {\n const text = node.textContent?.trim();\n if (text) parts.push(text);\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n const text = (node as Element).textContent?.trim();\n if (text) parts.push(text);\n }\n });\n return parts.join(' ').trim();\n }\n\n /**\n * Emit an ANNOUNCEMENT event for a live region content change.\n */\n function emitAnnouncement(\n liveRegion: Element,\n text: string,\n politeness: 'polite' | 'assertive'\n ): void {\n if (!text) return;\n\n const target = buildEventTarget(liveRegion);\n\n callback({\n type: 'ANNOUNCEMENT',\n target,\n payload: {\n kind: 'announcement',\n politeness,\n text,\n },\n });\n }\n\n /**\n * Find the closest ancestor (or self) that is a tracked live region.\n */\n function findLiveRegionAncestor(node: Node): Element | null {\n let current: Node | null = node;\n while (current) {\n if (current.nodeType === Node.ELEMENT_NODE && trackedRegions.has(current as Element)) {\n return current as Element;\n }\n current = current.parentNode;\n }\n return null;\n }\n\n // -------------------------------------------------------------------------\n // Content Mutation Handling\n // -------------------------------------------------------------------------\n\n /**\n * Handle mutations within tracked live regions.\n */\n function handleContentMutations(mutations: MutationRecord[]): void {\n // Group mutations by their live region ancestor to avoid duplicate announcements\n const regionChanges = new Map<Element, { addedText: string[]; charDataChanged: boolean }>();\n\n for (const mutation of mutations) {\n const liveRegion = findLiveRegionAncestor(mutation.target);\n if (!liveRegion) continue;\n\n if (!regionChanges.has(liveRegion)) {\n regionChanges.set(liveRegion, { addedText: [], charDataChanged: false });\n }\n const changes = regionChanges.get(liveRegion)!;\n\n if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {\n const text = getTextFromNodes(mutation.addedNodes);\n if (text) {\n changes.addedText.push(text);\n }\n } else if (mutation.type === 'characterData') {\n changes.charDataChanged = true;\n }\n }\n\n // Emit announcements for each live region that had changes\n for (const [region, changes] of regionChanges) {\n const politeness = getLiveRegionPoliteness(region);\n if (!politeness) continue;\n\n let text: string;\n if (isAtomic(region)) {\n // aria-atomic=\"true\": read the entire region's text content\n text = region.textContent?.trim() || '';\n } else {\n // Non-atomic: only announce changed/added content\n if (changes.addedText.length > 0) {\n text = changes.addedText.join(' ').trim();\n } else if (changes.charDataChanged) {\n // characterData changed but no new nodes — read updated text\n text = region.textContent?.trim() || '';\n } else {\n text = '';\n }\n }\n\n emitAnnouncement(region, text, politeness);\n }\n }\n\n // -------------------------------------------------------------------------\n // Document Mutation Handling (detect new live regions)\n // -------------------------------------------------------------------------\n\n /**\n * Handle document-level mutations to detect new live regions being added.\n */\n function handleDocumentMutations(mutations: MutationRecord[]): void {\n for (const mutation of mutations) {\n if (mutation.type !== 'childList') continue;\n\n mutation.addedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const element = node as Element;\n\n // Check if the added element itself is a live region\n if (getLiveRegionPoliteness(element) !== null && !trackedRegions.has(element)) {\n trackRegion(element);\n }\n\n // Check descendants for live regions\n const descendants = element.querySelectorAll('[aria-live], [role]');\n descendants.forEach((desc) => {\n if (getLiveRegionPoliteness(desc) !== null && !trackedRegions.has(desc)) {\n trackRegion(desc);\n }\n });\n });\n\n // Handle removed nodes: untrack regions that are removed from DOM\n mutation.removedNodes.forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) return;\n const element = node as Element;\n\n if (trackedRegions.has(element)) {\n trackedRegions.delete(element);\n }\n\n // Remove descendants\n const descendants = element.querySelectorAll('[aria-live], [role]');\n descendants.forEach((desc) => {\n trackedRegions.delete(desc);\n });\n });\n }\n }\n\n /**\n * Track a new live region element.\n */\n function trackRegion(element: Element): void {\n trackedRegions.add(element);\n }\n\n // -------------------------------------------------------------------------\n // Discovery\n // -------------------------------------------------------------------------\n\n /**\n * Find all existing live regions in the document and start tracking them.\n */\n function discoverExistingRegions(): void {\n // Elements with explicit aria-live\n const ariaLiveElements = document.querySelectorAll('[aria-live]');\n ariaLiveElements.forEach((el) => {\n if (getLiveRegionPoliteness(el) !== null) {\n trackRegion(el);\n }\n });\n\n // Elements with implicit live region roles\n IMPLICIT_LIVE_ROLES.forEach((role) => {\n const roleElements = document.querySelectorAll(`[role=\"${role}\"]`);\n roleElements.forEach((el) => {\n if (!trackedRegions.has(el)) {\n trackRegion(el);\n }\n });\n });\n }\n\n // -------------------------------------------------------------------------\n // Lifecycle\n // -------------------------------------------------------------------------\n\n function start(): void {\n // Discover existing live regions\n discoverExistingRegions();\n\n // Set up content observer for changes within live regions\n contentObserver = new MutationObserver(handleContentMutations);\n\n // Observe the entire document body for childList and characterData changes\n // in subtrees. We filter by live region ancestry in the handler.\n const body = document.body;\n if (body) {\n contentObserver.observe(body, {\n childList: true,\n characterData: true,\n subtree: true,\n characterDataOldValue: true,\n });\n }\n\n // Set up document observer for detecting new live regions being added\n documentObserver = new MutationObserver(handleDocumentMutations);\n if (body) {\n documentObserver.observe(body, {\n childList: true,\n subtree: true,\n });\n }\n }\n\n function stop(): void {\n if (contentObserver) {\n contentObserver.disconnect();\n contentObserver = null;\n }\n if (documentObserver) {\n documentObserver.disconnect();\n documentObserver = null;\n }\n trackedRegions.clear();\n }\n\n return { start, stop };\n}\n","/**\n * Dialog Observer\n *\n * Observes dialog open/close events on a document and emits DIALOG_OPENED\n * and DIALOG_CLOSED accessibility events. Tracks:\n * - Native `<dialog>` elements gaining/losing the `open` attribute\n * - Elements with role=\"dialog\" or role=\"alertdialog\" being added to the DOM\n * or having aria-modal change\n *\n * Maintains an internal stack of open dialogs for use by the heuristic\n * warnings module.\n *\n * @module runtime/observers/dialog-observer\n */\n\nimport type { AccessibilityEvent, EventTarget as A11yEventTarget } from '../types';\nimport { generateSelector } from '../selector';\n\n// ---------------------------------------------------------------------------\n// Accessible Name Computation (self-contained, dialog-aware)\n// ---------------------------------------------------------------------------\n\n/**\n * Compute the accessible name for a dialog element.\n * Checks aria-label, then aria-labelledby, then title attribute,\n * then falls back to the first heading's textContent within the dialog.\n */\nfunction computeDialogAccessibleName(element: Element, document: Document): string {\n // 1. aria-label takes precedence\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.trim()) {\n return ariaLabel.trim();\n }\n\n // 2. aria-labelledby: resolve referenced element(s) text content\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy && labelledBy.trim()) {\n const ids = labelledBy.trim().split(/\\s+/);\n const parts: string[] = [];\n for (const id of ids) {\n const referenced = document.getElementById(id);\n if (referenced && referenced.textContent) {\n parts.push(referenced.textContent.trim());\n }\n }\n const combined = parts.join(' ');\n if (combined) {\n return combined;\n }\n }\n\n // 3. title attribute\n const title = element.getAttribute('title');\n if (title && title.trim()) {\n return title.trim();\n }\n\n // 4. First heading within the dialog\n const heading = element.querySelector('h1, h2, h3, h4, h5, h6');\n if (heading && heading.textContent && heading.textContent.trim()) {\n return heading.textContent.trim();\n }\n\n return '';\n}\n\n// ---------------------------------------------------------------------------\n// Role Resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Determine the role of a dialog element.\n * Returns the explicit role attribute value, or 'dialog' for native <dialog>.\n */\nfunction getDialogRole(element: Element): string {\n const explicitRole = element.getAttribute('role');\n if (explicitRole && explicitRole.trim()) {\n return explicitRole.trim();\n }\n\n if (element.tagName.toLowerCase() === 'dialog') {\n return 'dialog';\n }\n\n return 'generic';\n}\n\n// ---------------------------------------------------------------------------\n// Dialog Detection Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Check if an element is a dialog (native <dialog> or role=\"dialog\" / role=\"alertdialog\").\n */\nfunction isDialogElement(element: Element): boolean {\n if (element.tagName.toLowerCase() === 'dialog') {\n return true;\n }\n const role = element.getAttribute('role');\n return role === 'dialog' || role === 'alertdialog';\n}\n\n/**\n * Determine if a dialog is modal.\n * A dialog is modal if:\n * - It's a native <dialog> opened via showModal() (has the `open` attribute and is the top layer)\n * - It has aria-modal=\"true\"\n */\nfunction isDialogModal(element: Element): boolean {\n const ariaModal = element.getAttribute('aria-modal');\n if (ariaModal === 'true') {\n return true;\n }\n return false;\n}\n\n// ---------------------------------------------------------------------------\n// Dialog Observer\n// ---------------------------------------------------------------------------\n\n/** Callback type for emitting accessibility events from the observer. */\nexport type DialogEventEmitter = (event: AccessibilityEvent) => void;\n\nexport interface DialogObserverOptions {\n /** The document to observe dialog events on */\n document: Document;\n /** Callback to emit accessibility events */\n onEvent: DialogEventEmitter;\n /** Function to get the current timestamp (ms since session start) */\n getTimestamp: () => number;\n}\n\nexport interface DialogObserver {\n /** Start observing dialog open/close events */\n start(): void;\n /** Stop observing dialog events */\n stop(): void;\n /** Whether the observer is currently active */\n readonly isActive: boolean;\n /** Get the current stack of open dialog names */\n getOpenDialogs(): string[];\n}\n\n/** Internal representation of a tracked open dialog */\ninterface TrackedDialog {\n element: Element;\n name: string;\n selector: string;\n}\n\n/**\n * Creates a DialogObserver that watches for dialog open/close events\n * and emits DIALOG_OPENED / DIALOG_CLOSED accessibility events.\n */\nexport function createDialogObserver(options: DialogObserverOptions): DialogObserver {\n const { document: doc, onEvent, getTimestamp } = options;\n\n let active = false;\n let mutationObserver: MutationObserver | null = null;\n const openDialogStack: TrackedDialog[] = [];\n\n function buildEventTarget(element: Element): A11yEventTarget {\n return {\n role: getDialogRole(element),\n accessibleName: computeDialogAccessibleName(element, doc),\n selector: generateSelector(element),\n };\n }\n\n function emitDialogOpened(element: Element): void {\n const name = computeDialogAccessibleName(element, doc);\n const isModal = isDialogModal(element);\n const target = buildEventTarget(element);\n\n // Add to open dialog stack\n openDialogStack.push({\n element,\n name,\n selector: target.selector,\n });\n\n const a11yEvent: AccessibilityEvent = {\n type: 'DIALOG_OPENED',\n timestamp: getTimestamp(),\n target,\n payload: {\n kind: 'dialog_opened',\n dialogName: name,\n isModal,\n },\n };\n\n onEvent(a11yEvent);\n }\n\n function emitDialogClosed(element: Element): void {\n const name = computeDialogAccessibleName(element, doc);\n const target = buildEventTarget(element);\n\n // Remove from open dialog stack\n const index = openDialogStack.findIndex((d) => d.element === element);\n if (index !== -1) {\n openDialogStack.splice(index, 1);\n }\n\n const a11yEvent: AccessibilityEvent = {\n type: 'DIALOG_CLOSED',\n timestamp: getTimestamp(),\n target,\n payload: {\n kind: 'dialog_closed',\n dialogName: name,\n },\n };\n\n onEvent(a11yEvent);\n }\n\n function isTrackedAsOpen(element: Element): boolean {\n return openDialogStack.some((d) => d.element === element);\n }\n\n function handleMutations(mutations: MutationRecord[]): void {\n if (!active) return;\n\n for (const mutation of mutations) {\n // Handle attribute changes\n if (mutation.type === 'attributes') {\n const target = mutation.target;\n if (!(target instanceof doc.defaultView!.Element)) continue;\n\n // Native <dialog> open attribute change\n if (\n mutation.attributeName === 'open' &&\n target.tagName.toLowerCase() === 'dialog'\n ) {\n if (target.hasAttribute('open')) {\n // Dialog opened\n if (!isTrackedAsOpen(target)) {\n emitDialogOpened(target);\n }\n } else {\n // Dialog closed\n if (isTrackedAsOpen(target)) {\n emitDialogClosed(target);\n }\n }\n }\n\n // aria-modal change on role=\"dialog\" or role=\"alertdialog\"\n if (mutation.attributeName === 'aria-modal' && isDialogElement(target)) {\n // If the dialog is already tracked, the modal status changed but\n // it's still open - we could emit an update, but per spec we just\n // track open/close. The modal status is captured at open time.\n // If it wasn't tracked and now has aria-modal=\"true\", check visibility.\n if (!isTrackedAsOpen(target) && isVisibleDialog(target)) {\n emitDialogOpened(target);\n }\n }\n\n // role attribute change - element might have become a dialog\n if (mutation.attributeName === 'role') {\n const oldRole = mutation.oldValue;\n const newRole = target.getAttribute('role');\n const wasDialog = oldRole === 'dialog' || oldRole === 'alertdialog';\n const isNowDialog = newRole === 'dialog' || newRole === 'alertdialog';\n\n if (!wasDialog && isNowDialog && isVisibleDialog(target)) {\n emitDialogOpened(target);\n } else if (wasDialog && !isNowDialog && isTrackedAsOpen(target)) {\n emitDialogClosed(target);\n }\n }\n }\n\n // Handle added nodes (role=\"dialog\" elements added to the DOM)\n if (mutation.type === 'childList') {\n for (let i = 0; i < mutation.addedNodes.length; i++) {\n const node = mutation.addedNodes[i];\n if (!(node instanceof doc.defaultView!.Element)) continue;\n\n // Check the added node itself\n if (isDialogElement(node) && isVisibleDialog(node)) {\n if (!isTrackedAsOpen(node)) {\n emitDialogOpened(node);\n }\n }\n\n // Check descendants of the added node\n const dialogDescendants = node.querySelectorAll(\n 'dialog[open], [role=\"dialog\"], [role=\"alertdialog\"]'\n );\n for (let j = 0; j < dialogDescendants.length; j++) {\n const dialog = dialogDescendants[j];\n if (isVisibleDialog(dialog) && !isTrackedAsOpen(dialog)) {\n emitDialogOpened(dialog);\n }\n }\n }\n\n // Handle removed nodes - dialogs removed from DOM\n for (let i = 0; i < mutation.removedNodes.length; i++) {\n const node = mutation.removedNodes[i];\n if (!(node instanceof doc.defaultView!.Element)) continue;\n\n // Check the removed node itself\n if (isTrackedAsOpen(node)) {\n emitDialogClosed(node);\n }\n\n // Check descendants of the removed node\n const trackedInRemoved = openDialogStack.filter((d) =>\n node.contains(d.element)\n );\n for (const tracked of trackedInRemoved) {\n emitDialogClosed(tracked.element);\n }\n }\n }\n }\n }\n\n /**\n * Determine if a dialog element is considered \"visible\" / open.\n * - Native <dialog>: must have `open` attribute\n * - ARIA dialog: considered visible when added to DOM (we can't reliably\n * detect CSS visibility in jsdom, so we assume role=\"dialog\" elements\n * in the DOM are intended to be visible)\n */\n function isVisibleDialog(element: Element): boolean {\n if (element.tagName.toLowerCase() === 'dialog') {\n return element.hasAttribute('open');\n }\n // For ARIA dialogs, we treat presence in the DOM as \"visible\"\n // In a real browser, we'd check computed styles, but jsdom doesn't support that reliably\n return true;\n }\n\n return {\n start(): void {\n if (active) return;\n active = true;\n openDialogStack.length = 0;\n\n // Scan existing open dialogs on start\n const existingDialogs = doc.querySelectorAll(\n 'dialog[open], [role=\"dialog\"], [role=\"alertdialog\"]'\n );\n for (let i = 0; i < existingDialogs.length; i++) {\n const dialog = existingDialogs[i];\n if (isVisibleDialog(dialog)) {\n // Track them without emitting events (they were already open before observation)\n openDialogStack.push({\n element: dialog,\n name: computeDialogAccessibleName(dialog, doc),\n selector: generateSelector(dialog),\n });\n }\n }\n\n // Set up MutationObserver\n mutationObserver = new MutationObserver(handleMutations);\n mutationObserver.observe(doc.body || doc.documentElement, {\n attributes: true,\n attributeFilter: ['open', 'role', 'aria-modal'],\n attributeOldValue: true,\n childList: true,\n subtree: true,\n });\n },\n\n stop(): void {\n if (!active) return;\n active = false;\n\n if (mutationObserver) {\n mutationObserver.disconnect();\n mutationObserver = null;\n }\n\n openDialogStack.length = 0;\n },\n\n get isActive(): boolean {\n return active;\n },\n\n getOpenDialogs(): string[] {\n return openDialogStack.map((d) => d.name);\n },\n };\n}\n","/**\n * Runtime Accessibility Engine\n *\n * Coordinates all accessibility observers (focus, mutation, live region, dialog)\n * into a single engine that collects normalized AccessibilityEvents during\n * component interaction. Events are timestamped relative to session start\n * and stored in chronological order.\n *\n * @module runtime/engine\n */\n\nimport type { AccessibilityEvent } from './types';\nimport { createFocusObserver, type FocusObserver } from './observers/focus-observer';\nimport { createMutationObserver, type AccessibilityMutationObserver } from './observers/mutation-observer';\nimport { createLiveRegionObserver, type LiveRegionObserver } from './observers/live-region-observer';\nimport { createDialogObserver, type DialogObserver } from './observers/dialog-observer';\n\n// ---------------------------------------------------------------------------\n// Engine Options\n// ---------------------------------------------------------------------------\n\nexport interface EngineOptions {\n /** Document to observe */\n document: Document;\n /** Whether to enable heuristic warnings (default: true) */\n heuristics?: boolean;\n /** Custom settle time in ms (default: 100) */\n settleTime?: number;\n}\n\n// ---------------------------------------------------------------------------\n// Engine Interface\n// ---------------------------------------------------------------------------\n\nexport interface RuntimeAccessibilityEngine {\n /** Attach observers to the document and begin event collection */\n attach(): void;\n /** Detach all observers and stop collection */\n detach(): void;\n /** Get all collected events since attach (chronological order) */\n getEvents(): AccessibilityEvent[];\n /** Clear collected events without detaching */\n reset(): void;\n /** Whether the engine is currently attached */\n readonly isAttached: boolean;\n /** Expose dialog observer for heuristics module */\n readonly dialogObserver: { getOpenDialogs(): string[] };\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a RuntimeAccessibilityEngine that coordinates all observers\n * and collects accessibility events with monotonically increasing timestamps.\n */\nexport function createEngine(options: EngineOptions): RuntimeAccessibilityEngine {\n const { document: doc } = options;\n\n let attached = false;\n let sessionStart = 0;\n let events: AccessibilityEvent[] = [];\n\n // Timestamp function: returns ms elapsed since session start\n function getTimestamp(): number {\n return Date.now() - sessionStart;\n }\n\n // Shared event collector for focus, mutation, and dialog observers\n function collectEvent(event: AccessibilityEvent): void {\n events.push(event);\n }\n\n // Live region observer has a different callback signature:\n // it emits events without a timestamp, so we wrap to add one\n function collectLiveRegionEvent(event: Omit<AccessibilityEvent, 'timestamp'>): void {\n const fullEvent: AccessibilityEvent = {\n ...event,\n timestamp: getTimestamp(),\n } as AccessibilityEvent;\n events.push(fullEvent);\n }\n\n // Create all observers\n const focusObs: FocusObserver = createFocusObserver({\n document: doc,\n onEvent: collectEvent,\n getTimestamp,\n });\n\n const mutationObs: AccessibilityMutationObserver = createMutationObserver({\n document: doc,\n onEvent: collectEvent,\n getTimestamp,\n });\n\n const liveRegionObs: LiveRegionObserver = createLiveRegionObserver(\n doc,\n collectLiveRegionEvent\n );\n\n const dialogObs: DialogObserver = createDialogObserver({\n document: doc,\n onEvent: collectEvent,\n getTimestamp,\n });\n\n return {\n attach(): void {\n if (attached) return;\n attached = true;\n sessionStart = Date.now();\n events = [];\n\n // Start all observers\n focusObs.start();\n mutationObs.start();\n liveRegionObs.start();\n dialogObs.start();\n },\n\n detach(): void {\n if (!attached) return;\n attached = false;\n\n // Stop all observers\n focusObs.stop();\n mutationObs.stop();\n liveRegionObs.stop();\n dialogObs.stop();\n },\n\n getEvents(): AccessibilityEvent[] {\n // Events are already in chronological order due to single-threaded execution\n return [...events];\n },\n\n reset(): void {\n events = [];\n },\n\n get isAttached(): boolean {\n return attached;\n },\n\n get dialogObserver(): { getOpenDialogs(): string[] } {\n return {\n getOpenDialogs(): string[] {\n return dialogObs.getOpenDialogs();\n },\n };\n },\n };\n}\n","/**\n * Interaction Execution\n *\n * Executes interaction sequences against a document, dispatching proper\n * DOM events (keyboard, mouse, focus) and emitting KEYBOARD_ACTION\n * accessibility events for each action.\n *\n * @module runtime/interactions\n */\n\nimport type { InteractionAction, InteractionSequence, AccessibilityEvent } from './types';\nimport { generateSelector } from './selector';\n\n// ---------------------------------------------------------------------------\n// Key Mappings\n// ---------------------------------------------------------------------------\n\ninterface KeyInfo {\n key: string;\n code: string;\n keyCode: number;\n}\n\nconst KEY_MAP: Record<string, KeyInfo> = {\n Tab: { key: 'Tab', code: 'Tab', keyCode: 9 },\n Escape: { key: 'Escape', code: 'Escape', keyCode: 27 },\n Enter: { key: 'Enter', code: 'Enter', keyCode: 13 },\n ' ': { key: ' ', code: 'Space', keyCode: 32 },\n ArrowUp: { key: 'ArrowUp', code: 'ArrowUp', keyCode: 38 },\n ArrowDown: { key: 'ArrowDown', code: 'ArrowDown', keyCode: 40 },\n ArrowLeft: { key: 'ArrowLeft', code: 'ArrowLeft', keyCode: 37 },\n ArrowRight: { key: 'ArrowRight', code: 'ArrowRight', keyCode: 39 },\n};\n\n// ---------------------------------------------------------------------------\n// Focusable Element Detection\n// ---------------------------------------------------------------------------\n\nconst FOCUSABLE_SELECTOR = [\n 'button:not([disabled])',\n 'a[href]',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\n/**\n * Get all focusable elements in DOM order, excluding those with tabindex=\"-1\".\n */\nfunction getFocusableElements(document: Document): Element[] {\n return Array.from(document.querySelectorAll(FOCUSABLE_SELECTOR));\n}\n\n// ---------------------------------------------------------------------------\n// Accessible Name and Role (lightweight versions for event target)\n// ---------------------------------------------------------------------------\n\nfunction computeAccessibleName(element: Element, document: Document): string {\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.trim()) {\n return ariaLabel.trim();\n }\n\n const labelledBy = element.getAttribute('aria-labelledby');\n if (labelledBy && labelledBy.trim()) {\n const ids = labelledBy.trim().split(/\\s+/);\n const parts: string[] = [];\n for (const id of ids) {\n const referenced = document.getElementById(id);\n if (referenced && referenced.textContent) {\n parts.push(referenced.textContent.trim());\n }\n }\n const combined = parts.join(' ');\n if (combined) return combined;\n }\n\n const textContent = element.textContent;\n if (textContent && textContent.trim()) {\n return textContent.trim();\n }\n\n return '';\n}\n\nfunction getElementRole(element: Element): string {\n const explicitRole = element.getAttribute('role');\n if (explicitRole && explicitRole.trim()) {\n return explicitRole.trim();\n }\n\n const tagName = element.tagName.toLowerCase();\n switch (tagName) {\n case 'button':\n return 'button';\n case 'a':\n return element.hasAttribute('href') ? 'link' : 'generic';\n case 'input': {\n const type = (element.getAttribute('type') || 'text').toLowerCase();\n switch (type) {\n case 'button':\n case 'submit':\n case 'reset':\n case 'image':\n return 'button';\n case 'checkbox':\n return 'checkbox';\n case 'radio':\n return 'radio';\n case 'range':\n return 'slider';\n case 'search':\n return 'searchbox';\n default:\n return 'textbox';\n }\n }\n case 'textarea':\n return 'textbox';\n case 'select':\n return element.hasAttribute('multiple') ? 'listbox' : 'combobox';\n case 'dialog':\n return 'dialog';\n default:\n return 'generic';\n }\n}\n\n// ---------------------------------------------------------------------------\n// Event Target Builder\n// ---------------------------------------------------------------------------\n\nfunction buildEventTarget(element: Element, document: Document) {\n return {\n role: getElementRole(element),\n accessibleName: computeAccessibleName(element, document),\n selector: generateSelector(element),\n };\n}\n\n// ---------------------------------------------------------------------------\n// Keyboard Event Dispatching\n// ---------------------------------------------------------------------------\n\ninterface KeyboardEventOptions {\n key: string;\n code: string;\n keyCode: number;\n shiftKey?: boolean;\n ctrlKey?: boolean;\n altKey?: boolean;\n metaKey?: boolean;\n}\n\n/**\n * Dispatch a full keyboard event sequence (keydown, keypress, keyup)\n * on the currently focused element.\n */\nfunction dispatchKeyboardEvent(\n document: Document,\n options: KeyboardEventOptions\n): void {\n const target = document.activeElement || document.body;\n\n const commonProps = {\n key: options.key,\n code: options.code,\n keyCode: options.keyCode,\n which: options.keyCode,\n shiftKey: options.shiftKey || false,\n ctrlKey: options.ctrlKey || false,\n altKey: options.altKey || false,\n metaKey: options.metaKey || false,\n bubbles: true,\n cancelable: true,\n };\n\n target.dispatchEvent(new KeyboardEvent('keydown', commonProps));\n // keypress is deprecated but still dispatched for compatibility\n // Only dispatch keypress for printable characters\n if (options.key.length === 1) {\n target.dispatchEvent(new KeyboardEvent('keypress', commonProps));\n }\n target.dispatchEvent(new KeyboardEvent('keyup', commonProps));\n}\n\n// ---------------------------------------------------------------------------\n// Key Combo Parsing\n// ---------------------------------------------------------------------------\n\ninterface ParsedCombo {\n key: string;\n modifiers: string[];\n shiftKey: boolean;\n ctrlKey: boolean;\n altKey: boolean;\n metaKey: boolean;\n}\n\n/**\n * Parse a key combination string like \"Control+Shift+A\" into its parts.\n */\nfunction parseKeyCombo(combo: string): ParsedCombo {\n const parts = combo.split('+');\n const modifiers: string[] = [];\n let shiftKey = false;\n let ctrlKey = false;\n let altKey = false;\n let metaKey = false;\n\n // The last part is the key, everything else is a modifier\n const key = parts[parts.length - 1];\n\n for (let i = 0; i < parts.length - 1; i++) {\n const mod = parts[i].toLowerCase();\n switch (mod) {\n case 'shift':\n shiftKey = true;\n modifiers.push('Shift');\n break;\n case 'control':\n case 'ctrl':\n ctrlKey = true;\n modifiers.push('Control');\n break;\n case 'alt':\n altKey = true;\n modifiers.push('Alt');\n break;\n case 'meta':\n case 'cmd':\n case 'command':\n metaKey = true;\n modifiers.push('Meta');\n break;\n }\n }\n\n return { key, modifiers, shiftKey, ctrlKey, altKey, metaKey };\n}\n\n/**\n * Get KeyInfo for a key string. Falls back to generating info from the key name.\n */\nfunction getKeyInfo(key: string): KeyInfo {\n if (KEY_MAP[key]) {\n return KEY_MAP[key];\n }\n // For single character keys\n if (key.length === 1) {\n return {\n key,\n code: `Key${key.toUpperCase()}`,\n keyCode: key.toUpperCase().charCodeAt(0),\n };\n }\n // For other named keys\n return {\n key,\n code: key,\n keyCode: 0,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Action Executors\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a click action on the element matching the selector.\n * Dispatches mousedown, mouseup, click events, and focuses the element.\n * If the element is not found, emits a WARNING event and continues.\n */\nfunction executeClick(\n selector: string,\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): void {\n const element = document.querySelector(selector);\n\n if (!element) {\n // Emit WARNING for missing element\n const warningEvent: AccessibilityEvent = {\n type: 'WARNING',\n timestamp: getTimestamp(),\n target: {\n role: 'generic',\n accessibleName: '',\n selector: selector,\n },\n payload: {\n kind: 'warning',\n message: `Element not found: ${selector}`,\n },\n };\n onEvent(warningEvent);\n return;\n }\n\n const eventProps = { bubbles: true, cancelable: true };\n\n element.dispatchEvent(new MouseEvent('mousedown', eventProps));\n element.dispatchEvent(new MouseEvent('mouseup', eventProps));\n element.dispatchEvent(new MouseEvent('click', eventProps));\n\n // Focus the element if it's focusable\n if ('focus' in element && typeof (element as HTMLElement).focus === 'function') {\n (element as HTMLElement).focus();\n }\n}\n\n/**\n * Execute a tab action: move focus to the next focusable element.\n */\nfunction executeTab(\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): void {\n const focusableElements = getFocusableElements(document);\n if (focusableElements.length === 0) return;\n\n const activeElement = document.activeElement;\n let currentIndex = -1;\n\n if (activeElement) {\n currentIndex = focusableElements.indexOf(activeElement);\n }\n\n // Move to next, wrapping around\n const nextIndex = (currentIndex + 1) % focusableElements.length;\n const nextElement = focusableElements[nextIndex] as HTMLElement;\n\n // Dispatch keyboard event on current element\n dispatchKeyboardEvent(document, {\n ...KEY_MAP['Tab'],\n shiftKey: false,\n });\n\n // Move focus\n if (nextElement && typeof nextElement.focus === 'function') {\n nextElement.focus();\n }\n\n // Emit KEYBOARD_ACTION event\n const target = document.activeElement || document.body;\n const keyboardEvent: AccessibilityEvent = {\n type: 'KEYBOARD_ACTION',\n timestamp: getTimestamp(),\n target: buildEventTarget(target as Element, document),\n payload: {\n kind: 'keyboard_action',\n key: 'Tab',\n modifiers: [],\n },\n };\n onEvent(keyboardEvent);\n}\n\n/**\n * Execute a shift+tab action: move focus to the previous focusable element.\n */\nfunction executeShiftTab(\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): void {\n const focusableElements = getFocusableElements(document);\n if (focusableElements.length === 0) return;\n\n const activeElement = document.activeElement;\n let currentIndex = -1;\n\n if (activeElement) {\n currentIndex = focusableElements.indexOf(activeElement);\n }\n\n // Move to previous, wrapping around\n const prevIndex = currentIndex <= 0 ? focusableElements.length - 1 : currentIndex - 1;\n const prevElement = focusableElements[prevIndex] as HTMLElement;\n\n // Dispatch keyboard event on current element\n dispatchKeyboardEvent(document, {\n ...KEY_MAP['Tab'],\n shiftKey: true,\n });\n\n // Move focus\n if (prevElement && typeof prevElement.focus === 'function') {\n prevElement.focus();\n }\n\n // Emit KEYBOARD_ACTION event\n const target = document.activeElement || document.body;\n const keyboardEvent: AccessibilityEvent = {\n type: 'KEYBOARD_ACTION',\n timestamp: getTimestamp(),\n target: buildEventTarget(target as Element, document),\n payload: {\n kind: 'keyboard_action',\n key: 'Tab',\n modifiers: ['Shift'],\n },\n };\n onEvent(keyboardEvent);\n}\n\n/**\n * Execute a simple keyboard action (escape, enter, space, arrow keys).\n */\nfunction executeKeyAction(\n keyName: string,\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): void {\n const keyInfo = KEY_MAP[keyName];\n if (!keyInfo) return;\n\n dispatchKeyboardEvent(document, {\n ...keyInfo,\n });\n\n // Emit KEYBOARD_ACTION event\n const target = document.activeElement || document.body;\n const keyboardEvent: AccessibilityEvent = {\n type: 'KEYBOARD_ACTION',\n timestamp: getTimestamp(),\n target: buildEventTarget(target as Element, document),\n payload: {\n kind: 'keyboard_action',\n key: keyName,\n modifiers: [],\n },\n };\n onEvent(keyboardEvent);\n}\n\n/**\n * Execute a custom key combination (e.g., \"Control+A\", \"Shift+Tab\").\n */\nfunction executeKeyCombo(\n combo: string,\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): void {\n const parsed = parseKeyCombo(combo);\n const keyInfo = getKeyInfo(parsed.key);\n\n dispatchKeyboardEvent(document, {\n ...keyInfo,\n shiftKey: parsed.shiftKey,\n ctrlKey: parsed.ctrlKey,\n altKey: parsed.altKey,\n metaKey: parsed.metaKey,\n });\n\n // Emit KEYBOARD_ACTION event\n const target = document.activeElement || document.body;\n const keyboardEvent: AccessibilityEvent = {\n type: 'KEYBOARD_ACTION',\n timestamp: getTimestamp(),\n target: buildEventTarget(target as Element, document),\n payload: {\n kind: 'keyboard_action',\n key: parsed.key,\n modifiers: parsed.modifiers,\n },\n };\n onEvent(keyboardEvent);\n}\n\n// ---------------------------------------------------------------------------\n// Public API\n// ---------------------------------------------------------------------------\n\n/**\n * Execute a single interaction action against the document.\n *\n * For keyboard actions, dispatches proper KeyboardEvent sequences (keydown, keypress, keyup).\n * For tab/shiftTab, computes next/previous focusable element and moves focus.\n * Emits KEYBOARD_ACTION events for each keyboard action.\n * Handles missing elements by emitting WARNING events and continuing.\n *\n * Click and wait actions do not emit KEYBOARD_ACTION events.\n */\nexport async function executeAction(\n action: InteractionAction,\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number\n): Promise<void> {\n switch (action.type) {\n case 'click':\n executeClick(action.selector, document, onEvent, getTimestamp);\n break;\n\n case 'tab':\n executeTab(document, onEvent, getTimestamp);\n break;\n\n case 'shiftTab':\n executeShiftTab(document, onEvent, getTimestamp);\n break;\n\n case 'escape':\n executeKeyAction('Escape', document, onEvent, getTimestamp);\n break;\n\n case 'enter':\n executeKeyAction('Enter', document, onEvent, getTimestamp);\n break;\n\n case 'space':\n executeKeyAction(' ', document, onEvent, getTimestamp);\n break;\n\n case 'arrowUp':\n executeKeyAction('ArrowUp', document, onEvent, getTimestamp);\n break;\n\n case 'arrowDown':\n executeKeyAction('ArrowDown', document, onEvent, getTimestamp);\n break;\n\n case 'arrowLeft':\n executeKeyAction('ArrowLeft', document, onEvent, getTimestamp);\n break;\n\n case 'arrowRight':\n executeKeyAction('ArrowRight', document, onEvent, getTimestamp);\n break;\n\n case 'key':\n executeKeyCombo(action.combo, document, onEvent, getTimestamp);\n break;\n\n case 'wait':\n // Wait does not emit any events\n await new Promise((resolve) => setTimeout(resolve, action.ms));\n break;\n }\n}\n\n/**\n * Execute an interaction sequence in order, with DOM stability waits between actions.\n *\n * Runs each action sequentially, waiting for `settleTime` milliseconds between actions\n * to allow the DOM to stabilize. This ensures observers can capture resulting changes\n * before the next action fires.\n *\n * @param sequence - The interaction sequence to execute\n * @param document - The target document\n * @param onEvent - Callback to emit accessibility events\n * @param getTimestamp - Function returning current timestamp in ms since session start\n * @param settleTime - Milliseconds to wait between actions for DOM stability (default: 100)\n */\nexport async function executeSequence(\n sequence: InteractionSequence,\n document: Document,\n onEvent: (event: AccessibilityEvent) => void,\n getTimestamp: () => number,\n settleTime: number = 100\n): Promise<void> {\n for (let i = 0; i < sequence.actions.length; i++) {\n const action = sequence.actions[i];\n\n await executeAction(action, document, onEvent, getTimestamp);\n\n // Wait for DOM stability between actions (except after the last action)\n if (i < sequence.actions.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, settleTime));\n }\n }\n}\n","/**\n * Heuristic Warning Analyzer\n *\n * Processes accessibility events one at a time and emits WARNING events\n * when common runtime accessibility anti-patterns are detected. Operates\n * independently of baselines, providing value from the first run.\n *\n * Detected patterns:\n * - Focus not moved into modal dialog within configured timeout (default: 100ms)\n * - Focus escaped modal dialog (focus moved to element outside open dialog)\n * - Rapid announcements (too many in a short window)\n * - Keyboard action with no accessibility response within timeout\n * - Focused element removed from DOM without explicit focus management\n *\n * Uses event timestamps (not real-time timers) for timeout detection,\n * enabling deterministic testing with jsdom.\n *\n * @module runtime/heuristics\n */\n\nimport type {\n AccessibilityEvent,\n EventTarget as A11yEventTarget,\n DialogOpenedPayload,\n WarningPayload,\n} from './types';\n\n// ---------------------------------------------------------------------------\n// Configuration\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration for heuristic warning thresholds.\n */\nexport interface HeuristicConfig {\n /** Time window to detect focus moving into dialog (default: 100ms) */\n dialogFocusTimeout: number;\n /** Time window to detect rapid announcements (default: 500ms) */\n rapidAnnouncementWindow: number;\n /** Threshold for rapid announcement count (default: 3) */\n rapidAnnouncementThreshold: number;\n /** Time window to detect keyboard action response (default: 200ms) */\n keyboardResponseTimeout: number;\n}\n\nconst DEFAULT_CONFIG: HeuristicConfig = {\n dialogFocusTimeout: 100,\n rapidAnnouncementWindow: 500,\n rapidAnnouncementThreshold: 3,\n keyboardResponseTimeout: 200,\n};\n\n// ---------------------------------------------------------------------------\n// Internal State Types\n// ---------------------------------------------------------------------------\n\n/** Tracks a pending dialog focus check */\ninterface PendingDialogFocus {\n /** Selector of the dialog that opened */\n dialogSelector: string;\n /** Name of the dialog for warning messages */\n dialogName: string;\n /** Timestamp when the dialog was opened */\n openedAt: number;\n /** Whether this dialog is modal */\n isModal: boolean;\n /** Whether focus has been moved into the dialog */\n resolved: boolean;\n}\n\n/** Tracks a pending keyboard response check */\ninterface PendingKeyboardResponse {\n /** The keyboard action event that started the check */\n event: AccessibilityEvent;\n /** Timestamp when the keyboard action occurred */\n timestamp: number;\n /** Whether an accessibility response has been received */\n resolved: boolean;\n}\n\n/** Tracks an open dialog for focus escape detection */\ninterface TrackedDialog {\n /** CSS selector of the dialog container */\n selector: string;\n /** Accessible name of the dialog */\n name: string;\n /** Whether this is a modal dialog */\n isModal: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Heuristic Analyzer Interface\n// ---------------------------------------------------------------------------\n\n/**\n * Processes accessibility events and detects runtime anti-patterns.\n */\nexport interface HeuristicAnalyzer {\n /** Process an event and return any warnings it triggers */\n process(event: AccessibilityEvent): AccessibilityEvent[];\n /** Get current open dialog selectors (for focus escape detection) */\n readonly openDialogs: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a heuristic analyzer that processes accessibility events and\n * emits warnings when common anti-patterns are detected.\n *\n * The analyzer uses event timestamps for timeout detection rather than\n * real-time timers, making it deterministic and testable with jsdom.\n */\nexport function createHeuristicAnalyzer(\n config?: Partial<HeuristicConfig>\n): HeuristicAnalyzer {\n const cfg: HeuristicConfig = { ...DEFAULT_CONFIG, ...config };\n\n // Internal state\n const trackedDialogs: TrackedDialog[] = [];\n const pendingDialogFocusChecks: PendingDialogFocus[] = [];\n const pendingKeyboardResponses: PendingKeyboardResponse[] = [];\n const announcementTimestamps: number[] = [];\n\n // Track the last known focused element selector for DOM removal detection\n let lastFocusedSelector: string | null = null;\n\n // ---------------------------------------------------------------------------\n // Helper: Create a WARNING event\n // ---------------------------------------------------------------------------\n\n function createWarning(\n timestamp: number,\n message: string,\n target: A11yEventTarget,\n relatedEvent?: AccessibilityEvent\n ): AccessibilityEvent {\n const payload: WarningPayload = {\n kind: 'warning',\n message,\n relatedEvent,\n };\n\n return {\n type: 'WARNING',\n timestamp,\n target,\n payload,\n };\n }\n\n // ---------------------------------------------------------------------------\n // Check: Dialog focus timeout expired\n // ---------------------------------------------------------------------------\n\n function checkExpiredDialogFocusTimeouts(\n currentTimestamp: number\n ): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n for (let i = pendingDialogFocusChecks.length - 1; i >= 0; i--) {\n const pending = pendingDialogFocusChecks[i];\n if (pending.resolved) continue;\n\n const elapsed = currentTimestamp - pending.openedAt;\n if (elapsed > cfg.dialogFocusTimeout) {\n // Only emit warning for modal dialogs\n if (pending.isModal) {\n warnings.push(\n createWarning(\n currentTimestamp,\n 'Focus was not moved into modal dialog',\n {\n role: 'dialog',\n accessibleName: pending.dialogName,\n selector: pending.dialogSelector,\n }\n )\n );\n }\n // Mark as resolved (expired) to avoid duplicate warnings\n pending.resolved = true;\n }\n }\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Check: Keyboard response timeout expired\n // ---------------------------------------------------------------------------\n\n function checkExpiredKeyboardResponses(\n currentTimestamp: number\n ): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n for (let i = pendingKeyboardResponses.length - 1; i >= 0; i--) {\n const pending = pendingKeyboardResponses[i];\n if (pending.resolved) continue;\n\n const elapsed = currentTimestamp - pending.timestamp;\n if (elapsed > cfg.keyboardResponseTimeout) {\n warnings.push(\n createWarning(\n currentTimestamp,\n 'Keyboard action produced no accessibility response',\n pending.event.target,\n pending.event\n )\n );\n pending.resolved = true;\n }\n }\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Check: Rapid announcements\n // ---------------------------------------------------------------------------\n\n function checkRapidAnnouncements(\n currentTimestamp: number\n ): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n // Remove old timestamps outside the window\n const windowStart = currentTimestamp - cfg.rapidAnnouncementWindow;\n while (announcementTimestamps.length > 0 && announcementTimestamps[0] < windowStart) {\n announcementTimestamps.shift();\n }\n\n // Check if threshold exceeded\n if (announcementTimestamps.length > cfg.rapidAnnouncementThreshold) {\n warnings.push(\n createWarning(\n currentTimestamp,\n 'Rapid announcements detected: assistive technology users may miss content',\n {\n role: 'region',\n accessibleName: '',\n selector: 'body',\n }\n )\n );\n\n // Clear timestamps to avoid repeated warnings for the same burst\n announcementTimestamps.length = 0;\n }\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Check: Focus escape from modal dialog\n // ---------------------------------------------------------------------------\n\n function checkFocusEscape(event: AccessibilityEvent): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n if (event.type !== 'FOCUS_CHANGED') return warnings;\n\n // Only check if there are open modal dialogs\n const modalDialogs = trackedDialogs.filter((d) => d.isModal);\n if (modalDialogs.length === 0) return warnings;\n\n const focusedSelector = event.target.selector;\n\n // Check if the focused element is outside all open modal dialogs\n for (const dialog of modalDialogs) {\n // Focus is outside the dialog if the focused element's selector\n // does not start with/contain the dialog's selector\n if (!isSelectorInside(focusedSelector, dialog.selector)) {\n warnings.push(\n createWarning(\n event.timestamp,\n 'Focus escaped modal dialog',\n event.target,\n event\n )\n );\n break; // One warning is enough\n }\n }\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Check: Focused element removed from DOM\n // ---------------------------------------------------------------------------\n\n function checkFocusedElementRemoved(\n event: AccessibilityEvent\n ): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n // DOM_MUTATION events where the target matches the last focused element\n // indicate the focused element may have been removed\n if (event.type === 'DOM_MUTATION' && lastFocusedSelector !== null) {\n if (event.target.selector === lastFocusedSelector) {\n warnings.push(\n createWarning(\n event.timestamp,\n 'Focused element removed without focus management',\n event.target,\n event\n )\n );\n }\n }\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Selector Containment Check\n // ---------------------------------------------------------------------------\n\n /**\n * Determines if `childSelector` represents an element inside the container\n * identified by `containerSelector`.\n *\n * Uses a simple heuristic: the child selector starts with the container\n * selector followed by a combinator (space, >, ~, +).\n */\n function isSelectorInside(\n childSelector: string,\n containerSelector: string\n ): boolean {\n // Direct match - element IS the container\n if (childSelector === containerSelector) return true;\n\n // Child selector starts with container selector path\n // e.g., container is \"#modal\" and child is \"#modal > .content > button\"\n if (childSelector.startsWith(containerSelector + ' ')) return true;\n if (childSelector.startsWith(containerSelector + ' > ')) return true;\n\n // Handle nth-child and descendant patterns\n // e.g., container is \"body > div:nth-child(2)\" and child is \"body > div:nth-child(2) > button\"\n if (childSelector.startsWith(containerSelector + '>')) return true;\n\n return false;\n }\n\n // ---------------------------------------------------------------------------\n // Event Processing\n // ---------------------------------------------------------------------------\n\n function processEvent(event: AccessibilityEvent): AccessibilityEvent[] {\n const warnings: AccessibilityEvent[] = [];\n\n // First, check for timeouts that may have expired given the current timestamp\n warnings.push(...checkExpiredDialogFocusTimeouts(event.timestamp));\n warnings.push(...checkExpiredKeyboardResponses(event.timestamp));\n\n // Process the event based on its type\n switch (event.type) {\n case 'DIALOG_OPENED': {\n const payload = event.payload as DialogOpenedPayload;\n const dialog: TrackedDialog = {\n selector: event.target.selector,\n name: payload.dialogName,\n isModal: payload.isModal,\n };\n trackedDialogs.push(dialog);\n\n // Set up pending focus check for modal dialogs\n if (payload.isModal) {\n pendingDialogFocusChecks.push({\n dialogSelector: event.target.selector,\n dialogName: payload.dialogName,\n openedAt: event.timestamp,\n isModal: true,\n resolved: false,\n });\n }\n break;\n }\n\n case 'DIALOG_CLOSED': {\n // Remove the dialog from tracked list\n const closedSelector = event.target.selector;\n const idx = trackedDialogs.findIndex(\n (d) => d.selector === closedSelector\n );\n if (idx !== -1) {\n trackedDialogs.splice(idx, 1);\n }\n\n // Resolve any pending focus checks for this dialog\n for (const pending of pendingDialogFocusChecks) {\n if (pending.dialogSelector === closedSelector && !pending.resolved) {\n pending.resolved = true;\n }\n }\n break;\n }\n\n case 'FOCUS_CHANGED': {\n // Resolve pending dialog focus checks if focus moved into dialog\n for (const pending of pendingDialogFocusChecks) {\n if (pending.resolved) continue;\n if (isSelectorInside(event.target.selector, pending.dialogSelector)) {\n pending.resolved = true;\n }\n }\n\n // Resolve pending keyboard responses (focus change is an accessibility response)\n for (const pending of pendingKeyboardResponses) {\n if (!pending.resolved) {\n pending.resolved = true;\n }\n }\n\n // Check for focus escaping modal dialogs\n warnings.push(...checkFocusEscape(event));\n\n // Update last focused element\n lastFocusedSelector = event.target.selector;\n break;\n }\n\n case 'ANNOUNCEMENT': {\n // Track timestamp for rapid announcement detection\n announcementTimestamps.push(event.timestamp);\n\n // Resolve pending keyboard responses (announcement is an accessibility response)\n for (const pending of pendingKeyboardResponses) {\n if (!pending.resolved) {\n pending.resolved = true;\n }\n }\n\n // Check for rapid announcements\n warnings.push(...checkRapidAnnouncements(event.timestamp));\n break;\n }\n\n case 'KEYBOARD_ACTION': {\n // Register pending keyboard response check\n pendingKeyboardResponses.push({\n event,\n timestamp: event.timestamp,\n resolved: false,\n });\n break;\n }\n\n case 'DOM_MUTATION': {\n // Check if the focused element was removed\n warnings.push(...checkFocusedElementRemoved(event));\n\n // DOM mutation is an accessibility response to keyboard action\n for (const pending of pendingKeyboardResponses) {\n if (!pending.resolved) {\n pending.resolved = true;\n }\n }\n break;\n }\n\n case 'STATE_CHANGED':\n case 'ROLE_CHANGED':\n case 'ACCESSIBLE_NAME_CHANGED': {\n // These are all accessibility responses to keyboard actions\n for (const pending of pendingKeyboardResponses) {\n if (!pending.resolved) {\n pending.resolved = true;\n }\n }\n break;\n }\n\n default:\n // WARNING, REGRESSION, and other event types don't trigger heuristics\n break;\n }\n\n // Clean up resolved pending checks to prevent unbounded memory growth\n cleanupResolvedChecks();\n\n return warnings;\n }\n\n // ---------------------------------------------------------------------------\n // Cleanup\n // ---------------------------------------------------------------------------\n\n function cleanupResolvedChecks(): void {\n // Remove resolved pending checks\n for (let i = pendingDialogFocusChecks.length - 1; i >= 0; i--) {\n if (pendingDialogFocusChecks[i].resolved) {\n pendingDialogFocusChecks.splice(i, 1);\n }\n }\n\n for (let i = pendingKeyboardResponses.length - 1; i >= 0; i--) {\n if (pendingKeyboardResponses[i].resolved) {\n pendingKeyboardResponses.splice(i, 1);\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Public Interface\n // ---------------------------------------------------------------------------\n\n return {\n process(event: AccessibilityEvent): AccessibilityEvent[] {\n return processEvent(event);\n },\n\n get openDialogs(): string[] {\n return trackedDialogs.map((d) => d.selector);\n },\n };\n}\n","/**\n * Single source of truth for the package version.\n *\n * The value is injected at build/test time via the `__SPEAKABLE_VERSION__`\n * define, which reads it from package.json:\n * - production bundles: defined in tsup.config.ts (all entries)\n * - the test suite: defined in vitest.config.ts\n *\n * This keeps runtime-reported versions (timeline metadata, baseline files, the\n * browser bundle) in lockstep with the published version, with no hardcoded\n * strings to drift. This module is browser-safe: it has no Node-only imports,\n * so it can be bundled into the browser/IIFE build.\n */\n\ndeclare const __SPEAKABLE_VERSION__: string | undefined;\n\n/** The resolved package version (e.g. \"1.7.0\"), or \"dev\" if the define is absent. */\nexport const SPEAKABLE_VERSION: string =\n typeof __SPEAKABLE_VERSION__ !== 'undefined' && __SPEAKABLE_VERSION__\n ? __SPEAKABLE_VERSION__\n : 'dev';\n","/**\n * Timeline Generator\n *\n * Orchestrates interaction sessions by coordinating the RuntimeAccessibilityEngine\n * with interaction execution and heuristic analysis. Produces complete\n * AccessibilityTimeline objects containing ordered events, warnings, and\n * session metadata.\n *\n * @module runtime/timeline-generator\n */\n\nimport type {\n AccessibilityEvent,\n AccessibilityTimeline,\n InteractionSequence,\n TimelineMetadata,\n} from './types';\nimport { createEngine, type RuntimeAccessibilityEngine } from './engine';\nimport { executeSequence } from './interactions';\nimport { createHeuristicAnalyzer, type HeuristicAnalyzer } from './heuristics';\nimport { SPEAKABLE_VERSION } from '../version.js';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\nconst TIMELINE_FORMAT_VERSION = '1.0';\nconst DEFAULT_SETTLE_PERIOD = 500;\nconst DEFAULT_LOAD_TIMEOUT = 10000;\nconst DOM_STABILITY_WAIT = 100;\n\n// ---------------------------------------------------------------------------\n// Options\n// ---------------------------------------------------------------------------\n\n/**\n * Configuration options for creating a TimelineGenerator.\n */\nexport interface TimelineGeneratorOptions {\n /** Document or iframe to attach to */\n document: Document;\n /** Component name for metadata */\n componentName: string;\n /** Story or variant name for metadata */\n storyName?: string;\n /** Settle period after last action (default: 500ms) */\n settlePeriod?: number;\n /** Maximum wait for document load (default: 10000ms) */\n loadTimeout?: number;\n /** Enable heuristic warnings (default: true) */\n heuristics?: boolean;\n}\n\n// ---------------------------------------------------------------------------\n// Timeline Generator Interface\n// ---------------------------------------------------------------------------\n\n/**\n * Orchestrates an interaction session and produces an AccessibilityTimeline.\n */\nexport interface TimelineGenerator {\n /** Execute an interaction sequence and produce a timeline */\n capture(sequence: InteractionSequence): Promise<AccessibilityTimeline>;\n /** Abort an in-progress capture */\n abort(): void;\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\n/**\n * Creates a TimelineGenerator that coordinates the engine, interaction\n * execution, and heuristic analysis to produce accessibility timelines.\n *\n * Usage:\n * ```ts\n * const generator = createTimelineGenerator({\n * document: myDocument,\n * componentName: 'LoginForm',\n * storyName: 'Default',\n * });\n *\n * const timeline = await generator.capture({\n * description: 'Tab through form fields',\n * actions: [{ type: 'tab' }, { type: 'tab' }, { type: 'enter' }],\n * });\n * ```\n */\nexport function createTimelineGenerator(\n options: TimelineGeneratorOptions\n): TimelineGenerator {\n const {\n document: doc,\n componentName,\n storyName,\n settlePeriod = DEFAULT_SETTLE_PERIOD,\n loadTimeout = DEFAULT_LOAD_TIMEOUT,\n heuristics: enableHeuristics = true,\n } = options;\n\n let aborted = false;\n let currentEngine: RuntimeAccessibilityEngine | null = null;\n\n return {\n async capture(sequence: InteractionSequence): Promise<AccessibilityTimeline> {\n aborted = false;\n\n // Wait for document to be ready (body must exist)\n await waitForDocumentReady(doc, loadTimeout);\n\n if (aborted) {\n return buildAbortedTimeline(componentName, storyName, sequence);\n }\n\n // Create engine and attach\n const engine = createEngine({ document: doc });\n currentEngine = engine;\n\n // Create heuristic analyzer if enabled\n const heuristicAnalyzer: HeuristicAnalyzer | null = enableHeuristics\n ? createHeuristicAnalyzer()\n : null;\n\n // Collect interaction-emitted events (KEYBOARD_ACTION, WARNINGs from missing elements)\n // These are not captured by the engine's observers.\n const interactionEvents: AccessibilityEvent[] = [];\n\n const sessionStart = Date.now();\n engine.attach();\n\n if (aborted) {\n engine.detach();\n currentEngine = null;\n return buildAbortedTimeline(componentName, storyName, sequence);\n }\n\n // Timestamp function for interactions\n function getTimestamp(): number {\n return Date.now() - sessionStart;\n }\n\n // Execute the interaction sequence with DOM stability waits\n await executeSequence(\n sequence,\n doc,\n (event: AccessibilityEvent) => {\n interactionEvents.push(event);\n },\n getTimestamp,\n DOM_STABILITY_WAIT\n );\n\n if (aborted) {\n engine.detach();\n currentEngine = null;\n return buildAbortedTimeline(componentName, storyName, sequence);\n }\n\n // Wait the settle period for trailing async events\n await delay(settlePeriod);\n\n // Detach engine and finalize\n engine.detach();\n currentEngine = null;\n\n const duration = Date.now() - sessionStart;\n\n // Merge engine events with interaction events, sorted by timestamp\n const engineEvents = engine.getEvents();\n const allEvents = mergeEvents(engineEvents, interactionEvents);\n\n // Run heuristic analysis on all events if enabled\n if (heuristicAnalyzer) {\n const heuristicWarnings: AccessibilityEvent[] = [];\n for (const event of allEvents) {\n const warnings = heuristicAnalyzer.process(event);\n heuristicWarnings.push(...warnings);\n }\n // Add heuristic warnings to the event stream\n for (const warning of heuristicWarnings) {\n allEvents.push(warning);\n }\n // Re-sort after adding heuristic warnings\n allEvents.sort((a, b) => a.timestamp - b.timestamp);\n }\n\n // Extract all WARNING events for the warnings array\n const allWarnings = allEvents.filter((e) => e.type === 'WARNING');\n\n // Build metadata\n const metadata: TimelineMetadata = {\n capturedAt: new Date().toISOString(),\n speakableVersion: SPEAKABLE_VERSION,\n sourceUrl: getSourceUrl(doc),\n userAgent: getUserAgent(),\n };\n\n // Build and return the AccessibilityTimeline\n const timeline: AccessibilityTimeline = {\n version: TIMELINE_FORMAT_VERSION,\n component: componentName,\n story: storyName || null,\n interactionSequence: sequence.description,\n duration,\n events: allEvents,\n warnings: allWarnings,\n metadata,\n };\n\n return timeline;\n },\n\n abort(): void {\n aborted = true;\n if (currentEngine && currentEngine.isAttached) {\n currentEngine.detach();\n currentEngine = null;\n }\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Wait for the document body to be available, with a timeout.\n * If the document already has a body, resolves immediately.\n */\nasync function waitForDocumentReady(\n doc: Document,\n timeout: number\n): Promise<void> {\n if (doc.body) return;\n\n return new Promise<void>((resolve, reject) => {\n const timeoutId = setTimeout(() => {\n reject(\n new Error(\n `Document load timeout (${timeout}ms): ${getSourceUrl(doc)}`\n )\n );\n }, timeout);\n\n // Poll for body availability\n const interval = setInterval(() => {\n if (doc.body) {\n clearTimeout(timeoutId);\n clearInterval(interval);\n resolve();\n }\n }, 50);\n });\n}\n\n/**\n * Merge two event arrays into a single sorted array by timestamp.\n */\nfunction mergeEvents(\n engineEvents: AccessibilityEvent[],\n interactionEvents: AccessibilityEvent[]\n): AccessibilityEvent[] {\n const all = [...engineEvents, ...interactionEvents];\n all.sort((a, b) => a.timestamp - b.timestamp);\n return all;\n}\n\n/**\n * Get the source URL from a document, falling back to 'local'.\n */\nfunction getSourceUrl(doc: Document): string {\n try {\n const url = doc.URL;\n if (url && url !== 'about:blank' && url !== '') {\n return url;\n }\n } catch {\n // Ignore errors accessing URL\n }\n return 'local';\n}\n\n/**\n * Get the user agent string, defaulting to 'jsdom' for Node.js environments.\n */\nfunction getUserAgent(): string {\n try {\n if (typeof navigator !== 'undefined' && navigator.userAgent) {\n return navigator.userAgent;\n }\n } catch {\n // Ignore errors\n }\n return 'jsdom';\n}\n\n/**\n * Simple promise-based delay.\n */\nfunction delay(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\n/**\n * Build an empty timeline for aborted captures.\n */\nfunction buildAbortedTimeline(\n componentName: string,\n storyName: string | undefined,\n sequence: InteractionSequence\n): AccessibilityTimeline {\n return {\n version: TIMELINE_FORMAT_VERSION,\n component: componentName,\n story: storyName || null,\n interactionSequence: sequence.description,\n duration: 0,\n events: [],\n warnings: [],\n metadata: {\n capturedAt: new Date().toISOString(),\n speakableVersion: SPEAKABLE_VERSION,\n sourceUrl: 'local',\n userAgent: getUserAgent(),\n },\n };\n}\n","/**\n * Transport-agnostic interaction timeline capture.\n *\n * Wraps the core runtime engine (`src/runtime`) so any real-browser surface\n * (Storybook addon, iframe harness, extension) can run an interaction\n * sequence against a live document and receive a serializable timeline.\n */\n\nimport { createTimelineGenerator } from '../runtime/timeline-generator.js';\nimport type { AccessibilityTimeline, InteractionSequence } from '../runtime/types.js';\nimport { awaitCustomElementsReady } from './upgrade.js';\n\nexport interface CaptureOptions {\n /** Component name for timeline metadata. */\n componentName: string;\n /** Story or variant name for timeline metadata. */\n storyName?: string;\n /** Ordered interaction sequence to execute during capture. */\n sequence: InteractionSequence;\n /** Settle period after the last action (ms). */\n settlePeriod?: number;\n /** Await custom-element upgrade before capture (default: true). */\n awaitUpgrade?: boolean;\n /** Maximum time to wait for custom elements to upgrade (ms). */\n upgradeTimeoutMs?: number;\n}\n\n/**\n * Attach the runtime engine to `document`, run the interaction sequence,\n * and return a serializable accessibility timeline.\n *\n * When `awaitUpgrade` is enabled (default), waits for custom elements to\n * upgrade first so web components (e.g. Lit) are analyzed post-hydration.\n * Any upgrade warnings are appended to the timeline's `warnings` array.\n */\nexport async function captureTimeline(\n document: Document,\n options: CaptureOptions\n): Promise<AccessibilityTimeline> {\n const {\n componentName,\n storyName,\n sequence,\n settlePeriod,\n awaitUpgrade = true,\n upgradeTimeoutMs,\n } = options;\n\n let upgradeWarnings: string[] = [];\n if (awaitUpgrade) {\n const warnings = await awaitCustomElementsReady(document, upgradeTimeoutMs);\n upgradeWarnings = warnings.map(w => w.message);\n }\n\n const generator = createTimelineGenerator({\n document,\n componentName,\n storyName,\n ...(settlePeriod !== undefined && { settlePeriod }),\n });\n\n const timeline = await generator.capture(sequence);\n\n if (upgradeWarnings.length > 0) {\n // Fold upgrade warnings into the timeline as WARNING events at t=0.\n const upgradeEvents = upgradeWarnings.map(message => ({\n type: 'WARNING' as const,\n timestamp: 0,\n target: { role: 'generic', accessibleName: '', selector: ':root' },\n payload: { kind: 'warning' as const, message },\n }));\n return {\n ...timeline,\n events: [...upgradeEvents, ...timeline.events],\n warnings: [...upgradeEvents, ...timeline.warnings],\n };\n }\n\n return timeline;\n}\n"],"mappings":"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","names":["model","shouldAnnounceRoleFirst","awaitCustomElementsReady","computeAccessibleName","buildEventTarget","computeAccessibleName","getElementRole","buildEventTarget","buildEventTarget","buildEventTarget","computeAccessibleName","getElementRole"]}