@wdio/mcp 2.4.1 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/snapshot.js CHANGED
@@ -853,7 +853,7 @@ function isValidValue(value) {
853
853
  return value !== void 0 && value !== null && value !== "null" && value.trim() !== "";
854
854
  }
855
855
  function escapeText(text) {
856
- return text.replace(/"/g, '\\"').replace(/\n/g, "\\n");
856
+ return text.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n");
857
857
  }
858
858
  function escapeXPathValue(value) {
859
859
  if (!value.includes("'")) {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/scripts/get-interactable-browser-elements.ts","../src/scripts/get-browser-accessibility-tree.ts","../src/locators/constants.ts","../src/locators/xml-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/index.ts","../src/scripts/get-visible-mobile-elements.ts"],"sourcesContent":["/**\n * Browser element detection\n * Single browser.execute() call: querySelectorAll → flat interactable element list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface BrowserElementInfo {\n tagName: string;\n name: string; // computed accessible name (ARIA spec)\n type: string;\n value: string;\n href: string;\n selector: string;\n isInViewport: boolean;\n boundingBox?: { x: number; y: number; width: number; height: number };\n}\n\nexport interface GetBrowserElementsOptions {\n includeBounds?: boolean;\n}\n\nconst elementsScript = (includeBounds: boolean) => (function () {\n const interactableSelectors = [\n 'a[href]',\n 'button',\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"combobox\"]',\n '[role=\"option\"]',\n '[role=\"switch\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"searchbox\"]',\n '[role=\"spinbutton\"]',\n '[contenteditable=\"true\"]',\n '[tabindex]:not([tabindex=\"-1\"])',\n ].join(',');\n\n function isVisible(element: HTMLElement): boolean {\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(element);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n element.offsetWidth > 0 &&\n element.offsetHeight > 0;\n }\n\n function getAccessibleName(el: HTMLElement): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n // 2. aria-labelledby — resolve referenced elements\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n // 3. alt for images and input[type=image]\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n // 4. label[for=id] for form elements\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n // 5. Wrapping label — clone, strip inputs, read text\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n // 6. placeholder\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n // 7. title\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n // 8. text content (truncated, whitespace normalized)\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n // 1. tag*=Text — best per WebdriverIO docs\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => {\n if (el.textContent?.includes(text)) matchCount++;\n });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n // 2. aria/label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n // 3. data-testid\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 4. #id\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n // 5. [name] — form elements\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 6. tag.class — try each class individually, then first-two combination\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n // 7. CSS path fallback\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) {\n path.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n const elements: Record<string, unknown>[] = [];\n const seen = new Set<Element>();\n\n document.querySelectorAll(interactableSelectors).forEach((el) => {\n if (seen.has(el)) return;\n seen.add(el);\n\n const htmlEl = el as HTMLElement;\n if (!isVisible(htmlEl)) return;\n\n const inputEl = htmlEl as HTMLInputElement;\n const rect = htmlEl.getBoundingClientRect();\n const isInViewport = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n\n const entry: Record<string, unknown> = {\n tagName: htmlEl.tagName.toLowerCase(),\n name: getAccessibleName(htmlEl),\n type: htmlEl.getAttribute('type') || '',\n value: inputEl.value || '',\n href: htmlEl.getAttribute('href') || '',\n selector: getSelector(htmlEl),\n isInViewport,\n };\n\n if (includeBounds) {\n entry.boundingBox = {\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n };\n }\n\n elements.push(entry);\n });\n\n return elements;\n})();\n\n/**\n * Get interactable browser elements via querySelectorAll.\n */\nexport async function getInteractableBrowserElements(\n browser: WebdriverIO.Browser,\n options: GetBrowserElementsOptions = {},\n): Promise<BrowserElementInfo[]> {\n const { includeBounds = false } = options;\n return (browser as any).execute(elementsScript, includeBounds) as unknown as Promise<BrowserElementInfo[]>;\n}\n\nexport default elementsScript;\n","/**\n * Browser accessibility tree\n * Single browser.execute() call: DOM walk → flat accessibility node list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface AccessibilityNode {\n role: string;\n name: string;\n selector: string;\n level: number | string;\n disabled: string;\n checked: string;\n expanded: string;\n selected: string;\n pressed: string;\n required: string;\n readonly: string;\n}\n\nconst accessibilityTreeScript = () => (function () {\n\n const INPUT_TYPE_ROLES: Record<string, string> = {\n text: 'textbox', search: 'searchbox', email: 'textbox', url: 'textbox',\n tel: 'textbox', password: 'textbox', number: 'spinbutton',\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n submit: 'button', reset: 'button', image: 'button', file: 'button', color: 'button',\n };\n\n const LANDMARK_ROLES = new Set([\n 'navigation', 'main', 'banner', 'contentinfo', 'complementary', 'form', 'dialog', 'region',\n ]);\n\n // Container roles: named only via aria-label/aria-labelledby, not textContent\n const CONTAINER_ROLES = new Set([\n 'navigation', 'banner', 'contentinfo', 'complementary', 'main', 'form',\n 'region', 'group', 'list', 'listitem', 'table', 'row', 'rowgroup', 'generic',\n ]);\n\n function getRole(el: HTMLElement): string | null {\n const explicit = el.getAttribute('role');\n if (explicit) return explicit.split(' ')[0];\n\n const tag = el.tagName.toLowerCase();\n\n switch (tag) {\n case 'button': return 'button';\n case 'a': return el.hasAttribute('href') ? 'link' : null;\n case 'input': {\n const type = (el.getAttribute('type') || 'text').toLowerCase();\n if (type === 'hidden') return null;\n return INPUT_TYPE_ROLES[type] || 'textbox';\n }\n case 'select': return 'combobox';\n case 'textarea': return 'textbox';\n case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': return 'heading';\n case 'img': return 'img';\n case 'nav': return 'navigation';\n case 'main': return 'main';\n case 'header': return !el.closest('article,aside,main,nav,section') ? 'banner' : null;\n case 'footer': return !el.closest('article,aside,main,nav,section') ? 'contentinfo' : null;\n case 'aside': return 'complementary';\n case 'dialog': return 'dialog';\n case 'form': return 'form';\n case 'section': return (el.hasAttribute('aria-label') || el.hasAttribute('aria-labelledby')) ? 'region' : null;\n case 'summary': return 'button';\n case 'details': return 'group';\n case 'progress': return 'progressbar';\n case 'meter': return 'meter';\n case 'ul': case 'ol': return 'list';\n case 'li': return 'listitem';\n case 'table': return 'table';\n }\n\n if ((el as HTMLElement & { contentEditable: string }).contentEditable === 'true') return 'textbox';\n if (el.hasAttribute('tabindex') && parseInt(el.getAttribute('tabindex') || '-1', 10) >= 0) return 'generic';\n\n return null;\n }\n\n function getAccessibleName(el: HTMLElement, role: string | null): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n if (role && CONTAINER_ROLES.has(role)) return '';\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => { if (el.textContent?.includes(text)) matchCount++; });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) { path.unshift(`#${CSS.escape(current.id)}`); break; }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n function isVisible(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === 'function') {\n return el.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(el);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n el.offsetWidth > 0 &&\n el.offsetHeight > 0;\n }\n\n function getLevel(el: HTMLElement): number | undefined {\n const m = el.tagName.toLowerCase().match(/^h([1-6])$/);\n if (m) return parseInt(m[1], 10);\n const ariaLevel = el.getAttribute('aria-level');\n if (ariaLevel) return parseInt(ariaLevel, 10);\n return undefined;\n }\n\n function getState(el: HTMLElement): Record<string, string> {\n const inputEl = el as HTMLInputElement;\n const isCheckable = ['input', 'menuitemcheckbox', 'menuitemradio'].includes(el.tagName.toLowerCase()) ||\n ['checkbox', 'radio', 'switch'].includes(el.getAttribute('role') || '');\n return {\n disabled: (el.getAttribute('aria-disabled') === 'true' || inputEl.disabled) ? 'true' : '',\n checked: (isCheckable && inputEl.checked) ? 'true' : el.getAttribute('aria-checked') || '',\n expanded: el.getAttribute('aria-expanded') || '',\n selected: el.getAttribute('aria-selected') || '',\n pressed: el.getAttribute('aria-pressed') || '',\n required: (inputEl.required || el.getAttribute('aria-required') === 'true') ? 'true' : '',\n readonly: (inputEl.readOnly || el.getAttribute('aria-readonly') === 'true') ? 'true' : '',\n };\n }\n\n type RawNode = Record<string, unknown>;\n\n const result: RawNode[] = [];\n\n function walk(el: HTMLElement, depth = 0): void {\n if (depth > 200) return;\n if (!isVisible(el)) return;\n\n const role = getRole(el);\n\n if (!role) {\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n return;\n }\n\n const name = getAccessibleName(el, role);\n const isLandmark = LANDMARK_ROLES.has(role);\n const hasIdentity = !!(name || isLandmark);\n const selector = hasIdentity ? getSelector(el) : '';\n const node: RawNode = { role, name, selector, level: getLevel(el) ?? '', ...getState(el) };\n result.push(node);\n\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n }\n\n for (const child of Array.from(document.body.children)) {\n walk(child as HTMLElement, 0);\n }\n\n return result;\n})();\n\n/**\n * Get browser accessibility tree via a single DOM walk.\n */\nexport async function getBrowserAccessibilityTree(\n browser: WebdriverIO.Browser,\n): Promise<AccessibilityNode[]> {\n return (browser as any).execute(accessibilityTreeScript) as unknown as Promise<AccessibilityNode[]>;\n}\n","/**\n * Platform-specific element tag constants for mobile automation\n */\n\nexport const ANDROID_INTERACTABLE_TAGS = [\n // Input elements\n 'android.widget.EditText',\n 'android.widget.AutoCompleteTextView',\n 'android.widget.MultiAutoCompleteTextView',\n 'android.widget.SearchView',\n\n // Button-like elements\n 'android.widget.Button',\n 'android.widget.ImageButton',\n 'android.widget.ToggleButton',\n 'android.widget.CompoundButton',\n 'android.widget.RadioButton',\n 'android.widget.CheckBox',\n 'android.widget.Switch',\n 'android.widget.FloatingActionButton',\n 'com.google.android.material.button.MaterialButton',\n 'com.google.android.material.floatingactionbutton.FloatingActionButton',\n\n // Text elements (often tappable)\n 'android.widget.TextView',\n 'android.widget.CheckedTextView',\n\n // Image elements (often tappable)\n 'android.widget.ImageView',\n 'android.widget.QuickContactBadge',\n\n // Selection elements\n 'android.widget.Spinner',\n 'android.widget.SeekBar',\n 'android.widget.RatingBar',\n 'android.widget.ProgressBar',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.NumberPicker',\n\n // List/grid items\n 'android.widget.AdapterView',\n];\n\nexport const ANDROID_LAYOUT_CONTAINERS = [\n // Core ViewGroup classes\n 'android.view.ViewGroup',\n 'android.view.View',\n 'android.widget.FrameLayout',\n 'android.widget.LinearLayout',\n 'android.widget.RelativeLayout',\n 'android.widget.GridLayout',\n 'android.widget.TableLayout',\n 'android.widget.TableRow',\n 'android.widget.AbsoluteLayout',\n\n // AndroidX layout classes\n 'androidx.constraintlayout.widget.ConstraintLayout',\n 'androidx.coordinatorlayout.widget.CoordinatorLayout',\n 'androidx.appcompat.widget.LinearLayoutCompat',\n 'androidx.cardview.widget.CardView',\n 'androidx.appcompat.widget.ContentFrameLayout',\n 'androidx.appcompat.widget.FitWindowsFrameLayout',\n\n // Scrolling containers\n 'android.widget.ScrollView',\n 'android.widget.HorizontalScrollView',\n 'android.widget.NestedScrollView',\n 'androidx.core.widget.NestedScrollView',\n 'androidx.recyclerview.widget.RecyclerView',\n 'android.widget.ListView',\n 'android.widget.GridView',\n 'android.widget.AbsListView',\n\n // App chrome / system elements\n 'android.widget.ActionBarContainer',\n 'android.widget.ActionBarOverlayLayout',\n 'android.view.ViewStub',\n 'androidx.appcompat.widget.ActionBarContainer',\n 'androidx.appcompat.widget.ActionBarContextView',\n 'androidx.appcompat.widget.ActionBarOverlayLayout',\n\n // Decor views\n 'com.android.internal.policy.DecorView',\n 'android.widget.DecorView',\n];\n\nexport const IOS_INTERACTABLE_TAGS = [\n // Input elements\n 'XCUIElementTypeTextField',\n 'XCUIElementTypeSecureTextField',\n 'XCUIElementTypeTextView',\n 'XCUIElementTypeSearchField',\n\n // Button-like elements\n 'XCUIElementTypeButton',\n 'XCUIElementTypeLink',\n\n // Text elements (often tappable)\n 'XCUIElementTypeStaticText',\n\n // Image elements\n 'XCUIElementTypeImage',\n 'XCUIElementTypeIcon',\n\n // Selection elements\n 'XCUIElementTypeSwitch',\n 'XCUIElementTypeSlider',\n 'XCUIElementTypeStepper',\n 'XCUIElementTypeSegmentedControl',\n 'XCUIElementTypePicker',\n 'XCUIElementTypePickerWheel',\n 'XCUIElementTypeDatePicker',\n 'XCUIElementTypePageIndicator',\n\n // Table/list items\n 'XCUIElementTypeCell',\n 'XCUIElementTypeMenuItem',\n 'XCUIElementTypeMenuBarItem',\n\n // Toggle elements\n 'XCUIElementTypeCheckBox',\n 'XCUIElementTypeRadioButton',\n 'XCUIElementTypeToggle',\n\n // Other interactive\n 'XCUIElementTypeKey',\n 'XCUIElementTypeKeyboard',\n 'XCUIElementTypeAlert',\n 'XCUIElementTypeSheet',\n];\n\nexport const IOS_LAYOUT_CONTAINERS = [\n // Generic containers\n 'XCUIElementTypeOther',\n 'XCUIElementTypeGroup',\n 'XCUIElementTypeLayoutItem',\n\n // Scroll containers\n 'XCUIElementTypeScrollView',\n 'XCUIElementTypeTable',\n 'XCUIElementTypeCollectionView',\n 'XCUIElementTypeScrollBar',\n\n // Navigation chrome\n 'XCUIElementTypeNavigationBar',\n 'XCUIElementTypeTabBar',\n 'XCUIElementTypeToolbar',\n 'XCUIElementTypeStatusBar',\n 'XCUIElementTypeMenuBar',\n\n // Windows and views\n 'XCUIElementTypeWindow',\n 'XCUIElementTypeSheet',\n 'XCUIElementTypeDrawer',\n 'XCUIElementTypeDialog',\n 'XCUIElementTypePopover',\n 'XCUIElementTypePopUpButton',\n\n // Outline elements\n 'XCUIElementTypeOutline',\n 'XCUIElementTypeOutlineRow',\n 'XCUIElementTypeBrowser',\n 'XCUIElementTypeSplitGroup',\n 'XCUIElementTypeSplitter',\n\n // Application root\n 'XCUIElementTypeApplication',\n];\n","/**\n * XML parsing utilities for mobile element source\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport xpath from 'xpath';\nimport type { ElementAttributes, JSONElement, Bounds, UniquenessResult } from './types';\n\n/**\n * Get child nodes that are elements (not text nodes, comments, etc.)\n */\nfunction childNodesOf(node: Node): Node[] {\n const children: Node[] = [];\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n return children;\n}\n\n/**\n * Recursively translate DOM node to JSONElement\n */\nfunction translateRecursively(\n domNode: Node,\n parentPath: string = '',\n index: number | null = null,\n): JSONElement {\n const attributes: ElementAttributes = {};\n\n const element = domNode as Element;\n if (element.attributes) {\n for (let attrIdx = 0; attrIdx < element.attributes.length; attrIdx++) {\n const attr = element.attributes.item(attrIdx);\n if (attr) {\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n const path = index === null ? '' : `${parentPath ? parentPath + '.' : ''}${index}`;\n\n return {\n children: childNodesOf(domNode).map((childNode, childIndex) =>\n translateRecursively(childNode, path, childIndex),\n ),\n tagName: domNode.nodeName,\n attributes,\n path,\n };\n}\n\n/**\n * Compare two nodes for equality by platform-specific attributes\n * (reference equality via === may fail when nodes come from different traversals)\n */\nfunction isSameElement(node1: Node, node2: Node): boolean {\n if (node1.nodeType !== 1 || node2.nodeType !== 1) return false;\n const el1 = node1 as Element;\n const el2 = node2 as Element;\n\n if (el1.nodeName !== el2.nodeName) return false;\n\n // For Android, compare by bounds (unique per element)\n const bounds1 = el1.getAttribute('bounds');\n const bounds2 = el2.getAttribute('bounds');\n if (bounds1 && bounds2) {\n return bounds1 === bounds2;\n }\n\n // For iOS, compare by x, y, width, height\n const x1 = el1.getAttribute('x');\n const y1 = el1.getAttribute('y');\n const x2 = el2.getAttribute('x');\n const y2 = el2.getAttribute('y');\n if (x1 && y1 && x2 && y2) {\n return (\n x1 === x2 &&\n y1 === y2 &&\n el1.getAttribute('width') === el2.getAttribute('width') &&\n el1.getAttribute('height') === el2.getAttribute('height')\n );\n }\n\n return false;\n}\n\n/**\n * Convert XML page source to JSON tree structure\n */\nexport function xmlToJSON(sourceXML: string): JSONElement | null {\n try {\n const parser = new DOMParser();\n const sourceDoc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = sourceDoc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToJSON] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n const children = childNodesOf(sourceDoc);\n const firstChild =\n children[0] ||\n (sourceDoc.documentElement ? childNodesOf(sourceDoc.documentElement)[0] : null);\n\n return firstChild\n ? translateRecursively(firstChild)\n : { children: [], tagName: '', attributes: {}, path: '' };\n } catch (e) {\n console.error('[xmlToJSON] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Parse XML source to DOM Document for XPath evaluation\n */\nexport function xmlToDOM(sourceXML: string): Document | null {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = doc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToDOM] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n return doc;\n } catch (e) {\n console.error('[xmlToDOM] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Execute XPath query on DOM document\n */\nexport function evaluateXPath(doc: Document, xpathExpr: string): Node[] {\n try {\n const nodes = xpath.select(xpathExpr, doc);\n if (Array.isArray(nodes)) {\n return nodes as Node[];\n }\n return [];\n } catch (e) {\n console.error(`[evaluateXPath] Failed to evaluate \"${xpathExpr}\":`, e);\n return [];\n }\n}\n\n/**\n * Check if an XPath selector is unique and get index if not\n */\nexport function checkXPathUniqueness(\n doc: Document,\n xpathExpr: string,\n targetNode?: Node,\n): UniquenessResult {\n try {\n const nodes = evaluateXPath(doc, xpathExpr);\n const totalMatches = nodes.length;\n\n if (totalMatches === 0) {\n return { isUnique: false };\n }\n\n if (totalMatches === 1) {\n return { isUnique: true };\n }\n\n // Not unique - find index of target node if provided\n if (targetNode) {\n for (let i = 0; i < nodes.length; i++) {\n if (nodes[i] === targetNode || isSameElement(nodes[i], targetNode)) {\n return {\n isUnique: false,\n index: i + 1, // 1-based index for XPath\n totalMatches,\n };\n }\n }\n }\n\n return { isUnique: false, totalMatches };\n } catch (e) {\n console.error(`[checkXPathUniqueness] Error checking \"${xpathExpr}\":`, e);\n return { isUnique: false };\n }\n}\n\n/**\n * Find DOM node by JSONElement path (e.g., \"0.2.1\")\n */\nexport function findDOMNodeByPath(doc: Document, path: string): Node | null {\n if (!path) return doc.documentElement;\n\n const indices = path.split('.').map(Number);\n let current: Node | null = doc.documentElement;\n\n for (const index of indices) {\n if (!current) return null;\n\n const children: Node[] = [];\n if (current.childNodes) {\n for (let i = 0; i < current.childNodes.length; i++) {\n const child = current.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n\n current = children[index] || null;\n }\n\n return current;\n}\n\n/**\n * Parse Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n */\nexport function parseAndroidBounds(bounds: string): Bounds {\n const match = bounds.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n const x1 = parseInt(match[1], 10);\n const y1 = parseInt(match[2], 10);\n const x2 = parseInt(match[3], 10);\n const y2 = parseInt(match[4], 10);\n\n return {\n x: x1,\n y: y1,\n width: x2 - x1,\n height: y2 - y1,\n };\n}\n\n/**\n * Parse iOS element bounds from individual x, y, width, height attributes\n */\nexport function parseIOSBounds(attributes: ElementAttributes): Bounds {\n return {\n x: parseInt(attributes.x || '0', 10),\n y: parseInt(attributes.y || '0', 10),\n width: parseInt(attributes.width || '0', 10),\n height: parseInt(attributes.height || '0', 10),\n };\n}\n\n/**\n * Flatten JSON element tree to array (depth-first)\n */\nexport function flattenElementTree(root: JSONElement): JSONElement[] {\n const result: JSONElement[] = [];\n\n function traverse(element: JSONElement) {\n result.push(element);\n for (const child of element.children) {\n traverse(child);\n }\n }\n\n traverse(root);\n return result;\n}\n\n/**\n * Count occurrences of an attribute value in the source XML\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`${attribute}=[\"']${escapedValue}[\"']`, 'g');\n const matches = sourceXML.match(pattern);\n return matches ? matches.length : 0;\n}\n\n/**\n * Check if an attribute value is unique in the source (fast regex-based check)\n */\nexport function isAttributeUnique(\n sourceXML: string,\n attribute: string,\n value: string,\n): boolean {\n return countAttributeOccurrences(sourceXML, attribute, value) === 1;\n}\n","/**\n * Element filtering logic for mobile automation\n */\n\nimport type { JSONElement, FilterOptions } from './types';\nimport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n if (tagList.includes(tagName)) {\n return true;\n }\n\n for (const tag of tagList) {\n if (tagName.endsWith(tag) || tagName.includes(tag)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element matches tag name filters\n */\nfunction matchesTagFilters(\n element: JSONElement,\n includeTagNames: string[],\n excludeTagNames: string[],\n): boolean {\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n if (matchesTagList(element.tagName, excludeTagNames)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if element matches attribute-based filters\n */\nfunction matchesAttributeFilters(\n element: JSONElement,\n requireAttributes: string[],\n minAttributeCount: number,\n): boolean {\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n if (element.attributes && minAttributeCount > 0) {\n const attrCount = Object.values(element.attributes).filter(\n (v) => v !== undefined && v !== null && v !== '',\n ).length;\n if (attrCount < minAttributeCount) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if element is interactable based on platform\n */\nexport function isInteractableElement(\n element: JSONElement,\n isNative: boolean,\n automationName: string,\n): boolean {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n if (isAndroid) {\n if (\n element.attributes?.clickable === 'true' ||\n element.attributes?.focusable === 'true' ||\n element.attributes?.checkable === 'true' ||\n element.attributes?.['long-clickable'] === 'true'\n ) {\n return true;\n }\n }\n\n if (!isAndroid) {\n if (element.attributes?.accessible === 'true') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element is a layout container\n */\nexport function isLayoutContainer(element: JSONElement, platform: 'android' | 'ios'): boolean {\n const containerList = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n return matchesTagList(element.tagName, containerList);\n}\n\n/**\n * Check if element has meaningful content (text, accessibility info)\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n if (attrs.label && attrs.label.trim() !== '' && attrs.label !== 'null') {\n return true;\n }\n if (attrs.name && attrs.name.trim() !== '' && attrs.name !== 'null') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Determine if an element should be included based on all filter criteria\n */\nexport function shouldIncludeElement(\n element: JSONElement,\n filters: FilterOptions,\n isNative: boolean,\n automationName: string,\n): boolean {\n const {\n includeTagNames = [],\n excludeTagNames = ['hierarchy'],\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n if (visibleOnly) {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n if (isAndroid && element.attributes?.displayed === 'false') {\n return false;\n }\n if (!isAndroid && element.attributes?.visible === 'false') {\n return false;\n }\n }\n\n if (fetchableOnly && !isInteractableElement(element, isNative, automationName)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get default filter options for a platform\n */\nexport function getDefaultFilters(\n platform: 'android' | 'ios',\n includeContainers: boolean = false,\n): FilterOptions {\n const layoutContainers = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n\n return {\n excludeTagNames: includeContainers ? ['hierarchy'] : ['hierarchy', ...layoutContainers],\n fetchableOnly: !includeContainers,\n visibleOnly: true,\n clickableOnly: false,\n };\n}\n","/**\n * Locator strategy generation for mobile elements\n */\n\nimport type { JSONElement, LocatorStrategy, LocatorContext, UniquenessResult } from './types';\nimport { checkXPathUniqueness, evaluateXPath, isAttributeUnique } from './xml-parsing';\n\n/**\n * Check if a string value is valid for use in a locator\n */\nfunction isValidValue(value: string | undefined): value is string {\n return value !== undefined && value !== null && value !== 'null' && value.trim() !== '';\n}\n\n/**\n * Escape special characters in text for use in selectors\n */\nfunction escapeText(text: string): string {\n return text.replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Escape value for use in XPath expressions\n */\nfunction escapeXPathValue(value: string): string {\n if (!value.includes(\"'\")) {\n return `'${value}'`;\n }\n if (!value.includes('\"')) {\n return `\"${value}\"`;\n }\n const parts: string[] = [];\n let current = '';\n for (const char of value) {\n if (char === \"'\") {\n if (current) parts.push(`'${current}'`);\n parts.push('\"\\'\"');\n current = '';\n } else {\n current += char;\n }\n }\n if (current) parts.push(`'${current}'`);\n return `concat(${parts.join(',')})`;\n}\n\n/**\n * Wrap non-unique XPath with index\n */\nfunction generateIndexedXPath(baseXPath: string, index: number): string {\n return `(${baseXPath})[${index}]`;\n}\n\n/**\n * Add .instance(n) for UiAutomator (0-based)\n */\nfunction generateIndexedUiAutomator(baseSelector: string, index: number): string {\n return `${baseSelector}.instance(${index - 1})`;\n}\n\n/**\n * Check uniqueness, falling back to regex if no DOM available\n */\nfunction checkUniqueness(\n ctx: LocatorContext,\n xpath: string,\n targetNode?: Node,\n): UniquenessResult {\n if (ctx.parsedDOM) {\n return checkXPathUniqueness(ctx.parsedDOM, xpath, targetNode);\n }\n\n const match = xpath.match(/\\/\\/\\*\\[@([^=]+)=\"([^\"]+)\"\\]/);\n if (match) {\n const [, attr, value] = match;\n return { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n }\n return { isUnique: false };\n}\n\n/**\n * Get sibling index (1-based) among same-tag siblings\n */\nfunction getSiblingIndex(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let index = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n index++;\n if (child === element) return index;\n }\n }\n\n return 1;\n}\n\n/**\n * Count siblings with same tag name\n */\nfunction countSiblings(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let count = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n count++;\n }\n }\n\n return count;\n}\n\n/**\n * Find unique attribute for element in XPath format\n */\nfunction findUniqueAttribute(element: Element, ctx: LocatorContext): string | null {\n const attrs = ctx.isAndroid\n ? ['resource-id', 'content-desc', 'text']\n : ['name', 'label', 'value'];\n\n for (const attr of attrs) {\n const value = element.getAttribute(attr);\n if (value && value.trim()) {\n const xpath = `//*[@${attr}=${escapeXPathValue(value)}]`;\n const result = ctx.parsedDOM\n ? checkXPathUniqueness(ctx.parsedDOM, xpath)\n : { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n\n if (result.isUnique) {\n return `@${attr}=${escapeXPathValue(value)}`;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build hierarchical XPath by traversing up the DOM tree\n */\nfunction buildHierarchicalXPath(\n ctx: LocatorContext,\n element: Element,\n maxDepth: number = 3,\n): string | null {\n if (!ctx.parsedDOM) return null;\n\n const pathParts: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n const tagName = current.nodeName;\n const uniqueAttr = findUniqueAttribute(current, ctx);\n\n if (uniqueAttr) {\n pathParts.unshift(`//${tagName}[${uniqueAttr}]`);\n break;\n } else {\n const siblingIndex = getSiblingIndex(current);\n const siblingCount = countSiblings(current);\n\n if (siblingCount > 1) {\n pathParts.unshift(`${tagName}[${siblingIndex}]`);\n } else {\n pathParts.unshift(tagName);\n }\n }\n\n const parent = current.parentNode as Element | null;\n current = parent && parent.nodeType === 1 ? parent : null;\n depth++;\n }\n\n if (pathParts.length === 0) return null;\n\n let result = pathParts[0];\n for (let i = 1; i < pathParts.length; i++) {\n result += '/' + pathParts[i];\n }\n\n if (!result.startsWith('//')) {\n result = '//' + result;\n }\n\n return result;\n}\n\n/**\n * Add XPath locator with uniqueness checking and fallbacks\n */\nfunction addXPathLocator(\n results: [LocatorStrategy, string][],\n xpath: string,\n ctx: LocatorContext,\n targetNode?: Node,\n): void {\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n if (uniqueness.isUnique) {\n results.push(['xpath', xpath]);\n } else if (uniqueness.index) {\n results.push(['xpath', generateIndexedXPath(xpath, uniqueness.index)]);\n } else {\n if (targetNode && ctx.parsedDOM) {\n const hierarchical = buildHierarchicalXPath(ctx, targetNode as Element);\n if (hierarchical) {\n results.push(['xpath', hierarchical]);\n }\n }\n results.push(['xpath', xpath]);\n }\n}\n\n/**\n * Check if element is within UiAutomator scope\n */\nfunction isInUiAutomatorScope(element: JSONElement, doc: Document | null): boolean {\n if (!doc) return true;\n\n const hierarchyNodes = evaluateXPath(doc, '/hierarchy/*');\n if (hierarchyNodes.length === 0) return true;\n\n const lastIndex = hierarchyNodes.length;\n const pathParts = element.path.split('.');\n if (pathParts.length === 0 || pathParts[0] === '') return true;\n\n const firstIndex = parseInt(pathParts[0], 10);\n return firstIndex === lastIndex - 1;\n}\n\n/**\n * Build Android UiAutomator selector with multiple attributes\n */\nfunction buildUiAutomatorSelector(element: JSONElement): string | null {\n const attrs = element.attributes;\n const parts: string[] = [];\n\n if (isValidValue(attrs['resource-id'])) {\n parts.push(`resourceId(\"${attrs['resource-id']}\")`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n parts.push(`text(\"${escapeText(attrs.text!)}\")`);\n }\n if (isValidValue(attrs['content-desc'])) {\n parts.push(`description(\"${attrs['content-desc']}\")`);\n }\n if (isValidValue(attrs.class)) {\n parts.push(`className(\"${attrs.class}\")`);\n }\n\n if (parts.length === 0) return null;\n\n return `android=new UiSelector().${parts.join('.')}`;\n}\n\n/**\n * Build iOS predicate string with multiple conditions\n */\nfunction buildPredicateString(element: JSONElement): string | null {\n const attrs = element.attributes;\n const conditions: string[] = [];\n\n if (isValidValue(attrs.name)) {\n conditions.push(`name == \"${escapeText(attrs.name!)}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`label == \"${escapeText(attrs.label!)}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`value == \"${escapeText(attrs.value!)}\"`);\n }\n if (attrs.visible === 'true') {\n conditions.push('visible == 1');\n }\n if (attrs.enabled === 'true') {\n conditions.push('enabled == 1');\n }\n\n if (conditions.length === 0) return null;\n\n return `-ios predicate string:${conditions.join(' AND ')}`;\n}\n\n/**\n * Build iOS class chain selector\n */\nfunction buildClassChain(element: JSONElement): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n if (isValidValue(attrs.label)) {\n selector += `[\\`label == \"${escapeText(attrs.label!)}\"\\`]`;\n } else if (isValidValue(attrs.name)) {\n selector += `[\\`name == \"${escapeText(attrs.name!)}\"\\`]`;\n }\n\n return `-ios class chain:${selector}`;\n}\n\n/**\n * Build XPath for element with unique identification\n */\nfunction buildXPath(element: JSONElement, sourceXML: string, isAndroid: boolean): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n const conditions: string[] = [];\n\n if (isAndroid) {\n if (isValidValue(attrs['resource-id'])) {\n conditions.push(`@resource-id=\"${attrs['resource-id']}\"`);\n }\n if (isValidValue(attrs['content-desc'])) {\n conditions.push(`@content-desc=\"${attrs['content-desc']}\"`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n conditions.push(`@text=\"${escapeText(attrs.text!)}\"`);\n }\n } else {\n if (isValidValue(attrs.name)) {\n conditions.push(`@name=\"${attrs.name}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`@label=\"${attrs.label}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`@value=\"${attrs.value}\"`);\n }\n }\n\n if (conditions.length === 0) {\n return `//${tagName}`;\n }\n\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get simple locators based on single attributes\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n // Resource ID\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId)) {\n const xpath = `//*[@resource-id=\"${resourceId}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().resourceId(\"${resourceId}\")`;\n results.push(['id', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n\n // Content Description\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc)) {\n const xpath = `//*[@content-desc=\"${contentDesc}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n }\n\n // Text\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100) {\n const xpath = `//*[@text=\"${escapeText(text)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().text(\"${escapeText(text)}\")`;\n results.push(['text', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n } else {\n // iOS: Accessibility ID (name)\n const name = attrs.name;\n if (isValidValue(name)) {\n const xpath = `//*[@name=\"${name}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${name}`]);\n }\n }\n\n // iOS: Label\n const label = attrs.label;\n if (isValidValue(label) && label !== attrs.name) {\n const xpath = `//*[@label=\"${escapeText(label)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n }\n\n // iOS: Value\n const value = attrs.value;\n if (isValidValue(value)) {\n const xpath = `//*[@value=\"${escapeText(value)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n if (inUiAutomatorScope) {\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, true);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n if (inUiAutomatorScope && isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, false);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n const type = element.tagName;\n if (type.startsWith('XCUIElementType')) {\n results.push(['class-name', `-ios class chain:**/${type}`]);\n }\n }\n\n return results;\n}\n\n/**\n * Get all suggested locators for an element\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n ctx?: LocatorContext,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const locatorCtx = ctx ?? {\n sourceXML,\n parsedDOM: null,\n isAndroid: automationName.toLowerCase().includes('uiautomator'),\n };\n\n const simpleLocators = getSimpleSuggestedLocators(element, locatorCtx, automationName, targetNode);\n const complexLocators = getComplexSuggestedLocators(element, locatorCtx, automationName, targetNode);\n\n const seen = new Set<string>();\n const results: [LocatorStrategy, string][] = [];\n\n for (const locator of [...simpleLocators, ...complexLocators]) {\n if (!seen.has(locator[1])) {\n seen.add(locator[1]);\n results.push(locator);\n }\n }\n\n return results;\n}\n\n/**\n * Get the best (first priority) locator for an element\n */\nexport function getBestLocator(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, automationName);\n return locators.length > 0 ? locators[0][1] : null;\n}\n\n/**\n * Convert locator array to object format\n */\nexport function locatorsToObject(locators: [LocatorStrategy, string][]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [strategy, value] of locators) {\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Mobile element locator generation\n *\n * Main orchestrator module that coordinates XML parsing, element filtering,\n * and locator generation for mobile automation.\n *\n * Based on: https://github.com/appium/appium-mcp\n */\n\n// Types\nexport type {\n ElementAttributes,\n JSONElement,\n Bounds,\n FilterOptions,\n UniquenessResult,\n LocatorStrategy,\n LocatorContext,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\n// Constants\nexport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n// XML Parsing\nexport {\n xmlToJSON,\n xmlToDOM,\n evaluateXPath,\n checkXPathUniqueness,\n findDOMNodeByPath,\n parseAndroidBounds,\n parseIOSBounds,\n flattenElementTree,\n countAttributeOccurrences,\n isAttributeUnique,\n} from './xml-parsing';\n\n// Element Filtering\nexport {\n isInteractableElement,\n isLayoutContainer,\n hasMeaningfulContent,\n shouldIncludeElement,\n getDefaultFilters,\n} from './element-filter';\n\n// Locator Generation\nexport {\n getSuggestedLocators,\n getBestLocator,\n locatorsToObject,\n} from './locator-generation';\n\nimport type {\n JSONElement,\n FilterOptions,\n LocatorStrategy,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\nimport { xmlToJSON, xmlToDOM, parseAndroidBounds, parseIOSBounds, findDOMNodeByPath } from './xml-parsing';\nimport { shouldIncludeElement, isLayoutContainer, hasMeaningfulContent } from './element-filter';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\n\ninterface ProcessingContext {\n sourceXML: string;\n platform: 'android' | 'ios';\n automationName: string;\n isNative: boolean;\n viewportSize: { width: number; height: number };\n filters: FilterOptions;\n results: ElementWithLocators[];\n parsedDOM: Document | null;\n}\n\n/**\n * Parse element bounds based on platform\n */\nfunction parseBounds(\n element: JSONElement,\n platform: 'android' | 'ios',\n): { x: number; y: number; width: number; height: number } {\n return platform === 'android'\n ? parseAndroidBounds(element.attributes.bounds || '')\n : parseIOSBounds(element.attributes);\n}\n\n/**\n * Check if bounds are within viewport\n */\nfunction isWithinViewport(\n bounds: { x: number; y: number; width: number; height: number },\n viewport: { width: number; height: number },\n): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width > 0 &&\n bounds.height > 0 &&\n bounds.x + bounds.width <= viewport.width &&\n bounds.y + bounds.height <= viewport.height\n );\n}\n\n/**\n * Transform JSONElement to ElementWithLocators\n */\nfunction transformElement(\n element: JSONElement,\n locators: [LocatorStrategy, string][],\n ctx: ProcessingContext,\n): ElementWithLocators {\n const attrs = element.attributes;\n const bounds = parseBounds(element, ctx.platform);\n\n return {\n tagName: element.tagName,\n locators: locatorsToObject(locators),\n text: attrs.text || attrs.label || '',\n contentDesc: attrs['content-desc'] || '',\n resourceId: attrs['resource-id'] || '',\n accessibilityId: attrs.name || attrs['content-desc'] || '',\n label: attrs.label || '',\n value: attrs.value || '',\n className: attrs.class || element.tagName,\n clickable: attrs.clickable === 'true' || attrs.accessible === 'true' || attrs['long-clickable'] === 'true',\n enabled: attrs.enabled !== 'false',\n displayed: ctx.platform === 'android' ? attrs.displayed !== 'false' : attrs.visible !== 'false',\n bounds,\n isInViewport: isWithinViewport(bounds, ctx.viewportSize),\n };\n}\n\n/**\n * Check if element should be processed\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n return isLayoutContainer(element, ctx.platform) && hasMeaningfulContent(element, ctx.platform);\n}\n\n/**\n * Process a single element and add to results if valid\n */\nfunction processElement(element: JSONElement, ctx: ProcessingContext): void {\n if (!shouldProcess(element, ctx)) return;\n\n try {\n const targetNode = ctx.parsedDOM ? findDOMNodeByPath(ctx.parsedDOM, element.path) : undefined;\n\n const locators = getSuggestedLocators(\n element,\n ctx.sourceXML,\n ctx.automationName,\n { sourceXML: ctx.sourceXML, parsedDOM: ctx.parsedDOM, isAndroid: ctx.platform === 'android' },\n targetNode || undefined,\n );\n if (locators.length === 0) return;\n\n const transformed = transformElement(element, locators, ctx);\n if (Object.keys(transformed.locators).length === 0) return;\n\n ctx.results.push(transformed);\n } catch (error) {\n console.error(`[processElement] Error at path ${element.path}:`, error);\n }\n}\n\n/**\n * Recursively traverse and process element tree\n */\nfunction traverseTree(element: JSONElement | null, ctx: ProcessingContext): void {\n if (!element) return;\n\n processElement(element, ctx);\n\n for (const child of element.children || []) {\n traverseTree(child, ctx);\n }\n}\n\n/**\n * Generate locators for all elements from page source XML\n */\nexport function generateAllElementLocators(\n sourceXML: string,\n options: GenerateLocatorsOptions,\n): ElementWithLocators[] {\n const sourceJSON = xmlToJSON(sourceXML);\n\n if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\n\n const parsedDOM = xmlToDOM(sourceXML);\n\n const ctx: ProcessingContext = {\n sourceXML,\n platform: options.platform,\n automationName: options.platform === 'android' ? 'uiautomator2' : 'xcuitest',\n isNative: options.isNative ?? true,\n viewportSize: options.viewportSize ?? { width: 9999, height: 9999 },\n filters: options.filters ?? {},\n results: [],\n parsedDOM,\n };\n\n traverseTree(sourceJSON, ctx);\n\n return ctx.results;\n}\n","/**\n * Mobile element detection utilities for iOS and Android\n *\n * Uses page source parsing for optimal performance (2 HTTP calls vs 600+ for 50 elements)\n */\n\nimport type { ElementWithLocators, FilterOptions, LocatorStrategy } from '../locators';\nimport { generateAllElementLocators, getDefaultFilters } from '../locators';\n\n/**\n * Element info returned by getMobileVisibleElements\n * Uses uniform fields (all elements have same keys) to enable TOON tabular format\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n text: string;\n resourceId: string;\n accessibilityId: string;\n isEnabled: boolean;\n altSelector: string; // Single alternative selector (flattened for tabular format)\n // Only present when includeBounds=true\n bounds?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Options for getMobileVisibleElements\n */\nexport interface GetMobileElementsOptions {\n includeContainers?: boolean;\n includeBounds?: boolean;\n filterOptions?: FilterOptions;\n}\n\n/**\n * Locator strategy priority order for selecting best selector\n * Earlier = higher priority\n */\nconst LOCATOR_PRIORITY: LocatorStrategy[] = [\n 'accessibility-id', // Most stable, cross-platform\n 'id', // Android resource-id\n 'text', // Text-based (can be fragile but readable)\n 'predicate-string', // iOS predicate\n 'class-chain', // iOS class chain\n 'uiautomator', // Android UiAutomator compound\n 'xpath', // XPath (last resort, brittle)\n // 'class-name' intentionally excluded - too generic\n];\n\n/**\n * Select best locators from available strategies\n * Returns [primarySelector, ...alternativeSelectors]\n */\nfunction selectBestLocators(locators: Record<string, string>): string[] {\n const selected: string[] = [];\n\n // Find primary selector based on priority\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy]) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n // Add one alternative if available (different strategy)\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy] && !selected.includes(locators[strategy])) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n return selected;\n}\n\n/**\n * Convert ElementWithLocators to MobileElementInfo\n * Uses uniform fields (all elements have same keys) to enable CSV tabular format\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n\n // Build object with ALL fields for uniform schema (enables CSV tabular format)\n // Empty string '' used for missing values to keep schema consistent\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n text: element.text || '',\n resourceId: element.resourceId || '',\n accessibilityId: accessId || '',\n isEnabled: element.enabled !== false,\n altSelector: selectedLocators[1] || '', // Single alternative (flattened for tabular)\n };\n\n // Only include bounds if explicitly requested (adds 4 extra columns)\n if (includeBounds) {\n info.bounds = element.bounds;\n }\n\n return info;\n}\n\n/**\n * Get viewport size from browser\n */\nasync function getViewportSize(browser: WebdriverIO.Browser): Promise<{ width: number; height: number }> {\n try {\n const size = await browser.getWindowSize();\n return { width: size.width, height: size.height };\n } catch {\n return { width: 9999, height: 9999 };\n }\n}\n\n/**\n * Get all visible elements from a mobile app\n *\n * Performance: 2 HTTP calls (getWindowSize + getPageSource) vs 12+ per element with legacy approach\n */\nexport async function getMobileVisibleElements(\n browser: WebdriverIO.Browser,\n platform: 'ios' | 'android',\n options: GetMobileElementsOptions = {},\n): Promise<MobileElementInfo[]> {\n const { includeContainers = false, includeBounds = false, filterOptions } = options;\n\n const viewportSize = await getViewportSize(browser);\n const pageSource = await browser.getPageSource();\n\n const filters: FilterOptions = {\n ...getDefaultFilters(platform, includeContainers),\n ...filterOptions,\n };\n\n const elements = generateAllElementLocators(pageSource, {\n platform,\n viewportSize,\n filters,\n });\n\n return elements.map((el) => toMobileElementInfo(el, includeBounds));\n}\n"],"mappings":";AAuBA,IAAM,iBAAiB,CAAC,mBAA4B,WAAY;AAC9D,QAAM,wBAAwB;AAAA,IAC5B;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,EAAE,KAAK,GAAG;AAEV,WAAS,UAAU,SAA+B;AAChD,QAAI,OAAO,QAAQ,oBAAoB,YAAY;AACjD,aAAO,QAAQ,gBAAgB,EAAE,iBAAiB,MAAM,oBAAoB,MAAM,uBAAuB,KAAK,CAAC;AAAA,IACjH;AACA,UAAM,QAAQ,OAAO,iBAAiB,OAAO;AAC7C,WAAO,MAAM,YAAY,UACvB,MAAM,eAAe,YACrB,MAAM,YAAY,OAClB,QAAQ,cAAc,KACtB,QAAQ,eAAe;AAAA,EAC3B;AAEA,WAAS,kBAAkB,IAAyB;AAElD,UAAM,YAAY,GAAG,aAAa,YAAY;AAC9C,QAAI,UAAW,QAAO,UAAU,KAAK;AAGrC,UAAM,aAAa,GAAG,aAAa,iBAAiB;AACpD,QAAI,YAAY;AACd,YAAM,QAAQ,WAAW,MAAM,KAAK,EACjC,IAAI,QAAM,SAAS,eAAe,EAAE,GAAG,aAAa,KAAK,KAAK,EAAE,EAChE,OAAO,OAAO;AACjB,UAAI,MAAM,SAAS,EAAG,QAAO,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,GAAG;AAAA,IAC3D;AAEA,UAAM,MAAM,GAAG,QAAQ,YAAY;AAGnC,QAAI,QAAQ,SAAU,QAAQ,WAAW,GAAG,aAAa,MAAM,MAAM,SAAU;AAC7E,YAAM,MAAM,GAAG,aAAa,KAAK;AACjC,UAAI,QAAQ,KAAM,QAAO,IAAI,KAAK;AAAA,IACpC;AAGA,QAAI,CAAC,SAAS,UAAU,UAAU,EAAE,SAAS,GAAG,GAAG;AACjD,YAAM,KAAK,GAAG,aAAa,IAAI;AAC/B,UAAI,IAAI;AACN,cAAM,QAAQ,SAAS,cAAc,cAAc,IAAI,OAAO,EAAE,CAAC,IAAI;AACrE,YAAI,MAAO,QAAO,MAAM,aAAa,KAAK,KAAK;AAAA,MACjD;AAEA,YAAM,cAAc,GAAG,QAAQ,OAAO;AACtC,UAAI,aAAa;AACf,cAAM,QAAQ,YAAY,UAAU,IAAI;AACxC,cAAM,iBAAiB,uBAAuB,EAAE,QAAQ,OAAK,EAAE,OAAO,CAAC;AACvE,cAAM,KAAK,MAAM,aAAa,KAAK;AACnC,YAAI,GAAI,QAAO;AAAA,MACjB;AAAA,IACF;AAGA,UAAM,KAAK,GAAG,aAAa,aAAa;AACxC,QAAI,GAAI,QAAO,GAAG,KAAK;AAGvB,UAAM,QAAQ,GAAG,aAAa,OAAO;AACrC,QAAI,MAAO,QAAO,MAAM,KAAK;AAG7B,YAAQ,GAAG,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG,KAAK,IAAI,MAAM,GAAG,GAAG;AAAA,EACzE;AAEA,WAAS,YAAY,SAA8B;AACjD,UAAM,MAAM,QAAQ,QAAQ,YAAY;AAGxC,UAAM,OAAO,QAAQ,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAC5D,QAAI,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,IAAI;AAChD,YAAM,kBAAkB,SAAS,iBAAiB,GAAG;AACrD,UAAI,aAAa;AACjB,sBAAgB,QAAQ,QAAM;AAC5B,YAAI,GAAG,aAAa,SAAS,IAAI,EAAG;AAAA,MACtC,CAAC;AACD,UAAI,eAAe,EAAG,QAAO,GAAG,GAAG,KAAK,IAAI;AAAA,IAC9C;AAGA,UAAM,YAAY,QAAQ,aAAa,YAAY;AACnD,QAAI,aAAa,UAAU,UAAU,GAAI,QAAO,QAAQ,SAAS;AAGjE,UAAM,SAAS,QAAQ,aAAa,aAAa;AACjD,QAAI,QAAQ;AACV,YAAM,MAAM,iBAAiB,IAAI,OAAO,MAAM,CAAC;AAC/C,UAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,IAC1D;AAGA,QAAI,QAAQ,GAAI,QAAO,IAAI,IAAI,OAAO,QAAQ,EAAE,CAAC;AAGjD,UAAM,WAAW,QAAQ,aAAa,MAAM;AAC5C,QAAI,UAAU;AACZ,YAAM,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,QAAQ,CAAC;AAChD,UAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,IAC1D;AAGA,QAAI,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC9D,YAAM,UAAU,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACpE,iBAAW,OAAO,SAAS;AACzB,cAAM,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,GAAG,CAAC;AACrC,YAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,MAC1D;AACA,UAAI,QAAQ,UAAU,GAAG;AACvB,cAAM,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,IAAI,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAC/E,YAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,MAC1D;AAAA,IACF;AAGA,QAAI,UAA8B;AAClC,UAAM,OAAiB,CAAC;AACxB,WAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,UAAI,MAAM,QAAQ,QAAQ,YAAY;AACtC,UAAI,QAAQ,IAAI;AACd,aAAK,QAAQ,IAAI,IAAI,OAAO,QAAQ,EAAE,CAAC,EAAE;AACzC;AAAA,MACF;AACA,YAAM,SAAS,QAAQ;AACvB,UAAI,QAAQ;AACV,cAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE,OAAO,OAAK,EAAE,YAAY,QAAS,OAAO;AACvF,YAAI,SAAS,SAAS,EAAG,QAAO,gBAAgB,SAAS,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC/E;AACA,WAAK,QAAQ,GAAG;AAChB,gBAAU,QAAQ;AAClB,UAAI,KAAK,UAAU,EAAG;AAAA,IACxB;AACA,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AAEA,QAAM,WAAsC,CAAC;AAC7C,QAAM,OAAO,oBAAI,IAAa;AAE9B,WAAS,iBAAiB,qBAAqB,EAAE,QAAQ,CAAC,OAAO;AAC/D,QAAI,KAAK,IAAI,EAAE,EAAG;AAClB,SAAK,IAAI,EAAE;AAEX,UAAM,SAAS;AACf,QAAI,CAAC,UAAU,MAAM,EAAG;AAExB,UAAM,UAAU;AAChB,UAAM,OAAO,OAAO,sBAAsB;AAC1C,UAAM,eACJ,KAAK,OAAO,KACZ,KAAK,QAAQ,KACb,KAAK,WAAW,OAAO,eAAe,SAAS,gBAAgB,iBAC/D,KAAK,UAAU,OAAO,cAAc,SAAS,gBAAgB;AAG/D,UAAM,QAAiC;AAAA,MACrC,SAAS,OAAO,QAAQ,YAAY;AAAA,MACpC,MAAM,kBAAkB,MAAM;AAAA,MAC9B,MAAM,OAAO,aAAa,MAAM,KAAK;AAAA,MACrC,OAAO,QAAQ,SAAS;AAAA,MACxB,MAAM,OAAO,aAAa,MAAM,KAAK;AAAA,MACrC,UAAU,YAAY,MAAM;AAAA,MAC5B;AAAA,IACF;AAEA,QAAI,eAAe;AACjB,YAAM,cAAc;AAAA,QAClB,GAAG,KAAK,IAAI,OAAO;AAAA,QACnB,GAAG,KAAK,IAAI,OAAO;AAAA,QACnB,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,MACf;AAAA,IACF;AAEA,aAAS,KAAK,KAAK;AAAA,EACrB,CAAC;AAED,SAAO;AACT,GAAG;AAKH,eAAsB,+BACpB,SACA,UAAqC,CAAC,GACP;AAC/B,QAAM,EAAE,gBAAgB,MAAM,IAAI;AAClC,SAAQ,QAAgB,QAAQ,gBAAgB,aAAa;AAC/D;;;AClNA,IAAM,0BAA0B,OAAO,WAAY;AAEjD,QAAM,mBAA2C;AAAA,IAC/C,MAAM;AAAA,IAAW,QAAQ;AAAA,IAAa,OAAO;AAAA,IAAW,KAAK;AAAA,IAC7D,KAAK;AAAA,IAAW,UAAU;AAAA,IAAW,QAAQ;AAAA,IAC7C,UAAU;AAAA,IAAY,OAAO;AAAA,IAAS,OAAO;AAAA,IAC7C,QAAQ;AAAA,IAAU,OAAO;AAAA,IAAU,OAAO;AAAA,IAAU,MAAM;AAAA,IAAU,OAAO;AAAA,EAC7E;AAEA,QAAM,iBAAiB,oBAAI,IAAI;AAAA,IAC7B;AAAA,IAAc;AAAA,IAAQ;AAAA,IAAU;AAAA,IAAe;AAAA,IAAiB;AAAA,IAAQ;AAAA,IAAU;AAAA,EACpF,CAAC;AAGD,QAAM,kBAAkB,oBAAI,IAAI;AAAA,IAC9B;AAAA,IAAc;AAAA,IAAU;AAAA,IAAe;AAAA,IAAiB;AAAA,IAAQ;AAAA,IAChE;AAAA,IAAU;AAAA,IAAS;AAAA,IAAQ;AAAA,IAAY;AAAA,IAAS;AAAA,IAAO;AAAA,IAAY;AAAA,EACrE,CAAC;AAED,WAAS,QAAQ,IAAgC;AAC/C,UAAM,WAAW,GAAG,aAAa,MAAM;AACvC,QAAI,SAAU,QAAO,SAAS,MAAM,GAAG,EAAE,CAAC;AAE1C,UAAM,MAAM,GAAG,QAAQ,YAAY;AAEnC,YAAQ,KAAK;AAAA,MACX,KAAK;AAAU,eAAO;AAAA,MACtB,KAAK;AAAK,eAAO,GAAG,aAAa,MAAM,IAAI,SAAS;AAAA,MACpD,KAAK,SAAS;AACZ,cAAM,QAAQ,GAAG,aAAa,MAAM,KAAK,QAAQ,YAAY;AAC7D,YAAI,SAAS,SAAU,QAAO;AAC9B,eAAO,iBAAiB,IAAI,KAAK;AAAA,MACnC;AAAA,MACA,KAAK;AAAU,eAAO;AAAA,MACtB,KAAK;AAAY,eAAO;AAAA,MACxB,KAAK;AAAA,MAAM,KAAK;AAAA,MAAM,KAAK;AAAA,MAAM,KAAK;AAAA,MAAM,KAAK;AAAA,MAAM,KAAK;AAAM,eAAO;AAAA,MACzE,KAAK;AAAO,eAAO;AAAA,MACnB,KAAK;AAAO,eAAO;AAAA,MACnB,KAAK;AAAQ,eAAO;AAAA,MACpB,KAAK;AAAU,eAAO,CAAC,GAAG,QAAQ,gCAAgC,IAAI,WAAW;AAAA,MACjF,KAAK;AAAU,eAAO,CAAC,GAAG,QAAQ,gCAAgC,IAAI,gBAAgB;AAAA,MACtF,KAAK;AAAS,eAAO;AAAA,MACrB,KAAK;AAAU,eAAO;AAAA,MACtB,KAAK;AAAQ,eAAO;AAAA,MACpB,KAAK;AAAW,eAAQ,GAAG,aAAa,YAAY,KAAK,GAAG,aAAa,iBAAiB,IAAK,WAAW;AAAA,MAC1G,KAAK;AAAW,eAAO;AAAA,MACvB,KAAK;AAAW,eAAO;AAAA,MACvB,KAAK;AAAY,eAAO;AAAA,MACxB,KAAK;AAAS,eAAO;AAAA,MACrB,KAAK;AAAA,MAAM,KAAK;AAAM,eAAO;AAAA,MAC7B,KAAK;AAAM,eAAO;AAAA,MAClB,KAAK;AAAS,eAAO;AAAA,IACvB;AAEA,QAAK,GAAiD,oBAAoB,OAAQ,QAAO;AACzF,QAAI,GAAG,aAAa,UAAU,KAAK,SAAS,GAAG,aAAa,UAAU,KAAK,MAAM,EAAE,KAAK,EAAG,QAAO;AAElG,WAAO;AAAA,EACT;AAEA,WAAS,kBAAkB,IAAiB,MAA6B;AACvE,UAAM,YAAY,GAAG,aAAa,YAAY;AAC9C,QAAI,UAAW,QAAO,UAAU,KAAK;AAErC,UAAM,aAAa,GAAG,aAAa,iBAAiB;AACpD,QAAI,YAAY;AACd,YAAM,QAAQ,WAAW,MAAM,KAAK,EACjC,IAAI,QAAM,SAAS,eAAe,EAAE,GAAG,aAAa,KAAK,KAAK,EAAE,EAChE,OAAO,OAAO;AACjB,UAAI,MAAM,SAAS,EAAG,QAAO,MAAM,KAAK,GAAG,EAAE,MAAM,GAAG,GAAG;AAAA,IAC3D;AAEA,UAAM,MAAM,GAAG,QAAQ,YAAY;AAEnC,QAAI,QAAQ,SAAU,QAAQ,WAAW,GAAG,aAAa,MAAM,MAAM,SAAU;AAC7E,YAAM,MAAM,GAAG,aAAa,KAAK;AACjC,UAAI,QAAQ,KAAM,QAAO,IAAI,KAAK;AAAA,IACpC;AAEA,QAAI,CAAC,SAAS,UAAU,UAAU,EAAE,SAAS,GAAG,GAAG;AACjD,YAAM,KAAK,GAAG,aAAa,IAAI;AAC/B,UAAI,IAAI;AACN,cAAM,QAAQ,SAAS,cAAc,cAAc,IAAI,OAAO,EAAE,CAAC,IAAI;AACrE,YAAI,MAAO,QAAO,MAAM,aAAa,KAAK,KAAK;AAAA,MACjD;AACA,YAAM,cAAc,GAAG,QAAQ,OAAO;AACtC,UAAI,aAAa;AACf,cAAM,QAAQ,YAAY,UAAU,IAAI;AACxC,cAAM,iBAAiB,uBAAuB,EAAE,QAAQ,OAAK,EAAE,OAAO,CAAC;AACvE,cAAM,KAAK,MAAM,aAAa,KAAK;AACnC,YAAI,GAAI,QAAO;AAAA,MACjB;AAAA,IACF;AAEA,UAAM,KAAK,GAAG,aAAa,aAAa;AACxC,QAAI,GAAI,QAAO,GAAG,KAAK;AAEvB,UAAM,QAAQ,GAAG,aAAa,OAAO;AACrC,QAAI,MAAO,QAAO,MAAM,KAAK;AAE7B,QAAI,QAAQ,gBAAgB,IAAI,IAAI,EAAG,QAAO;AAC9C,YAAQ,GAAG,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG,KAAK,IAAI,MAAM,GAAG,GAAG;AAAA,EACzE;AAEA,WAAS,YAAY,SAA8B;AACjD,UAAM,MAAM,QAAQ,QAAQ,YAAY;AAExC,UAAM,OAAO,QAAQ,aAAa,KAAK,EAAE,QAAQ,QAAQ,GAAG;AAC5D,QAAI,QAAQ,KAAK,SAAS,KAAK,KAAK,UAAU,IAAI;AAChD,YAAM,kBAAkB,SAAS,iBAAiB,GAAG;AACrD,UAAI,aAAa;AACjB,sBAAgB,QAAQ,QAAM;AAAE,YAAI,GAAG,aAAa,SAAS,IAAI,EAAG;AAAA,MAAc,CAAC;AACnF,UAAI,eAAe,EAAG,QAAO,GAAG,GAAG,KAAK,IAAI;AAAA,IAC9C;AAEA,UAAM,YAAY,QAAQ,aAAa,YAAY;AACnD,QAAI,aAAa,UAAU,UAAU,GAAI,QAAO,QAAQ,SAAS;AAEjE,UAAM,SAAS,QAAQ,aAAa,aAAa;AACjD,QAAI,QAAQ;AACV,YAAM,MAAM,iBAAiB,IAAI,OAAO,MAAM,CAAC;AAC/C,UAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,IAC1D;AAEA,QAAI,QAAQ,GAAI,QAAO,IAAI,IAAI,OAAO,QAAQ,EAAE,CAAC;AAEjD,UAAM,WAAW,QAAQ,aAAa,MAAM;AAC5C,QAAI,UAAU;AACZ,YAAM,MAAM,GAAG,GAAG,UAAU,IAAI,OAAO,QAAQ,CAAC;AAChD,UAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,IAC1D;AAEA,QAAI,QAAQ,aAAa,OAAO,QAAQ,cAAc,UAAU;AAC9D,YAAM,UAAU,QAAQ,UAAU,KAAK,EAAE,MAAM,KAAK,EAAE,OAAO,OAAO;AACpE,iBAAW,OAAO,SAAS;AACzB,cAAM,MAAM,GAAG,GAAG,IAAI,IAAI,OAAO,GAAG,CAAC;AACrC,YAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,MAC1D;AACA,UAAI,QAAQ,UAAU,GAAG;AACvB,cAAM,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,GAAG,CAAC,EAAE,IAAI,OAAK,IAAI,IAAI,OAAO,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC;AAC/E,YAAI,SAAS,iBAAiB,GAAG,EAAE,WAAW,EAAG,QAAO;AAAA,MAC1D;AAAA,IACF;AAEA,QAAI,UAA8B;AAClC,UAAM,OAAiB,CAAC;AACxB,WAAO,WAAW,YAAY,SAAS,iBAAiB;AACtD,UAAI,MAAM,QAAQ,QAAQ,YAAY;AACtC,UAAI,QAAQ,IAAI;AAAE,aAAK,QAAQ,IAAI,IAAI,OAAO,QAAQ,EAAE,CAAC,EAAE;AAAG;AAAA,MAAO;AACrE,YAAM,SAAS,QAAQ;AACvB,UAAI,QAAQ;AACV,cAAM,WAAW,MAAM,KAAK,OAAO,QAAQ,EAAE,OAAO,OAAK,EAAE,YAAY,QAAS,OAAO;AACvF,YAAI,SAAS,SAAS,EAAG,QAAO,gBAAgB,SAAS,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC/E;AACA,WAAK,QAAQ,GAAG;AAChB,gBAAU,QAAQ;AAClB,UAAI,KAAK,UAAU,EAAG;AAAA,IACxB;AACA,WAAO,KAAK,KAAK,KAAK;AAAA,EACxB;AAEA,WAAS,UAAU,IAA0B;AAC3C,QAAI,OAAO,GAAG,oBAAoB,YAAY;AAC5C,aAAO,GAAG,gBAAgB,EAAE,iBAAiB,MAAM,oBAAoB,MAAM,uBAAuB,KAAK,CAAC;AAAA,IAC5G;AACA,UAAM,QAAQ,OAAO,iBAAiB,EAAE;AACxC,WAAO,MAAM,YAAY,UACvB,MAAM,eAAe,YACrB,MAAM,YAAY,OAClB,GAAG,cAAc,KACjB,GAAG,eAAe;AAAA,EACtB;AAEA,WAAS,SAAS,IAAqC;AACrD,UAAM,IAAI,GAAG,QAAQ,YAAY,EAAE,MAAM,YAAY;AACrD,QAAI,EAAG,QAAO,SAAS,EAAE,CAAC,GAAG,EAAE;AAC/B,UAAM,YAAY,GAAG,aAAa,YAAY;AAC9C,QAAI,UAAW,QAAO,SAAS,WAAW,EAAE;AAC5C,WAAO;AAAA,EACT;AAEA,WAAS,SAAS,IAAyC;AACzD,UAAM,UAAU;AAChB,UAAM,cAAc,CAAC,SAAS,oBAAoB,eAAe,EAAE,SAAS,GAAG,QAAQ,YAAY,CAAC,KAClG,CAAC,YAAY,SAAS,QAAQ,EAAE,SAAS,GAAG,aAAa,MAAM,KAAK,EAAE;AACxE,WAAO;AAAA,MACL,UAAW,GAAG,aAAa,eAAe,MAAM,UAAU,QAAQ,WAAY,SAAS;AAAA,MACvF,SAAU,eAAe,QAAQ,UAAW,SAAS,GAAG,aAAa,cAAc,KAAK;AAAA,MACxF,UAAU,GAAG,aAAa,eAAe,KAAK;AAAA,MAC9C,UAAU,GAAG,aAAa,eAAe,KAAK;AAAA,MAC9C,SAAS,GAAG,aAAa,cAAc,KAAK;AAAA,MAC5C,UAAW,QAAQ,YAAY,GAAG,aAAa,eAAe,MAAM,SAAU,SAAS;AAAA,MACvF,UAAW,QAAQ,YAAY,GAAG,aAAa,eAAe,MAAM,SAAU,SAAS;AAAA,IACzF;AAAA,EACF;AAIA,QAAM,SAAoB,CAAC;AAE3B,WAAS,KAAK,IAAiB,QAAQ,GAAS;AAC9C,QAAI,QAAQ,IAAK;AACjB,QAAI,CAAC,UAAU,EAAE,EAAG;AAEpB,UAAM,OAAO,QAAQ,EAAE;AAEvB,QAAI,CAAC,MAAM;AACT,iBAAW,SAAS,MAAM,KAAK,GAAG,QAAQ,GAAG;AAC3C,aAAK,OAAsB,QAAQ,CAAC;AAAA,MACtC;AACA;AAAA,IACF;AAEA,UAAM,OAAO,kBAAkB,IAAI,IAAI;AACvC,UAAM,aAAa,eAAe,IAAI,IAAI;AAC1C,UAAM,cAAc,CAAC,EAAE,QAAQ;AAC/B,UAAM,WAAW,cAAc,YAAY,EAAE,IAAI;AACjD,UAAM,OAAgB,EAAE,MAAM,MAAM,UAAU,OAAO,SAAS,EAAE,KAAK,IAAI,GAAG,SAAS,EAAE,EAAE;AACzF,WAAO,KAAK,IAAI;AAEhB,eAAW,SAAS,MAAM,KAAK,GAAG,QAAQ,GAAG;AAC3C,WAAK,OAAsB,QAAQ,CAAC;AAAA,IACtC;AAAA,EACF;AAEA,aAAW,SAAS,MAAM,KAAK,SAAS,KAAK,QAAQ,GAAG;AACtD,SAAK,OAAsB,CAAC;AAAA,EAC9B;AAEA,SAAO;AACT,GAAG;AAKH,eAAsB,4BACpB,SAC8B;AAC9B,SAAQ,QAAgB,QAAQ,uBAAuB;AACzD;;;ACjQO,IAAM,4BAA4B;AAAA;AAAA,EAEvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AACF;AAEO,IAAM,4BAA4B;AAAA;AAAA,EAEvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AACF;AAEO,IAAM,wBAAwB;AAAA;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,IAAM,wBAAwB;AAAA;AAAA,EAEnC;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AACF;;;ACpKA,SAAS,iBAAiB;AAC1B,OAAO,WAAW;AAMlB,SAAS,aAAa,MAAoB;AACxC,QAAM,WAAmB,CAAC;AAC1B,MAAI,KAAK,YAAY;AACnB,aAAS,IAAI,GAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAC/C,YAAM,QAAQ,KAAK,WAAW,KAAK,CAAC;AACpC,UAAI,OAAO,aAAa,GAAG;AACzB,iBAAS,KAAK,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAKA,SAAS,qBACP,SACA,aAAqB,IACrB,QAAuB,MACV;AACb,QAAM,aAAgC,CAAC;AAEvC,QAAM,UAAU;AAChB,MAAI,QAAQ,YAAY;AACtB,aAAS,UAAU,GAAG,UAAU,QAAQ,WAAW,QAAQ,WAAW;AACpE,YAAM,OAAO,QAAQ,WAAW,KAAK,OAAO;AAC5C,UAAI,MAAM;AACR,mBAAW,KAAK,IAAI,IAAI,KAAK,MAAM,QAAQ,UAAU,KAAK;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAEA,QAAM,OAAO,UAAU,OAAO,KAAK,GAAG,aAAa,aAAa,MAAM,EAAE,GAAG,KAAK;AAEhF,SAAO;AAAA,IACL,UAAU,aAAa,OAAO,EAAE;AAAA,MAAI,CAAC,WAAW,eAC9C,qBAAqB,WAAW,MAAM,UAAU;AAAA,IAClD;AAAA,IACA,SAAS,QAAQ;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,cAAc,OAAa,OAAsB;AACxD,MAAI,MAAM,aAAa,KAAK,MAAM,aAAa,EAAG,QAAO;AACzD,QAAM,MAAM;AACZ,QAAM,MAAM;AAEZ,MAAI,IAAI,aAAa,IAAI,SAAU,QAAO;AAG1C,QAAM,UAAU,IAAI,aAAa,QAAQ;AACzC,QAAM,UAAU,IAAI,aAAa,QAAQ;AACzC,MAAI,WAAW,SAAS;AACtB,WAAO,YAAY;AAAA,EACrB;AAGA,QAAM,KAAK,IAAI,aAAa,GAAG;AAC/B,QAAM,KAAK,IAAI,aAAa,GAAG;AAC/B,QAAM,KAAK,IAAI,aAAa,GAAG;AAC/B,QAAM,KAAK,IAAI,aAAa,GAAG;AAC/B,MAAI,MAAM,MAAM,MAAM,IAAI;AACxB,WACE,OAAO,MACP,OAAO,MACP,IAAI,aAAa,OAAO,MAAM,IAAI,aAAa,OAAO,KACtD,IAAI,aAAa,QAAQ,MAAM,IAAI,aAAa,QAAQ;AAAA,EAE5D;AAEA,SAAO;AACT;AAKO,SAAS,UAAU,WAAuC;AAC/D,MAAI;AACF,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,YAAY,OAAO,gBAAgB,WAAW,UAAU;AAE9D,UAAM,cAAc,UAAU,qBAAqB,aAAa;AAChE,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,MAAM,kCAAkC,YAAY,CAAC,EAAE,WAAW;AAC1E,aAAO;AAAA,IACT;AAEA,UAAM,WAAW,aAAa,SAAS;AACvC,UAAM,aACJ,SAAS,CAAC,MACT,UAAU,kBAAkB,aAAa,UAAU,eAAe,EAAE,CAAC,IAAI;AAE5E,WAAO,aACH,qBAAqB,UAAU,IAC/B,EAAE,UAAU,CAAC,GAAG,SAAS,IAAI,YAAY,CAAC,GAAG,MAAM,GAAG;AAAA,EAC5D,SAAS,GAAG;AACV,YAAQ,MAAM,oCAAoC,CAAC;AACnD,WAAO;AAAA,EACT;AACF;AAKO,SAAS,SAAS,WAAoC;AAC3D,MAAI;AACF,UAAM,SAAS,IAAI,UAAU;AAC7B,UAAM,MAAM,OAAO,gBAAgB,WAAW,UAAU;AAExD,UAAM,cAAc,IAAI,qBAAqB,aAAa;AAC1D,QAAI,YAAY,SAAS,GAAG;AAC1B,cAAQ,MAAM,iCAAiC,YAAY,CAAC,EAAE,WAAW;AACzE,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT,SAAS,GAAG;AACV,YAAQ,MAAM,mCAAmC,CAAC;AAClD,WAAO;AAAA,EACT;AACF;AAKO,SAAS,cAAc,KAAe,WAA2B;AACtE,MAAI;AACF,UAAM,QAAQ,MAAM,OAAO,WAAW,GAAG;AACzC,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,aAAO;AAAA,IACT;AACA,WAAO,CAAC;AAAA,EACV,SAAS,GAAG;AACV,YAAQ,MAAM,uCAAuC,SAAS,MAAM,CAAC;AACrE,WAAO,CAAC;AAAA,EACV;AACF;AAKO,SAAS,qBACd,KACA,WACA,YACkB;AAClB,MAAI;AACF,UAAM,QAAQ,cAAc,KAAK,SAAS;AAC1C,UAAM,eAAe,MAAM;AAE3B,QAAI,iBAAiB,GAAG;AACtB,aAAO,EAAE,UAAU,MAAM;AAAA,IAC3B;AAEA,QAAI,iBAAiB,GAAG;AACtB,aAAO,EAAE,UAAU,KAAK;AAAA,IAC1B;AAGA,QAAI,YAAY;AACd,eAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAI,MAAM,CAAC,MAAM,cAAc,cAAc,MAAM,CAAC,GAAG,UAAU,GAAG;AAClE,iBAAO;AAAA,YACL,UAAU;AAAA,YACV,OAAO,IAAI;AAAA;AAAA,YACX;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,UAAU,OAAO,aAAa;AAAA,EACzC,SAAS,GAAG;AACV,YAAQ,MAAM,0CAA0C,SAAS,MAAM,CAAC;AACxE,WAAO,EAAE,UAAU,MAAM;AAAA,EAC3B;AACF;AAKO,SAAS,kBAAkB,KAAe,MAA2B;AAC1E,MAAI,CAAC,KAAM,QAAO,IAAI;AAEtB,QAAM,UAAU,KAAK,MAAM,GAAG,EAAE,IAAI,MAAM;AAC1C,MAAI,UAAuB,IAAI;AAE/B,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,QAAS,QAAO;AAErB,UAAM,WAAmB,CAAC;AAC1B,QAAI,QAAQ,YAAY;AACtB,eAAS,IAAI,GAAG,IAAI,QAAQ,WAAW,QAAQ,KAAK;AAClD,cAAM,QAAQ,QAAQ,WAAW,KAAK,CAAC;AACvC,YAAI,OAAO,aAAa,GAAG;AACzB,mBAAS,KAAK,KAAK;AAAA,QACrB;AAAA,MACF;AAAA,IACF;AAEA,cAAU,SAAS,KAAK,KAAK;AAAA,EAC/B;AAEA,SAAO;AACT;AAKO,SAAS,mBAAmB,QAAwB;AACzD,QAAM,QAAQ,OAAO,MAAM,gCAAgC;AAC3D,MAAI,CAAC,OAAO;AACV,WAAO,EAAE,GAAG,GAAG,GAAG,GAAG,OAAO,GAAG,QAAQ,EAAE;AAAA,EAC3C;AAEA,QAAM,KAAK,SAAS,MAAM,CAAC,GAAG,EAAE;AAChC,QAAM,KAAK,SAAS,MAAM,CAAC,GAAG,EAAE;AAChC,QAAM,KAAK,SAAS,MAAM,CAAC,GAAG,EAAE;AAChC,QAAM,KAAK,SAAS,MAAM,CAAC,GAAG,EAAE;AAEhC,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAG;AAAA,IACH,OAAO,KAAK;AAAA,IACZ,QAAQ,KAAK;AAAA,EACf;AACF;AAKO,SAAS,eAAe,YAAuC;AACpE,SAAO;AAAA,IACL,GAAG,SAAS,WAAW,KAAK,KAAK,EAAE;AAAA,IACnC,GAAG,SAAS,WAAW,KAAK,KAAK,EAAE;AAAA,IACnC,OAAO,SAAS,WAAW,SAAS,KAAK,EAAE;AAAA,IAC3C,QAAQ,SAAS,WAAW,UAAU,KAAK,EAAE;AAAA,EAC/C;AACF;AAsBO,SAAS,0BACd,WACA,WACA,OACQ;AACR,QAAM,eAAe,MAAM,QAAQ,uBAAuB,MAAM;AAChE,QAAM,UAAU,IAAI,OAAO,GAAG,SAAS,QAAQ,YAAY,QAAQ,GAAG;AACtE,QAAM,UAAU,UAAU,MAAM,OAAO;AACvC,SAAO,UAAU,QAAQ,SAAS;AACpC;AAKO,SAAS,kBACd,WACA,WACA,OACS;AACT,SAAO,0BAA0B,WAAW,WAAW,KAAK,MAAM;AACpE;;;AC3RA,SAAS,eAAe,SAAiB,SAA4B;AACnE,MAAI,QAAQ,SAAS,OAAO,GAAG;AAC7B,WAAO;AAAA,EACT;AAEA,aAAW,OAAO,SAAS;AACzB,QAAI,QAAQ,SAAS,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AAClD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,kBACP,SACA,iBACA,iBACS;AACT,MAAI,gBAAgB,SAAS,KAAK,CAAC,eAAe,QAAQ,SAAS,eAAe,GAAG;AACnF,WAAO;AAAA,EACT;AAEA,MAAI,eAAe,QAAQ,SAAS,eAAe,GAAG;AACpD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKA,SAAS,wBACP,SACA,mBACA,mBACS;AACT,MAAI,kBAAkB,SAAS,GAAG;AAChC,UAAM,kBAAkB,kBAAkB,KAAK,CAAC,SAAS,QAAQ,aAAa,IAAI,CAAC;AACnF,QAAI,CAAC,gBAAiB,QAAO;AAAA,EAC/B;AAEA,MAAI,QAAQ,cAAc,oBAAoB,GAAG;AAC/C,UAAM,YAAY,OAAO,OAAO,QAAQ,UAAU,EAAE;AAAA,MAClD,CAAC,MAAM,MAAM,UAAa,MAAM,QAAQ,MAAM;AAAA,IAChD,EAAE;AACF,QAAI,YAAY,mBAAmB;AACjC,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,sBACd,SACA,UACA,gBACS;AACT,QAAM,YAAY,eAAe,YAAY,EAAE,SAAS,aAAa;AACrE,QAAM,mBAAmB,YAAY,4BAA4B;AAEjE,MAAI,eAAe,QAAQ,SAAS,gBAAgB,GAAG;AACrD,WAAO;AAAA,EACT;AAEA,MAAI,WAAW;AACb,QACE,QAAQ,YAAY,cAAc,UAClC,QAAQ,YAAY,cAAc,UAClC,QAAQ,YAAY,cAAc,UAClC,QAAQ,aAAa,gBAAgB,MAAM,QAC3C;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,CAAC,WAAW;AACd,QAAI,QAAQ,YAAY,eAAe,QAAQ;AAC7C,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,kBAAkB,SAAsB,UAAsC;AAC5F,QAAM,gBAAgB,aAAa,YAAY,4BAA4B;AAC3E,SAAO,eAAe,QAAQ,SAAS,aAAa;AACtD;AAKO,SAAS,qBACd,SACA,UACS;AACT,QAAM,QAAQ,QAAQ;AAEtB,MAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,SAAS,QAAQ;AACnE,WAAO;AAAA,EACT;AAEA,MAAI,aAAa,WAAW;AAC1B,QAAI,MAAM,cAAc,KAAK,MAAM,cAAc,EAAE,KAAK,MAAM,MAAM,MAAM,cAAc,MAAM,QAAQ;AACpG,aAAO;AAAA,IACT;AAAA,EACF,OAAO;AACL,QAAI,MAAM,SAAS,MAAM,MAAM,KAAK,MAAM,MAAM,MAAM,UAAU,QAAQ;AACtE,aAAO;AAAA,IACT;AACA,QAAI,MAAM,QAAQ,MAAM,KAAK,KAAK,MAAM,MAAM,MAAM,SAAS,QAAQ;AACnE,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,qBACd,SACA,SACA,UACA,gBACS;AACT,QAAM;AAAA,IACJ,kBAAkB,CAAC;AAAA,IACnB,kBAAkB,CAAC,WAAW;AAAA,IAC9B,oBAAoB,CAAC;AAAA,IACrB,oBAAoB;AAAA,IACpB,gBAAgB;AAAA,IAChB,gBAAgB;AAAA,IAChB,cAAc;AAAA,EAChB,IAAI;AAEJ,MAAI,CAAC,kBAAkB,SAAS,iBAAiB,eAAe,GAAG;AACjE,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,wBAAwB,SAAS,mBAAmB,iBAAiB,GAAG;AAC3E,WAAO;AAAA,EACT;AAEA,MAAI,iBAAiB,QAAQ,YAAY,cAAc,QAAQ;AAC7D,WAAO;AAAA,EACT;AAEA,MAAI,aAAa;AACf,UAAM,YAAY,eAAe,YAAY,EAAE,SAAS,aAAa;AACrE,QAAI,aAAa,QAAQ,YAAY,cAAc,SAAS;AAC1D,aAAO;AAAA,IACT;AACA,QAAI,CAAC,aAAa,QAAQ,YAAY,YAAY,SAAS;AACzD,aAAO;AAAA,IACT;AAAA,EACF;AAEA,MAAI,iBAAiB,CAAC,sBAAsB,SAAS,UAAU,cAAc,GAAG;AAC9E,WAAO;AAAA,EACT;AAEA,SAAO;AACT;AAKO,SAAS,kBACd,UACA,oBAA6B,OACd;AACf,QAAM,mBAAmB,aAAa,YAAY,4BAA4B;AAE9E,SAAO;AAAA,IACL,iBAAiB,oBAAoB,CAAC,WAAW,IAAI,CAAC,aAAa,GAAG,gBAAgB;AAAA,IACtF,eAAe,CAAC;AAAA,IAChB,aAAa;AAAA,IACb,eAAe;AAAA,EACjB;AACF;;;ACtMA,SAAS,aAAa,OAA4C;AAChE,SAAO,UAAU,UAAa,UAAU,QAAQ,UAAU,UAAU,MAAM,KAAK,MAAM;AACvF;AAKA,SAAS,WAAW,MAAsB;AACxC,SAAO,KAAK,QAAQ,MAAM,KAAK,EAAE,QAAQ,OAAO,KAAK;AACvD;AAKA,SAAS,iBAAiB,OAAuB;AAC/C,MAAI,CAAC,MAAM,SAAS,GAAG,GAAG;AACxB,WAAO,IAAI,KAAK;AAAA,EAClB;AACA,MAAI,CAAC,MAAM,SAAS,GAAG,GAAG;AACxB,WAAO,IAAI,KAAK;AAAA,EAClB;AACA,QAAM,QAAkB,CAAC;AACzB,MAAI,UAAU;AACd,aAAW,QAAQ,OAAO;AACxB,QAAI,SAAS,KAAK;AAChB,UAAI,QAAS,OAAM,KAAK,IAAI,OAAO,GAAG;AACtC,YAAM,KAAK,KAAM;AACjB,gBAAU;AAAA,IACZ,OAAO;AACL,iBAAW;AAAA,IACb;AAAA,EACF;AACA,MAAI,QAAS,OAAM,KAAK,IAAI,OAAO,GAAG;AACtC,SAAO,UAAU,MAAM,KAAK,GAAG,CAAC;AAClC;AAKA,SAAS,qBAAqB,WAAmB,OAAuB;AACtE,SAAO,IAAI,SAAS,KAAK,KAAK;AAChC;AAKA,SAAS,2BAA2B,cAAsB,OAAuB;AAC/E,SAAO,GAAG,YAAY,aAAa,QAAQ,CAAC;AAC9C;AAKA,SAAS,gBACP,KACAA,QACA,YACkB;AAClB,MAAI,IAAI,WAAW;AACjB,WAAO,qBAAqB,IAAI,WAAWA,QAAO,UAAU;AAAA,EAC9D;AAEA,QAAM,QAAQA,OAAM,MAAM,8BAA8B;AACxD,MAAI,OAAO;AACT,UAAM,CAAC,EAAE,MAAM,KAAK,IAAI;AACxB,WAAO,EAAE,UAAU,kBAAkB,IAAI,WAAW,MAAM,KAAK,EAAE;AAAA,EACnE;AACA,SAAO,EAAE,UAAU,MAAM;AAC3B;AAKA,SAAS,gBAAgB,SAA0B;AACjD,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UAAU,QAAQ;AACxB,MAAI,QAAQ;AAEZ,WAAS,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;AACjD,UAAM,QAAQ,OAAO,WAAW,KAAK,CAAC;AACtC,QAAI,OAAO,aAAa,KAAK,MAAM,aAAa,SAAS;AACvD;AACA,UAAI,UAAU,QAAS,QAAO;AAAA,IAChC;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,cAAc,SAA0B;AAC/C,QAAM,SAAS,QAAQ;AACvB,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,UAAU,QAAQ;AACxB,MAAI,QAAQ;AAEZ,WAAS,IAAI,GAAG,IAAI,OAAO,WAAW,QAAQ,KAAK;AACjD,UAAM,QAAQ,OAAO,WAAW,KAAK,CAAC;AACtC,QAAI,OAAO,aAAa,KAAK,MAAM,aAAa,SAAS;AACvD;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,oBAAoB,SAAkB,KAAoC;AACjF,QAAM,QAAQ,IAAI,YACd,CAAC,eAAe,gBAAgB,MAAM,IACtC,CAAC,QAAQ,SAAS,OAAO;AAE7B,aAAW,QAAQ,OAAO;AACxB,UAAM,QAAQ,QAAQ,aAAa,IAAI;AACvC,QAAI,SAAS,MAAM,KAAK,GAAG;AACzB,YAAMA,SAAQ,QAAQ,IAAI,IAAI,iBAAiB,KAAK,CAAC;AACrD,YAAM,SAAS,IAAI,YACf,qBAAqB,IAAI,WAAWA,MAAK,IACzC,EAAE,UAAU,kBAAkB,IAAI,WAAW,MAAM,KAAK,EAAE;AAE9D,UAAI,OAAO,UAAU;AACnB,eAAO,IAAI,IAAI,IAAI,iBAAiB,KAAK,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,uBACP,KACA,SACA,WAAmB,GACJ;AACf,MAAI,CAAC,IAAI,UAAW,QAAO;AAE3B,QAAM,YAAsB,CAAC;AAC7B,MAAI,UAA0B;AAC9B,MAAI,QAAQ;AAEZ,SAAO,WAAW,QAAQ,UAAU;AAClC,UAAM,UAAU,QAAQ;AACxB,UAAM,aAAa,oBAAoB,SAAS,GAAG;AAEnD,QAAI,YAAY;AACd,gBAAU,QAAQ,KAAK,OAAO,IAAI,UAAU,GAAG;AAC/C;AAAA,IACF,OAAO;AACL,YAAM,eAAe,gBAAgB,OAAO;AAC5C,YAAM,eAAe,cAAc,OAAO;AAE1C,UAAI,eAAe,GAAG;AACpB,kBAAU,QAAQ,GAAG,OAAO,IAAI,YAAY,GAAG;AAAA,MACjD,OAAO;AACL,kBAAU,QAAQ,OAAO;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,SAAS,QAAQ;AACvB,cAAU,UAAU,OAAO,aAAa,IAAI,SAAS;AACrD;AAAA,EACF;AAEA,MAAI,UAAU,WAAW,EAAG,QAAO;AAEnC,MAAI,SAAS,UAAU,CAAC;AACxB,WAAS,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK;AACzC,cAAU,MAAM,UAAU,CAAC;AAAA,EAC7B;AAEA,MAAI,CAAC,OAAO,WAAW,IAAI,GAAG;AAC5B,aAAS,OAAO;AAAA,EAClB;AAEA,SAAO;AACT;AAKA,SAAS,gBACP,SACAA,QACA,KACA,YACM;AACN,QAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AACzD,MAAI,WAAW,UAAU;AACvB,YAAQ,KAAK,CAAC,SAASA,MAAK,CAAC;AAAA,EAC/B,WAAW,WAAW,OAAO;AAC3B,YAAQ,KAAK,CAAC,SAAS,qBAAqBA,QAAO,WAAW,KAAK,CAAC,CAAC;AAAA,EACvE,OAAO;AACL,QAAI,cAAc,IAAI,WAAW;AAC/B,YAAM,eAAe,uBAAuB,KAAK,UAAqB;AACtE,UAAI,cAAc;AAChB,gBAAQ,KAAK,CAAC,SAAS,YAAY,CAAC;AAAA,MACtC;AAAA,IACF;AACA,YAAQ,KAAK,CAAC,SAASA,MAAK,CAAC;AAAA,EAC/B;AACF;AAKA,SAAS,qBAAqB,SAAsB,KAA+B;AACjF,MAAI,CAAC,IAAK,QAAO;AAEjB,QAAM,iBAAiB,cAAc,KAAK,cAAc;AACxD,MAAI,eAAe,WAAW,EAAG,QAAO;AAExC,QAAM,YAAY,eAAe;AACjC,QAAM,YAAY,QAAQ,KAAK,MAAM,GAAG;AACxC,MAAI,UAAU,WAAW,KAAK,UAAU,CAAC,MAAM,GAAI,QAAO;AAE1D,QAAM,aAAa,SAAS,UAAU,CAAC,GAAG,EAAE;AAC5C,SAAO,eAAe,YAAY;AACpC;AAKA,SAAS,yBAAyB,SAAqC;AACrE,QAAM,QAAQ,QAAQ;AACtB,QAAM,QAAkB,CAAC;AAEzB,MAAI,aAAa,MAAM,aAAa,CAAC,GAAG;AACtC,UAAM,KAAK,eAAe,MAAM,aAAa,CAAC,IAAI;AAAA,EACpD;AACA,MAAI,aAAa,MAAM,IAAI,KAAK,MAAM,KAAM,SAAS,KAAK;AACxD,UAAM,KAAK,SAAS,WAAW,MAAM,IAAK,CAAC,IAAI;AAAA,EACjD;AACA,MAAI,aAAa,MAAM,cAAc,CAAC,GAAG;AACvC,UAAM,KAAK,gBAAgB,MAAM,cAAc,CAAC,IAAI;AAAA,EACtD;AACA,MAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,UAAM,KAAK,cAAc,MAAM,KAAK,IAAI;AAAA,EAC1C;AAEA,MAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,SAAO,4BAA4B,MAAM,KAAK,GAAG,CAAC;AACpD;AAKA,SAAS,qBAAqB,SAAqC;AACjE,QAAM,QAAQ,QAAQ;AACtB,QAAM,aAAuB,CAAC;AAE9B,MAAI,aAAa,MAAM,IAAI,GAAG;AAC5B,eAAW,KAAK,YAAY,WAAW,MAAM,IAAK,CAAC,GAAG;AAAA,EACxD;AACA,MAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,eAAW,KAAK,aAAa,WAAW,MAAM,KAAM,CAAC,GAAG;AAAA,EAC1D;AACA,MAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,eAAW,KAAK,aAAa,WAAW,MAAM,KAAM,CAAC,GAAG;AAAA,EAC1D;AACA,MAAI,MAAM,YAAY,QAAQ;AAC5B,eAAW,KAAK,cAAc;AAAA,EAChC;AACA,MAAI,MAAM,YAAY,QAAQ;AAC5B,eAAW,KAAK,cAAc;AAAA,EAChC;AAEA,MAAI,WAAW,WAAW,EAAG,QAAO;AAEpC,SAAO,yBAAyB,WAAW,KAAK,OAAO,CAAC;AAC1D;AAKA,SAAS,gBAAgB,SAAqC;AAC5D,QAAM,QAAQ,QAAQ;AACtB,QAAM,UAAU,QAAQ;AAExB,MAAI,CAAC,QAAQ,WAAW,MAAM,EAAG,QAAO;AAExC,MAAI,WAAW,MAAM,OAAO;AAE5B,MAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,gBAAY,gBAAgB,WAAW,MAAM,KAAM,CAAC;AAAA,EACtD,WAAW,aAAa,MAAM,IAAI,GAAG;AACnC,gBAAY,eAAe,WAAW,MAAM,IAAK,CAAC;AAAA,EACpD;AAEA,SAAO,oBAAoB,QAAQ;AACrC;AAKA,SAAS,WAAW,SAAsB,WAAmB,WAAmC;AAC9F,QAAM,QAAQ,QAAQ;AACtB,QAAM,UAAU,QAAQ;AACxB,QAAM,aAAuB,CAAC;AAE9B,MAAI,WAAW;AACb,QAAI,aAAa,MAAM,aAAa,CAAC,GAAG;AACtC,iBAAW,KAAK,iBAAiB,MAAM,aAAa,CAAC,GAAG;AAAA,IAC1D;AACA,QAAI,aAAa,MAAM,cAAc,CAAC,GAAG;AACvC,iBAAW,KAAK,kBAAkB,MAAM,cAAc,CAAC,GAAG;AAAA,IAC5D;AACA,QAAI,aAAa,MAAM,IAAI,KAAK,MAAM,KAAM,SAAS,KAAK;AACxD,iBAAW,KAAK,UAAU,WAAW,MAAM,IAAK,CAAC,GAAG;AAAA,IACtD;AAAA,EACF,OAAO;AACL,QAAI,aAAa,MAAM,IAAI,GAAG;AAC5B,iBAAW,KAAK,UAAU,MAAM,IAAI,GAAG;AAAA,IACzC;AACA,QAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,iBAAW,KAAK,WAAW,MAAM,KAAK,GAAG;AAAA,IAC3C;AACA,QAAI,aAAa,MAAM,KAAK,GAAG;AAC7B,iBAAW,KAAK,WAAW,MAAM,KAAK,GAAG;AAAA,IAC3C;AAAA,EACF;AAEA,MAAI,WAAW,WAAW,GAAG;AAC3B,WAAO,KAAK,OAAO;AAAA,EACrB;AAEA,SAAO,KAAK,OAAO,IAAI,WAAW,KAAK,OAAO,CAAC;AACjD;AAKA,SAAS,2BACP,SACA,KACA,gBACA,YAC6B;AAC7B,QAAM,UAAuC,CAAC;AAC9C,QAAM,YAAY,eAAe,YAAY,EAAE,SAAS,aAAa;AACrE,QAAM,QAAQ,QAAQ;AACtB,QAAM,qBAAqB,YAAY,qBAAqB,SAAS,IAAI,SAAS,IAAI;AAEtF,MAAI,WAAW;AAEb,UAAM,aAAa,MAAM,aAAa;AACtC,QAAI,aAAa,UAAU,GAAG;AAC5B,YAAMA,SAAQ,qBAAqB,UAAU;AAC7C,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,YAAY,oBAAoB;AAC7C,gBAAQ,KAAK,CAAC,MAAM,wCAAwC,UAAU,IAAI,CAAC;AAAA,MAC7E,WAAW,WAAW,SAAS,oBAAoB;AACjD,cAAM,OAAO,wCAAwC,UAAU;AAC/D,gBAAQ,KAAK,CAAC,MAAM,2BAA2B,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,MACzE;AAAA,IACF;AAGA,UAAM,cAAc,MAAM,cAAc;AACxC,QAAI,aAAa,WAAW,GAAG;AAC7B,YAAMA,SAAQ,sBAAsB,WAAW;AAC/C,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,UAAU;AACvB,gBAAQ,KAAK,CAAC,oBAAoB,IAAI,WAAW,EAAE,CAAC;AAAA,MACtD;AAAA,IACF;AAGA,UAAM,OAAO,MAAM;AACnB,QAAI,aAAa,IAAI,KAAK,KAAK,SAAS,KAAK;AAC3C,YAAMA,SAAQ,cAAc,WAAW,IAAI,CAAC;AAC5C,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,YAAY,oBAAoB;AAC7C,gBAAQ,KAAK,CAAC,QAAQ,kCAAkC,WAAW,IAAI,CAAC,IAAI,CAAC;AAAA,MAC/E,WAAW,WAAW,SAAS,oBAAoB;AACjD,cAAM,OAAO,kCAAkC,WAAW,IAAI,CAAC;AAC/D,gBAAQ,KAAK,CAAC,QAAQ,2BAA2B,MAAM,WAAW,KAAK,CAAC,CAAC;AAAA,MAC3E;AAAA,IACF;AAAA,EACF,OAAO;AAEL,UAAM,OAAO,MAAM;AACnB,QAAI,aAAa,IAAI,GAAG;AACtB,YAAMA,SAAQ,cAAc,IAAI;AAChC,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,UAAU;AACvB,gBAAQ,KAAK,CAAC,oBAAoB,IAAI,IAAI,EAAE,CAAC;AAAA,MAC/C;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM;AACpB,QAAI,aAAa,KAAK,KAAK,UAAU,MAAM,MAAM;AAC/C,YAAMA,SAAQ,eAAe,WAAW,KAAK,CAAC;AAC9C,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,UAAU;AACvB,gBAAQ,KAAK,CAAC,oBAAoB,mCAAmC,WAAW,KAAK,CAAC,GAAG,CAAC;AAAA,MAC5F;AAAA,IACF;AAGA,UAAM,QAAQ,MAAM;AACpB,QAAI,aAAa,KAAK,GAAG;AACvB,YAAMA,SAAQ,eAAe,WAAW,KAAK,CAAC;AAC9C,YAAM,aAAa,gBAAgB,KAAKA,QAAO,UAAU;AAEzD,UAAI,WAAW,UAAU;AACvB,gBAAQ,KAAK,CAAC,oBAAoB,mCAAmC,WAAW,KAAK,CAAC,GAAG,CAAC;AAAA,MAC5F;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAKA,SAAS,4BACP,SACA,KACA,gBACA,YAC6B;AAC7B,QAAM,UAAuC,CAAC;AAC9C,QAAM,YAAY,eAAe,YAAY,EAAE,SAAS,aAAa;AACrE,QAAM,qBAAqB,YAAY,qBAAqB,SAAS,IAAI,SAAS,IAAI;AAEtF,MAAI,WAAW;AACb,QAAI,oBAAoB;AACtB,YAAM,cAAc,yBAAyB,OAAO;AACpD,UAAI,aAAa;AACf,gBAAQ,KAAK,CAAC,eAAe,WAAW,CAAC;AAAA,MAC3C;AAAA,IACF;AAEA,UAAMA,SAAQ,WAAW,SAAS,IAAI,WAAW,IAAI;AACrD,QAAIA,QAAO;AACT,sBAAgB,SAASA,QAAO,KAAK,UAAU;AAAA,IACjD;AAEA,QAAI,sBAAsB,aAAa,QAAQ,WAAW,KAAK,GAAG;AAChE,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,uCAAuC,QAAQ,WAAW,KAAK;AAAA,MACjE,CAAC;AAAA,IACH;AAAA,EACF,OAAO;AACL,UAAM,YAAY,qBAAqB,OAAO;AAC9C,QAAI,WAAW;AACb,cAAQ,KAAK,CAAC,oBAAoB,SAAS,CAAC;AAAA,IAC9C;AAEA,UAAM,aAAa,gBAAgB,OAAO;AAC1C,QAAI,YAAY;AACd,cAAQ,KAAK,CAAC,eAAe,UAAU,CAAC;AAAA,IAC1C;AAEA,UAAMA,SAAQ,WAAW,SAAS,IAAI,WAAW,KAAK;AACtD,QAAIA,QAAO;AACT,sBAAgB,SAASA,QAAO,KAAK,UAAU;AAAA,IACjD;AAEA,UAAM,OAAO,QAAQ;AACrB,QAAI,KAAK,WAAW,iBAAiB,GAAG;AACtC,cAAQ,KAAK,CAAC,cAAc,uBAAuB,IAAI,EAAE,CAAC;AAAA,IAC5D;AAAA,EACF;AAEA,SAAO;AACT;AAKO,SAAS,qBACd,SACA,WACA,gBACA,KACA,YAC6B;AAC7B,QAAM,aAAa,OAAO;AAAA,IACxB;AAAA,IACA,WAAW;AAAA,IACX,WAAW,eAAe,YAAY,EAAE,SAAS,aAAa;AAAA,EAChE;AAEA,QAAM,iBAAiB,2BAA2B,SAAS,YAAY,gBAAgB,UAAU;AACjG,QAAM,kBAAkB,4BAA4B,SAAS,YAAY,gBAAgB,UAAU;AAEnG,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,UAAuC,CAAC;AAE9C,aAAW,WAAW,CAAC,GAAG,gBAAgB,GAAG,eAAe,GAAG;AAC7D,QAAI,CAAC,KAAK,IAAI,QAAQ,CAAC,CAAC,GAAG;AACzB,WAAK,IAAI,QAAQ,CAAC,CAAC;AACnB,cAAQ,KAAK,OAAO;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAiBO,SAAS,iBAAiB,UAA+D;AAC9F,QAAM,SAAiC,CAAC;AACxC,aAAW,CAAC,UAAU,KAAK,KAAK,UAAU;AACxC,QAAI,CAAC,OAAO,QAAQ,GAAG;AACrB,aAAO,QAAQ,IAAI;AAAA,IACrB;AAAA,EACF;AACA,SAAO;AACT;;;ACldA,SAAS,YACP,SACA,UACyD;AACzD,SAAO,aAAa,YAChB,mBAAmB,QAAQ,WAAW,UAAU,EAAE,IAClD,eAAe,QAAQ,UAAU;AACvC;AAKA,SAAS,iBACP,QACA,UACS;AACT,SACE,OAAO,KAAK,KACZ,OAAO,KAAK,KACZ,OAAO,QAAQ,KACf,OAAO,SAAS,KAChB,OAAO,IAAI,OAAO,SAAS,SAAS,SACpC,OAAO,IAAI,OAAO,UAAU,SAAS;AAEzC;AAKA,SAAS,iBACP,SACA,UACA,KACqB;AACrB,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,YAAY,SAAS,IAAI,QAAQ;AAEhD,SAAO;AAAA,IACL,SAAS,QAAQ;AAAA,IACjB,UAAU,iBAAiB,QAAQ;AAAA,IACnC,MAAM,MAAM,QAAQ,MAAM,SAAS;AAAA,IACnC,aAAa,MAAM,cAAc,KAAK;AAAA,IACtC,YAAY,MAAM,aAAa,KAAK;AAAA,IACpC,iBAAiB,MAAM,QAAQ,MAAM,cAAc,KAAK;AAAA,IACxD,OAAO,MAAM,SAAS;AAAA,IACtB,OAAO,MAAM,SAAS;AAAA,IACtB,WAAW,MAAM,SAAS,QAAQ;AAAA,IAClC,WAAW,MAAM,cAAc,UAAU,MAAM,eAAe,UAAU,MAAM,gBAAgB,MAAM;AAAA,IACpG,SAAS,MAAM,YAAY;AAAA,IAC3B,WAAW,IAAI,aAAa,YAAY,MAAM,cAAc,UAAU,MAAM,YAAY;AAAA,IACxF;AAAA,IACA,cAAc,iBAAiB,QAAQ,IAAI,YAAY;AAAA,EACzD;AACF;AAKA,SAAS,cAAc,SAAsB,KAAiC;AAC5E,MAAI,qBAAqB,SAAS,IAAI,SAAS,IAAI,UAAU,IAAI,cAAc,GAAG;AAChF,WAAO;AAAA,EACT;AACA,SAAO,kBAAkB,SAAS,IAAI,QAAQ,KAAK,qBAAqB,SAAS,IAAI,QAAQ;AAC/F;AAKA,SAAS,eAAe,SAAsB,KAA8B;AAC1E,MAAI,CAAC,cAAc,SAAS,GAAG,EAAG;AAElC,MAAI;AACF,UAAM,aAAa,IAAI,YAAY,kBAAkB,IAAI,WAAW,QAAQ,IAAI,IAAI;AAEpF,UAAM,WAAW;AAAA,MACf;AAAA,MACA,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,EAAE,WAAW,IAAI,WAAW,WAAW,IAAI,WAAW,WAAW,IAAI,aAAa,UAAU;AAAA,MAC5F,cAAc;AAAA,IAChB;AACA,QAAI,SAAS,WAAW,EAAG;AAE3B,UAAM,cAAc,iBAAiB,SAAS,UAAU,GAAG;AAC3D,QAAI,OAAO,KAAK,YAAY,QAAQ,EAAE,WAAW,EAAG;AAEpD,QAAI,QAAQ,KAAK,WAAW;AAAA,EAC9B,SAAS,OAAO;AACd,YAAQ,MAAM,kCAAkC,QAAQ,IAAI,KAAK,KAAK;AAAA,EACxE;AACF;AAKA,SAAS,aAAa,SAA6B,KAA8B;AAC/E,MAAI,CAAC,QAAS;AAEd,iBAAe,SAAS,GAAG;AAE3B,aAAW,SAAS,QAAQ,YAAY,CAAC,GAAG;AAC1C,iBAAa,OAAO,GAAG;AAAA,EACzB;AACF;AAKO,SAAS,2BACd,WACA,SACuB;AACvB,QAAM,aAAa,UAAU,SAAS;AAEtC,MAAI,CAAC,YAAY;AACf,YAAQ,MAAM,8DAA8D;AAC5E,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAY,SAAS,SAAS;AAEpC,QAAM,MAAyB;AAAA,IAC7B;AAAA,IACA,UAAU,QAAQ;AAAA,IAClB,gBAAgB,QAAQ,aAAa,YAAY,iBAAiB;AAAA,IAClE,UAAU,QAAQ,YAAY;AAAA,IAC9B,cAAc,QAAQ,gBAAgB,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,IAClE,SAAS,QAAQ,WAAW,CAAC;AAAA,IAC7B,SAAS,CAAC;AAAA,IACV;AAAA,EACF;AAEA,eAAa,YAAY,GAAG;AAE5B,SAAO,IAAI;AACb;;;ACtLA,IAAM,mBAAsC;AAAA,EAC1C;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA;AAEF;AAMA,SAAS,mBAAmB,UAA4C;AACtE,QAAM,WAAqB,CAAC;AAG5B,aAAW,YAAY,kBAAkB;AACvC,QAAI,SAAS,QAAQ,GAAG;AACtB,eAAS,KAAK,SAAS,QAAQ,CAAC;AAChC;AAAA,IACF;AAAA,EACF;AAGA,aAAW,YAAY,kBAAkB;AACvC,QAAI,SAAS,QAAQ,KAAK,CAAC,SAAS,SAAS,SAAS,QAAQ,CAAC,GAAG;AAChE,eAAS,KAAK,SAAS,QAAQ,CAAC;AAChC;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAMA,SAAS,oBAAoB,SAA8B,eAA2C;AACpG,QAAM,mBAAmB,mBAAmB,QAAQ,QAAQ;AAG5D,QAAM,WAAW,QAAQ,mBAAmB,QAAQ;AAIpD,QAAM,OAA0B;AAAA,IAC9B,UAAU,iBAAiB,CAAC,KAAK;AAAA,IACjC,SAAS,QAAQ;AAAA,IACjB,cAAc,QAAQ;AAAA,IACtB,MAAM,QAAQ,QAAQ;AAAA,IACtB,YAAY,QAAQ,cAAc;AAAA,IAClC,iBAAiB,YAAY;AAAA,IAC7B,WAAW,QAAQ,YAAY;AAAA,IAC/B,aAAa,iBAAiB,CAAC,KAAK;AAAA;AAAA,EACtC;AAGA,MAAI,eAAe;AACjB,SAAK,SAAS,QAAQ;AAAA,EACxB;AAEA,SAAO;AACT;AAKA,eAAe,gBAAgB,SAA0E;AACvG,MAAI;AACF,UAAM,OAAO,MAAM,QAAQ,cAAc;AACzC,WAAO,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAAA,EAClD,QAAQ;AACN,WAAO,EAAE,OAAO,MAAM,QAAQ,KAAK;AAAA,EACrC;AACF;AAOA,eAAsB,yBACpB,SACA,UACA,UAAoC,CAAC,GACP;AAC9B,QAAM,EAAE,oBAAoB,OAAO,gBAAgB,OAAO,cAAc,IAAI;AAE5E,QAAM,eAAe,MAAM,gBAAgB,OAAO;AAClD,QAAM,aAAa,MAAM,QAAQ,cAAc;AAE/C,QAAM,UAAyB;AAAA,IAC7B,GAAG,kBAAkB,UAAU,iBAAiB;AAAA,IAChD,GAAG;AAAA,EACL;AAEA,QAAM,WAAW,2BAA2B,YAAY;AAAA,IACtD;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,SAAS,IAAI,CAAC,OAAO,oBAAoB,IAAI,aAAa,CAAC;AACpE;","names":["xpath"]}
1
+ {"version":3,"sources":["../src/scripts/get-interactable-browser-elements.ts","../src/scripts/get-browser-accessibility-tree.ts","../src/locators/constants.ts","../src/locators/xml-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/index.ts","../src/scripts/get-visible-mobile-elements.ts"],"sourcesContent":["/**\n * Browser element detection\n * Single browser.execute() call: querySelectorAll → flat interactable element list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface BrowserElementInfo {\n tagName: string;\n name: string; // computed accessible name (ARIA spec)\n type: string;\n value: string;\n href: string;\n selector: string;\n isInViewport: boolean;\n boundingBox?: { x: number; y: number; width: number; height: number };\n}\n\nexport interface GetBrowserElementsOptions {\n includeBounds?: boolean;\n}\n\nconst elementsScript = (includeBounds: boolean) => (function () {\n const interactableSelectors = [\n 'a[href]',\n 'button',\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"combobox\"]',\n '[role=\"option\"]',\n '[role=\"switch\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"searchbox\"]',\n '[role=\"spinbutton\"]',\n '[contenteditable=\"true\"]',\n '[tabindex]:not([tabindex=\"-1\"])',\n ].join(',');\n\n function isVisible(element: HTMLElement): boolean {\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(element);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n element.offsetWidth > 0 &&\n element.offsetHeight > 0;\n }\n\n function getAccessibleName(el: HTMLElement): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n // 2. aria-labelledby — resolve referenced elements\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n // 3. alt for images and input[type=image]\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n // 4. label[for=id] for form elements\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n // 5. Wrapping label — clone, strip inputs, read text\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n // 6. placeholder\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n // 7. title\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n // 8. text content (truncated, whitespace normalized)\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n // 1. tag*=Text — best per WebdriverIO docs\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => {\n if (el.textContent?.includes(text)) matchCount++;\n });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n // 2. aria/label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n // 3. data-testid\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 4. #id\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n // 5. [name] — form elements\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 6. tag.class — try each class individually, then first-two combination\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n // 7. CSS path fallback\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) {\n path.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n const elements: Record<string, unknown>[] = [];\n const seen = new Set<Element>();\n\n document.querySelectorAll(interactableSelectors).forEach((el) => {\n if (seen.has(el)) return;\n seen.add(el);\n\n const htmlEl = el as HTMLElement;\n if (!isVisible(htmlEl)) return;\n\n const inputEl = htmlEl as HTMLInputElement;\n const rect = htmlEl.getBoundingClientRect();\n const isInViewport = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n\n const entry: Record<string, unknown> = {\n tagName: htmlEl.tagName.toLowerCase(),\n name: getAccessibleName(htmlEl),\n type: htmlEl.getAttribute('type') || '',\n value: inputEl.value || '',\n href: htmlEl.getAttribute('href') || '',\n selector: getSelector(htmlEl),\n isInViewport,\n };\n\n if (includeBounds) {\n entry.boundingBox = {\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n };\n }\n\n elements.push(entry);\n });\n\n return elements;\n})();\n\n/**\n * Get interactable browser elements via querySelectorAll.\n */\nexport async function getInteractableBrowserElements(\n browser: WebdriverIO.Browser,\n options: GetBrowserElementsOptions = {},\n): Promise<BrowserElementInfo[]> {\n const { includeBounds = false } = options;\n return (browser as any).execute(elementsScript, includeBounds) as unknown as Promise<BrowserElementInfo[]>;\n}\n\nexport default elementsScript;\n","/**\n * Browser accessibility tree\n * Single browser.execute() call: DOM walk → flat accessibility node list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface AccessibilityNode {\n role: string;\n name: string;\n selector: string;\n level: number | string;\n disabled: string;\n checked: string;\n expanded: string;\n selected: string;\n pressed: string;\n required: string;\n readonly: string;\n}\n\nconst accessibilityTreeScript = () => (function () {\n\n const INPUT_TYPE_ROLES: Record<string, string> = {\n text: 'textbox', search: 'searchbox', email: 'textbox', url: 'textbox',\n tel: 'textbox', password: 'textbox', number: 'spinbutton',\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n submit: 'button', reset: 'button', image: 'button', file: 'button', color: 'button',\n };\n\n const LANDMARK_ROLES = new Set([\n 'navigation', 'main', 'banner', 'contentinfo', 'complementary', 'form', 'dialog', 'region',\n ]);\n\n // Container roles: named only via aria-label/aria-labelledby, not textContent\n const CONTAINER_ROLES = new Set([\n 'navigation', 'banner', 'contentinfo', 'complementary', 'main', 'form',\n 'region', 'group', 'list', 'listitem', 'table', 'row', 'rowgroup', 'generic',\n ]);\n\n function getRole(el: HTMLElement): string | null {\n const explicit = el.getAttribute('role');\n if (explicit) return explicit.split(' ')[0];\n\n const tag = el.tagName.toLowerCase();\n\n switch (tag) {\n case 'button': return 'button';\n case 'a': return el.hasAttribute('href') ? 'link' : null;\n case 'input': {\n const type = (el.getAttribute('type') || 'text').toLowerCase();\n if (type === 'hidden') return null;\n return INPUT_TYPE_ROLES[type] || 'textbox';\n }\n case 'select': return 'combobox';\n case 'textarea': return 'textbox';\n case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': return 'heading';\n case 'img': return 'img';\n case 'nav': return 'navigation';\n case 'main': return 'main';\n case 'header': return !el.closest('article,aside,main,nav,section') ? 'banner' : null;\n case 'footer': return !el.closest('article,aside,main,nav,section') ? 'contentinfo' : null;\n case 'aside': return 'complementary';\n case 'dialog': return 'dialog';\n case 'form': return 'form';\n case 'section': return (el.hasAttribute('aria-label') || el.hasAttribute('aria-labelledby')) ? 'region' : null;\n case 'summary': return 'button';\n case 'details': return 'group';\n case 'progress': return 'progressbar';\n case 'meter': return 'meter';\n case 'ul': case 'ol': return 'list';\n case 'li': return 'listitem';\n case 'table': return 'table';\n }\n\n if ((el as HTMLElement & { contentEditable: string }).contentEditable === 'true') return 'textbox';\n if (el.hasAttribute('tabindex') && parseInt(el.getAttribute('tabindex') || '-1', 10) >= 0) return 'generic';\n\n return null;\n }\n\n function getAccessibleName(el: HTMLElement, role: string | null): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n if (role && CONTAINER_ROLES.has(role)) return '';\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => { if (el.textContent?.includes(text)) matchCount++; });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) { path.unshift(`#${CSS.escape(current.id)}`); break; }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n function isVisible(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === 'function') {\n return el.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(el);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n el.offsetWidth > 0 &&\n el.offsetHeight > 0;\n }\n\n function getLevel(el: HTMLElement): number | undefined {\n const m = el.tagName.toLowerCase().match(/^h([1-6])$/);\n if (m) return parseInt(m[1], 10);\n const ariaLevel = el.getAttribute('aria-level');\n if (ariaLevel) return parseInt(ariaLevel, 10);\n return undefined;\n }\n\n function getState(el: HTMLElement): Record<string, string> {\n const inputEl = el as HTMLInputElement;\n const isCheckable = ['input', 'menuitemcheckbox', 'menuitemradio'].includes(el.tagName.toLowerCase()) ||\n ['checkbox', 'radio', 'switch'].includes(el.getAttribute('role') || '');\n return {\n disabled: (el.getAttribute('aria-disabled') === 'true' || inputEl.disabled) ? 'true' : '',\n checked: (isCheckable && inputEl.checked) ? 'true' : el.getAttribute('aria-checked') || '',\n expanded: el.getAttribute('aria-expanded') || '',\n selected: el.getAttribute('aria-selected') || '',\n pressed: el.getAttribute('aria-pressed') || '',\n required: (inputEl.required || el.getAttribute('aria-required') === 'true') ? 'true' : '',\n readonly: (inputEl.readOnly || el.getAttribute('aria-readonly') === 'true') ? 'true' : '',\n };\n }\n\n type RawNode = Record<string, unknown>;\n\n const result: RawNode[] = [];\n\n function walk(el: HTMLElement, depth = 0): void {\n if (depth > 200) return;\n if (!isVisible(el)) return;\n\n const role = getRole(el);\n\n if (!role) {\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n return;\n }\n\n const name = getAccessibleName(el, role);\n const isLandmark = LANDMARK_ROLES.has(role);\n const hasIdentity = !!(name || isLandmark);\n const selector = hasIdentity ? getSelector(el) : '';\n const node: RawNode = { role, name, selector, level: getLevel(el) ?? '', ...getState(el) };\n result.push(node);\n\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n }\n\n for (const child of Array.from(document.body.children)) {\n walk(child as HTMLElement, 0);\n }\n\n return result;\n})();\n\n/**\n * Get browser accessibility tree via a single DOM walk.\n */\nexport async function getBrowserAccessibilityTree(\n browser: WebdriverIO.Browser,\n): Promise<AccessibilityNode[]> {\n return (browser as any).execute(accessibilityTreeScript) as unknown as Promise<AccessibilityNode[]>;\n}\n","/**\n * Platform-specific element tag constants for mobile automation\n */\n\nexport const ANDROID_INTERACTABLE_TAGS = [\n // Input elements\n 'android.widget.EditText',\n 'android.widget.AutoCompleteTextView',\n 'android.widget.MultiAutoCompleteTextView',\n 'android.widget.SearchView',\n\n // Button-like elements\n 'android.widget.Button',\n 'android.widget.ImageButton',\n 'android.widget.ToggleButton',\n 'android.widget.CompoundButton',\n 'android.widget.RadioButton',\n 'android.widget.CheckBox',\n 'android.widget.Switch',\n 'android.widget.FloatingActionButton',\n 'com.google.android.material.button.MaterialButton',\n 'com.google.android.material.floatingactionbutton.FloatingActionButton',\n\n // Text elements (often tappable)\n 'android.widget.TextView',\n 'android.widget.CheckedTextView',\n\n // Image elements (often tappable)\n 'android.widget.ImageView',\n 'android.widget.QuickContactBadge',\n\n // Selection elements\n 'android.widget.Spinner',\n 'android.widget.SeekBar',\n 'android.widget.RatingBar',\n 'android.widget.ProgressBar',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.NumberPicker',\n\n // List/grid items\n 'android.widget.AdapterView',\n];\n\nexport const ANDROID_LAYOUT_CONTAINERS = [\n // Core ViewGroup classes\n 'android.view.ViewGroup',\n 'android.view.View',\n 'android.widget.FrameLayout',\n 'android.widget.LinearLayout',\n 'android.widget.RelativeLayout',\n 'android.widget.GridLayout',\n 'android.widget.TableLayout',\n 'android.widget.TableRow',\n 'android.widget.AbsoluteLayout',\n\n // AndroidX layout classes\n 'androidx.constraintlayout.widget.ConstraintLayout',\n 'androidx.coordinatorlayout.widget.CoordinatorLayout',\n 'androidx.appcompat.widget.LinearLayoutCompat',\n 'androidx.cardview.widget.CardView',\n 'androidx.appcompat.widget.ContentFrameLayout',\n 'androidx.appcompat.widget.FitWindowsFrameLayout',\n\n // Scrolling containers\n 'android.widget.ScrollView',\n 'android.widget.HorizontalScrollView',\n 'android.widget.NestedScrollView',\n 'androidx.core.widget.NestedScrollView',\n 'androidx.recyclerview.widget.RecyclerView',\n 'android.widget.ListView',\n 'android.widget.GridView',\n 'android.widget.AbsListView',\n\n // App chrome / system elements\n 'android.widget.ActionBarContainer',\n 'android.widget.ActionBarOverlayLayout',\n 'android.view.ViewStub',\n 'androidx.appcompat.widget.ActionBarContainer',\n 'androidx.appcompat.widget.ActionBarContextView',\n 'androidx.appcompat.widget.ActionBarOverlayLayout',\n\n // Decor views\n 'com.android.internal.policy.DecorView',\n 'android.widget.DecorView',\n];\n\nexport const IOS_INTERACTABLE_TAGS = [\n // Input elements\n 'XCUIElementTypeTextField',\n 'XCUIElementTypeSecureTextField',\n 'XCUIElementTypeTextView',\n 'XCUIElementTypeSearchField',\n\n // Button-like elements\n 'XCUIElementTypeButton',\n 'XCUIElementTypeLink',\n\n // Text elements (often tappable)\n 'XCUIElementTypeStaticText',\n\n // Image elements\n 'XCUIElementTypeImage',\n 'XCUIElementTypeIcon',\n\n // Selection elements\n 'XCUIElementTypeSwitch',\n 'XCUIElementTypeSlider',\n 'XCUIElementTypeStepper',\n 'XCUIElementTypeSegmentedControl',\n 'XCUIElementTypePicker',\n 'XCUIElementTypePickerWheel',\n 'XCUIElementTypeDatePicker',\n 'XCUIElementTypePageIndicator',\n\n // Table/list items\n 'XCUIElementTypeCell',\n 'XCUIElementTypeMenuItem',\n 'XCUIElementTypeMenuBarItem',\n\n // Toggle elements\n 'XCUIElementTypeCheckBox',\n 'XCUIElementTypeRadioButton',\n 'XCUIElementTypeToggle',\n\n // Other interactive\n 'XCUIElementTypeKey',\n 'XCUIElementTypeKeyboard',\n 'XCUIElementTypeAlert',\n 'XCUIElementTypeSheet',\n];\n\nexport const IOS_LAYOUT_CONTAINERS = [\n // Generic containers\n 'XCUIElementTypeOther',\n 'XCUIElementTypeGroup',\n 'XCUIElementTypeLayoutItem',\n\n // Scroll containers\n 'XCUIElementTypeScrollView',\n 'XCUIElementTypeTable',\n 'XCUIElementTypeCollectionView',\n 'XCUIElementTypeScrollBar',\n\n // Navigation chrome\n 'XCUIElementTypeNavigationBar',\n 'XCUIElementTypeTabBar',\n 'XCUIElementTypeToolbar',\n 'XCUIElementTypeStatusBar',\n 'XCUIElementTypeMenuBar',\n\n // Windows and views\n 'XCUIElementTypeWindow',\n 'XCUIElementTypeSheet',\n 'XCUIElementTypeDrawer',\n 'XCUIElementTypeDialog',\n 'XCUIElementTypePopover',\n 'XCUIElementTypePopUpButton',\n\n // Outline elements\n 'XCUIElementTypeOutline',\n 'XCUIElementTypeOutlineRow',\n 'XCUIElementTypeBrowser',\n 'XCUIElementTypeSplitGroup',\n 'XCUIElementTypeSplitter',\n\n // Application root\n 'XCUIElementTypeApplication',\n];\n","/**\n * XML parsing utilities for mobile element source\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport xpath from 'xpath';\nimport type { ElementAttributes, JSONElement, Bounds, UniquenessResult } from './types';\n\n/**\n * Get child nodes that are elements (not text nodes, comments, etc.)\n */\nfunction childNodesOf(node: Node): Node[] {\n const children: Node[] = [];\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n return children;\n}\n\n/**\n * Recursively translate DOM node to JSONElement\n */\nfunction translateRecursively(\n domNode: Node,\n parentPath: string = '',\n index: number | null = null,\n): JSONElement {\n const attributes: ElementAttributes = {};\n\n const element = domNode as Element;\n if (element.attributes) {\n for (let attrIdx = 0; attrIdx < element.attributes.length; attrIdx++) {\n const attr = element.attributes.item(attrIdx);\n if (attr) {\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n const path = index === null ? '' : `${parentPath ? parentPath + '.' : ''}${index}`;\n\n return {\n children: childNodesOf(domNode).map((childNode, childIndex) =>\n translateRecursively(childNode, path, childIndex),\n ),\n tagName: domNode.nodeName,\n attributes,\n path,\n };\n}\n\n/**\n * Compare two nodes for equality by platform-specific attributes\n * (reference equality via === may fail when nodes come from different traversals)\n */\nfunction isSameElement(node1: Node, node2: Node): boolean {\n if (node1.nodeType !== 1 || node2.nodeType !== 1) return false;\n const el1 = node1 as Element;\n const el2 = node2 as Element;\n\n if (el1.nodeName !== el2.nodeName) return false;\n\n // For Android, compare by bounds (unique per element)\n const bounds1 = el1.getAttribute('bounds');\n const bounds2 = el2.getAttribute('bounds');\n if (bounds1 && bounds2) {\n return bounds1 === bounds2;\n }\n\n // For iOS, compare by x, y, width, height\n const x1 = el1.getAttribute('x');\n const y1 = el1.getAttribute('y');\n const x2 = el2.getAttribute('x');\n const y2 = el2.getAttribute('y');\n if (x1 && y1 && x2 && y2) {\n return (\n x1 === x2 &&\n y1 === y2 &&\n el1.getAttribute('width') === el2.getAttribute('width') &&\n el1.getAttribute('height') === el2.getAttribute('height')\n );\n }\n\n return false;\n}\n\n/**\n * Convert XML page source to JSON tree structure\n */\nexport function xmlToJSON(sourceXML: string): JSONElement | null {\n try {\n const parser = new DOMParser();\n const sourceDoc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = sourceDoc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToJSON] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n const children = childNodesOf(sourceDoc);\n const firstChild =\n children[0] ||\n (sourceDoc.documentElement ? childNodesOf(sourceDoc.documentElement)[0] : null);\n\n return firstChild\n ? translateRecursively(firstChild)\n : { children: [], tagName: '', attributes: {}, path: '' };\n } catch (e) {\n console.error('[xmlToJSON] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Parse XML source to DOM Document for XPath evaluation\n */\nexport function xmlToDOM(sourceXML: string): Document | null {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = doc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToDOM] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n return doc;\n } catch (e) {\n console.error('[xmlToDOM] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Execute XPath query on DOM document\n */\nexport function evaluateXPath(doc: Document, xpathExpr: string): Node[] {\n try {\n const nodes = xpath.select(xpathExpr, doc);\n if (Array.isArray(nodes)) {\n return nodes as Node[];\n }\n return [];\n } catch (e) {\n console.error(`[evaluateXPath] Failed to evaluate \"${xpathExpr}\":`, e);\n return [];\n }\n}\n\n/**\n * Check if an XPath selector is unique and get index if not\n */\nexport function checkXPathUniqueness(\n doc: Document,\n xpathExpr: string,\n targetNode?: Node,\n): UniquenessResult {\n try {\n const nodes = evaluateXPath(doc, xpathExpr);\n const totalMatches = nodes.length;\n\n if (totalMatches === 0) {\n return { isUnique: false };\n }\n\n if (totalMatches === 1) {\n return { isUnique: true };\n }\n\n // Not unique - find index of target node if provided\n if (targetNode) {\n for (let i = 0; i < nodes.length; i++) {\n if (nodes[i] === targetNode || isSameElement(nodes[i], targetNode)) {\n return {\n isUnique: false,\n index: i + 1, // 1-based index for XPath\n totalMatches,\n };\n }\n }\n }\n\n return { isUnique: false, totalMatches };\n } catch (e) {\n console.error(`[checkXPathUniqueness] Error checking \"${xpathExpr}\":`, e);\n return { isUnique: false };\n }\n}\n\n/**\n * Find DOM node by JSONElement path (e.g., \"0.2.1\")\n */\nexport function findDOMNodeByPath(doc: Document, path: string): Node | null {\n if (!path) return doc.documentElement;\n\n const indices = path.split('.').map(Number);\n let current: Node | null = doc.documentElement;\n\n for (const index of indices) {\n if (!current) return null;\n\n const children: Node[] = [];\n if (current.childNodes) {\n for (let i = 0; i < current.childNodes.length; i++) {\n const child = current.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n\n current = children[index] || null;\n }\n\n return current;\n}\n\n/**\n * Parse Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n */\nexport function parseAndroidBounds(bounds: string): Bounds {\n const match = bounds.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n const x1 = parseInt(match[1], 10);\n const y1 = parseInt(match[2], 10);\n const x2 = parseInt(match[3], 10);\n const y2 = parseInt(match[4], 10);\n\n return {\n x: x1,\n y: y1,\n width: x2 - x1,\n height: y2 - y1,\n };\n}\n\n/**\n * Parse iOS element bounds from individual x, y, width, height attributes\n */\nexport function parseIOSBounds(attributes: ElementAttributes): Bounds {\n return {\n x: parseInt(attributes.x || '0', 10),\n y: parseInt(attributes.y || '0', 10),\n width: parseInt(attributes.width || '0', 10),\n height: parseInt(attributes.height || '0', 10),\n };\n}\n\n/**\n * Flatten JSON element tree to array (depth-first)\n */\nexport function flattenElementTree(root: JSONElement): JSONElement[] {\n const result: JSONElement[] = [];\n\n function traverse(element: JSONElement) {\n result.push(element);\n for (const child of element.children) {\n traverse(child);\n }\n }\n\n traverse(root);\n return result;\n}\n\n/**\n * Count occurrences of an attribute value in the source XML\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`${attribute}=[\"']${escapedValue}[\"']`, 'g');\n const matches = sourceXML.match(pattern);\n return matches ? matches.length : 0;\n}\n\n/**\n * Check if an attribute value is unique in the source (fast regex-based check)\n */\nexport function isAttributeUnique(\n sourceXML: string,\n attribute: string,\n value: string,\n): boolean {\n return countAttributeOccurrences(sourceXML, attribute, value) === 1;\n}\n","/**\n * Element filtering logic for mobile automation\n */\n\nimport type { JSONElement, FilterOptions } from './types';\nimport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n if (tagList.includes(tagName)) {\n return true;\n }\n\n for (const tag of tagList) {\n if (tagName.endsWith(tag) || tagName.includes(tag)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element matches tag name filters\n */\nfunction matchesTagFilters(\n element: JSONElement,\n includeTagNames: string[],\n excludeTagNames: string[],\n): boolean {\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n if (matchesTagList(element.tagName, excludeTagNames)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if element matches attribute-based filters\n */\nfunction matchesAttributeFilters(\n element: JSONElement,\n requireAttributes: string[],\n minAttributeCount: number,\n): boolean {\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n if (element.attributes && minAttributeCount > 0) {\n const attrCount = Object.values(element.attributes).filter(\n (v) => v !== undefined && v !== null && v !== '',\n ).length;\n if (attrCount < minAttributeCount) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if element is interactable based on platform\n */\nexport function isInteractableElement(\n element: JSONElement,\n isNative: boolean,\n automationName: string,\n): boolean {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n if (isAndroid) {\n if (\n element.attributes?.clickable === 'true' ||\n element.attributes?.focusable === 'true' ||\n element.attributes?.checkable === 'true' ||\n element.attributes?.['long-clickable'] === 'true'\n ) {\n return true;\n }\n }\n\n if (!isAndroid) {\n if (element.attributes?.accessible === 'true') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element is a layout container\n */\nexport function isLayoutContainer(element: JSONElement, platform: 'android' | 'ios'): boolean {\n const containerList = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n return matchesTagList(element.tagName, containerList);\n}\n\n/**\n * Check if element has meaningful content (text, accessibility info)\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n if (attrs.label && attrs.label.trim() !== '' && attrs.label !== 'null') {\n return true;\n }\n if (attrs.name && attrs.name.trim() !== '' && attrs.name !== 'null') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Determine if an element should be included based on all filter criteria\n */\nexport function shouldIncludeElement(\n element: JSONElement,\n filters: FilterOptions,\n isNative: boolean,\n automationName: string,\n): boolean {\n const {\n includeTagNames = [],\n excludeTagNames = ['hierarchy'],\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n if (visibleOnly) {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n if (isAndroid && element.attributes?.displayed === 'false') {\n return false;\n }\n if (!isAndroid && element.attributes?.visible === 'false') {\n return false;\n }\n }\n\n if (fetchableOnly && !isInteractableElement(element, isNative, automationName)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get default filter options for a platform\n */\nexport function getDefaultFilters(\n platform: 'android' | 'ios',\n includeContainers: boolean = false,\n): FilterOptions {\n const layoutContainers = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n\n return {\n excludeTagNames: includeContainers ? ['hierarchy'] : ['hierarchy', ...layoutContainers],\n fetchableOnly: !includeContainers,\n visibleOnly: true,\n clickableOnly: false,\n };\n}\n","/**\n * Locator strategy generation for mobile elements\n */\n\nimport type { JSONElement, LocatorStrategy, LocatorContext, UniquenessResult } from './types';\nimport { checkXPathUniqueness, evaluateXPath, isAttributeUnique } from './xml-parsing';\n\n/**\n * Check if a string value is valid for use in a locator\n */\nfunction isValidValue(value: string | undefined): value is string {\n return value !== undefined && value !== null && value !== 'null' && value.trim() !== '';\n}\n\n/**\n * Escape special characters in text for use in selectors\n */\nfunction escapeText(text: string): string {\n return text.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Escape value for use in XPath expressions\n */\nfunction escapeXPathValue(value: string): string {\n if (!value.includes(\"'\")) {\n return `'${value}'`;\n }\n if (!value.includes('\"')) {\n return `\"${value}\"`;\n }\n const parts: string[] = [];\n let current = '';\n for (const char of value) {\n if (char === \"'\") {\n if (current) parts.push(`'${current}'`);\n parts.push('\"\\'\"');\n current = '';\n } else {\n current += char;\n }\n }\n if (current) parts.push(`'${current}'`);\n return `concat(${parts.join(',')})`;\n}\n\n/**\n * Wrap non-unique XPath with index\n */\nfunction generateIndexedXPath(baseXPath: string, index: number): string {\n return `(${baseXPath})[${index}]`;\n}\n\n/**\n * Add .instance(n) for UiAutomator (0-based)\n */\nfunction generateIndexedUiAutomator(baseSelector: string, index: number): string {\n return `${baseSelector}.instance(${index - 1})`;\n}\n\n/**\n * Check uniqueness, falling back to regex if no DOM available\n */\nfunction checkUniqueness(\n ctx: LocatorContext,\n xpath: string,\n targetNode?: Node,\n): UniquenessResult {\n if (ctx.parsedDOM) {\n return checkXPathUniqueness(ctx.parsedDOM, xpath, targetNode);\n }\n\n const match = xpath.match(/\\/\\/\\*\\[@([^=]+)=\"([^\"]+)\"\\]/);\n if (match) {\n const [, attr, value] = match;\n return { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n }\n return { isUnique: false };\n}\n\n/**\n * Get sibling index (1-based) among same-tag siblings\n */\nfunction getSiblingIndex(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let index = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n index++;\n if (child === element) return index;\n }\n }\n\n return 1;\n}\n\n/**\n * Count siblings with same tag name\n */\nfunction countSiblings(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let count = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n count++;\n }\n }\n\n return count;\n}\n\n/**\n * Find unique attribute for element in XPath format\n */\nfunction findUniqueAttribute(element: Element, ctx: LocatorContext): string | null {\n const attrs = ctx.isAndroid\n ? ['resource-id', 'content-desc', 'text']\n : ['name', 'label', 'value'];\n\n for (const attr of attrs) {\n const value = element.getAttribute(attr);\n if (value && value.trim()) {\n const xpath = `//*[@${attr}=${escapeXPathValue(value)}]`;\n const result = ctx.parsedDOM\n ? checkXPathUniqueness(ctx.parsedDOM, xpath)\n : { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n\n if (result.isUnique) {\n return `@${attr}=${escapeXPathValue(value)}`;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build hierarchical XPath by traversing up the DOM tree\n */\nfunction buildHierarchicalXPath(\n ctx: LocatorContext,\n element: Element,\n maxDepth: number = 3,\n): string | null {\n if (!ctx.parsedDOM) return null;\n\n const pathParts: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n const tagName = current.nodeName;\n const uniqueAttr = findUniqueAttribute(current, ctx);\n\n if (uniqueAttr) {\n pathParts.unshift(`//${tagName}[${uniqueAttr}]`);\n break;\n } else {\n const siblingIndex = getSiblingIndex(current);\n const siblingCount = countSiblings(current);\n\n if (siblingCount > 1) {\n pathParts.unshift(`${tagName}[${siblingIndex}]`);\n } else {\n pathParts.unshift(tagName);\n }\n }\n\n const parent = current.parentNode as Element | null;\n current = parent && parent.nodeType === 1 ? parent : null;\n depth++;\n }\n\n if (pathParts.length === 0) return null;\n\n let result = pathParts[0];\n for (let i = 1; i < pathParts.length; i++) {\n result += '/' + pathParts[i];\n }\n\n if (!result.startsWith('//')) {\n result = '//' + result;\n }\n\n return result;\n}\n\n/**\n * Add XPath locator with uniqueness checking and fallbacks\n */\nfunction addXPathLocator(\n results: [LocatorStrategy, string][],\n xpath: string,\n ctx: LocatorContext,\n targetNode?: Node,\n): void {\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n if (uniqueness.isUnique) {\n results.push(['xpath', xpath]);\n } else if (uniqueness.index) {\n results.push(['xpath', generateIndexedXPath(xpath, uniqueness.index)]);\n } else {\n if (targetNode && ctx.parsedDOM) {\n const hierarchical = buildHierarchicalXPath(ctx, targetNode as Element);\n if (hierarchical) {\n results.push(['xpath', hierarchical]);\n }\n }\n results.push(['xpath', xpath]);\n }\n}\n\n/**\n * Check if element is within UiAutomator scope\n */\nfunction isInUiAutomatorScope(element: JSONElement, doc: Document | null): boolean {\n if (!doc) return true;\n\n const hierarchyNodes = evaluateXPath(doc, '/hierarchy/*');\n if (hierarchyNodes.length === 0) return true;\n\n const lastIndex = hierarchyNodes.length;\n const pathParts = element.path.split('.');\n if (pathParts.length === 0 || pathParts[0] === '') return true;\n\n const firstIndex = parseInt(pathParts[0], 10);\n return firstIndex === lastIndex - 1;\n}\n\n/**\n * Build Android UiAutomator selector with multiple attributes\n */\nfunction buildUiAutomatorSelector(element: JSONElement): string | null {\n const attrs = element.attributes;\n const parts: string[] = [];\n\n if (isValidValue(attrs['resource-id'])) {\n parts.push(`resourceId(\"${attrs['resource-id']}\")`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n parts.push(`text(\"${escapeText(attrs.text!)}\")`);\n }\n if (isValidValue(attrs['content-desc'])) {\n parts.push(`description(\"${attrs['content-desc']}\")`);\n }\n if (isValidValue(attrs.class)) {\n parts.push(`className(\"${attrs.class}\")`);\n }\n\n if (parts.length === 0) return null;\n\n return `android=new UiSelector().${parts.join('.')}`;\n}\n\n/**\n * Build iOS predicate string with multiple conditions\n */\nfunction buildPredicateString(element: JSONElement): string | null {\n const attrs = element.attributes;\n const conditions: string[] = [];\n\n if (isValidValue(attrs.name)) {\n conditions.push(`name == \"${escapeText(attrs.name!)}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`label == \"${escapeText(attrs.label!)}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`value == \"${escapeText(attrs.value!)}\"`);\n }\n if (attrs.visible === 'true') {\n conditions.push('visible == 1');\n }\n if (attrs.enabled === 'true') {\n conditions.push('enabled == 1');\n }\n\n if (conditions.length === 0) return null;\n\n return `-ios predicate string:${conditions.join(' AND ')}`;\n}\n\n/**\n * Build iOS class chain selector\n */\nfunction buildClassChain(element: JSONElement): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n if (isValidValue(attrs.label)) {\n selector += `[\\`label == \"${escapeText(attrs.label!)}\"\\`]`;\n } else if (isValidValue(attrs.name)) {\n selector += `[\\`name == \"${escapeText(attrs.name!)}\"\\`]`;\n }\n\n return `-ios class chain:${selector}`;\n}\n\n/**\n * Build XPath for element with unique identification\n */\nfunction buildXPath(element: JSONElement, sourceXML: string, isAndroid: boolean): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n const conditions: string[] = [];\n\n if (isAndroid) {\n if (isValidValue(attrs['resource-id'])) {\n conditions.push(`@resource-id=\"${attrs['resource-id']}\"`);\n }\n if (isValidValue(attrs['content-desc'])) {\n conditions.push(`@content-desc=\"${attrs['content-desc']}\"`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n conditions.push(`@text=\"${escapeText(attrs.text!)}\"`);\n }\n } else {\n if (isValidValue(attrs.name)) {\n conditions.push(`@name=\"${attrs.name}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`@label=\"${attrs.label}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`@value=\"${attrs.value}\"`);\n }\n }\n\n if (conditions.length === 0) {\n return `//${tagName}`;\n }\n\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get simple locators based on single attributes\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n // Resource ID\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId)) {\n const xpath = `//*[@resource-id=\"${resourceId}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().resourceId(\"${resourceId}\")`;\n results.push(['id', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n\n // Content Description\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc)) {\n const xpath = `//*[@content-desc=\"${contentDesc}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n }\n\n // Text\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100) {\n const xpath = `//*[@text=\"${escapeText(text)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().text(\"${escapeText(text)}\")`;\n results.push(['text', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n } else {\n // iOS: Accessibility ID (name)\n const name = attrs.name;\n if (isValidValue(name)) {\n const xpath = `//*[@name=\"${name}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${name}`]);\n }\n }\n\n // iOS: Label\n const label = attrs.label;\n if (isValidValue(label) && label !== attrs.name) {\n const xpath = `//*[@label=\"${escapeText(label)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n }\n\n // iOS: Value\n const value = attrs.value;\n if (isValidValue(value)) {\n const xpath = `//*[@value=\"${escapeText(value)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n if (inUiAutomatorScope) {\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, true);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n if (inUiAutomatorScope && isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, false);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n const type = element.tagName;\n if (type.startsWith('XCUIElementType')) {\n results.push(['class-name', `-ios class chain:**/${type}`]);\n }\n }\n\n return results;\n}\n\n/**\n * Get all suggested locators for an element\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n ctx?: LocatorContext,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const locatorCtx = ctx ?? {\n sourceXML,\n parsedDOM: null,\n isAndroid: automationName.toLowerCase().includes('uiautomator'),\n };\n\n const simpleLocators = getSimpleSuggestedLocators(element, locatorCtx, automationName, targetNode);\n const complexLocators = getComplexSuggestedLocators(element, locatorCtx, automationName, targetNode);\n\n const seen = new Set<string>();\n const results: [LocatorStrategy, string][] = [];\n\n for (const locator of [...simpleLocators, ...complexLocators]) {\n if (!seen.has(locator[1])) {\n seen.add(locator[1]);\n results.push(locator);\n }\n }\n\n return results;\n}\n\n/**\n * Get the best (first priority) locator for an element\n */\nexport function getBestLocator(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, automationName);\n return locators.length > 0 ? locators[0][1] : null;\n}\n\n/**\n * Convert locator array to object format\n */\nexport function locatorsToObject(locators: [LocatorStrategy, string][]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [strategy, value] of locators) {\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Mobile element locator generation\n *\n * Main orchestrator module that coordinates XML parsing, element filtering,\n * and locator generation for mobile automation.\n *\n * Based on: https://github.com/appium/appium-mcp\n */\n\n// Types\nexport type {\n ElementAttributes,\n JSONElement,\n Bounds,\n FilterOptions,\n UniquenessResult,\n LocatorStrategy,\n LocatorContext,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\n// Constants\nexport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n// XML Parsing\nexport {\n xmlToJSON,\n xmlToDOM,\n evaluateXPath,\n checkXPathUniqueness,\n findDOMNodeByPath,\n parseAndroidBounds,\n parseIOSBounds,\n flattenElementTree,\n countAttributeOccurrences,\n isAttributeUnique,\n} from './xml-parsing';\n\n// Element Filtering\nexport {\n isInteractableElement,\n isLayoutContainer,\n hasMeaningfulContent,\n shouldIncludeElement,\n getDefaultFilters,\n} from './element-filter';\n\n// Locator Generation\nexport {\n getSuggestedLocators,\n getBestLocator,\n locatorsToObject,\n} from './locator-generation';\n\nimport type {\n JSONElement,\n FilterOptions,\n LocatorStrategy,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\nimport { xmlToJSON, xmlToDOM, parseAndroidBounds, parseIOSBounds, findDOMNodeByPath } from './xml-parsing';\nimport { shouldIncludeElement, isLayoutContainer, hasMeaningfulContent } from './element-filter';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\n\ninterface ProcessingContext {\n sourceXML: string;\n platform: 'android' | 'ios';\n automationName: string;\n isNative: boolean;\n viewportSize: { width: number; height: number };\n filters: FilterOptions;\n results: ElementWithLocators[];\n parsedDOM: Document | null;\n}\n\n/**\n * Parse element bounds based on platform\n */\nfunction parseBounds(\n element: JSONElement,\n platform: 'android' | 'ios',\n): { x: number; y: number; width: number; height: number } {\n return platform === 'android'\n ? parseAndroidBounds(element.attributes.bounds || '')\n : parseIOSBounds(element.attributes);\n}\n\n/**\n * Check if bounds are within viewport\n */\nfunction isWithinViewport(\n bounds: { x: number; y: number; width: number; height: number },\n viewport: { width: number; height: number },\n): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width > 0 &&\n bounds.height > 0 &&\n bounds.x + bounds.width <= viewport.width &&\n bounds.y + bounds.height <= viewport.height\n );\n}\n\n/**\n * Transform JSONElement to ElementWithLocators\n */\nfunction transformElement(\n element: JSONElement,\n locators: [LocatorStrategy, string][],\n ctx: ProcessingContext,\n): ElementWithLocators {\n const attrs = element.attributes;\n const bounds = parseBounds(element, ctx.platform);\n\n return {\n tagName: element.tagName,\n locators: locatorsToObject(locators),\n text: attrs.text || attrs.label || '',\n contentDesc: attrs['content-desc'] || '',\n resourceId: attrs['resource-id'] || '',\n accessibilityId: attrs.name || attrs['content-desc'] || '',\n label: attrs.label || '',\n value: attrs.value || '',\n className: attrs.class || element.tagName,\n clickable: attrs.clickable === 'true' || attrs.accessible === 'true' || attrs['long-clickable'] === 'true',\n enabled: attrs.enabled !== 'false',\n displayed: ctx.platform === 'android' ? attrs.displayed !== 'false' : attrs.visible !== 'false',\n bounds,\n isInViewport: isWithinViewport(bounds, ctx.viewportSize),\n };\n}\n\n/**\n * Check if element should be processed\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n return isLayoutContainer(element, ctx.platform) && hasMeaningfulContent(element, ctx.platform);\n}\n\n/**\n * Process a single element and add to results if valid\n */\nfunction processElement(element: JSONElement, ctx: ProcessingContext): void {\n if (!shouldProcess(element, ctx)) return;\n\n try {\n const targetNode = ctx.parsedDOM ? findDOMNodeByPath(ctx.parsedDOM, element.path) : undefined;\n\n const locators = getSuggestedLocators(\n element,\n ctx.sourceXML,\n ctx.automationName,\n { sourceXML: ctx.sourceXML, parsedDOM: ctx.parsedDOM, isAndroid: ctx.platform === 'android' },\n targetNode || undefined,\n );\n if (locators.length === 0) return;\n\n const transformed = transformElement(element, locators, ctx);\n if (Object.keys(transformed.locators).length === 0) return;\n\n ctx.results.push(transformed);\n } catch (error) {\n console.error(`[processElement] Error at path ${element.path}:`, error);\n }\n}\n\n/**\n * Recursively traverse and process element tree\n */\nfunction traverseTree(element: JSONElement | null, ctx: ProcessingContext): void {\n if (!element) return;\n\n processElement(element, ctx);\n\n for (const child of element.children || []) {\n traverseTree(child, ctx);\n }\n}\n\n/**\n * Generate locators for all elements from page source XML\n */\nexport function generateAllElementLocators(\n sourceXML: string,\n options: GenerateLocatorsOptions,\n): ElementWithLocators[] {\n const sourceJSON = xmlToJSON(sourceXML);\n\n if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\n\n const parsedDOM = xmlToDOM(sourceXML);\n\n const ctx: ProcessingContext = {\n sourceXML,\n platform: options.platform,\n automationName: options.platform === 'android' ? 'uiautomator2' : 'xcuitest',\n isNative: options.isNative ?? true,\n viewportSize: options.viewportSize ?? { width: 9999, height: 9999 },\n filters: options.filters ?? {},\n results: [],\n parsedDOM,\n };\n\n traverseTree(sourceJSON, ctx);\n\n return ctx.results;\n}\n","/**\n * Mobile element detection utilities for iOS and Android\n *\n * Uses page source parsing for optimal performance (2 HTTP calls vs 600+ for 50 elements)\n */\n\nimport type { ElementWithLocators, FilterOptions, LocatorStrategy } from '../locators';\nimport { generateAllElementLocators, getDefaultFilters } from '../locators';\n\n/**\n * Element info returned by getMobileVisibleElements\n * Uses uniform fields (all elements have same keys) to enable TOON tabular format\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n text: string;\n resourceId: string;\n accessibilityId: string;\n isEnabled: boolean;\n altSelector: string; // Single alternative selector (flattened for tabular format)\n // Only present when includeBounds=true\n bounds?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Options for getMobileVisibleElements\n */\nexport interface GetMobileElementsOptions {\n includeContainers?: boolean;\n includeBounds?: boolean;\n filterOptions?: FilterOptions;\n}\n\n/**\n * Locator strategy priority order for selecting best selector\n * Earlier = higher priority\n */\nconst LOCATOR_PRIORITY: LocatorStrategy[] = [\n 'accessibility-id', // Most stable, cross-platform\n 'id', // Android resource-id\n 'text', // Text-based (can be fragile but readable)\n 'predicate-string', // iOS predicate\n 'class-chain', // iOS class chain\n 'uiautomator', // Android UiAutomator compound\n 'xpath', // XPath (last resort, brittle)\n // 'class-name' intentionally excluded - too generic\n];\n\n/**\n * Select best locators from available strategies\n * Returns [primarySelector, ...alternativeSelectors]\n */\nfunction selectBestLocators(locators: Record<string, string>): string[] {\n const selected: string[] = [];\n\n // Find primary selector based on priority\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy]) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n // Add one alternative if available (different strategy)\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy] && !selected.includes(locators[strategy])) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n return selected;\n}\n\n/**\n * Convert ElementWithLocators to MobileElementInfo\n * Uses uniform fields (all elements have same keys) to enable CSV tabular format\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n\n // Build object with ALL fields for uniform schema (enables CSV tabular format)\n // Empty string '' used for missing values to keep schema consistent\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n text: element.text || '',\n resourceId: element.resourceId || '',\n accessibilityId: accessId || '',\n isEnabled: element.enabled !== false,\n altSelector: selectedLocators[1] || '', // Single alternative (flattened for tabular)\n };\n\n // Only include bounds if explicitly requested (adds 4 extra columns)\n if (includeBounds) {\n info.bounds = element.bounds;\n }\n\n return info;\n}\n\n/**\n * Get viewport size from browser\n */\nasync function getViewportSize(browser: WebdriverIO.Browser): Promise<{ width: number; height: number }> {\n try {\n const size = await browser.getWindowSize();\n return { width: size.width, height: size.height };\n } catch {\n return { width: 9999, height: 9999 };\n }\n}\n\n/**\n * Get all visible elements from a mobile app\n *\n * Performance: 2 HTTP calls (getWindowSize + getPageSource) vs 12+ per element with legacy approach\n */\nexport async function getMobileVisibleElements(\n browser: WebdriverIO.Browser,\n platform: 'ios' | 'android',\n options: GetMobileElementsOptions = {},\n): Promise<MobileElementInfo[]> {\n const { includeContainers = false, includeBounds = false, filterOptions } = options;\n\n const viewportSize = await getViewportSize(browser);\n const pageSource = await browser.getPageSource();\n\n const filters: FilterOptions = {\n ...getDefaultFilters(platform, includeContainers),\n ...filterOptions,\n };\n\n const elements = generateAllElementLocators(pageSource, {\n platform,\n viewportSize,\n filters,\n });\n\n return elements.map((el) => toMobileElementInfo(el, includeBounds));\n}\n"],"mappings":"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","names":["xpath"]}
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "type": "git",
6
6
  "url": "git://github.com/webdriverio/mcp.git"
7
7
  },
8
- "version": "2.4.1",
8
+ "version": "2.5.1",
9
9
  "description": "MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)",
10
10
  "main": "./lib/server.js",
11
11
  "module": "./lib/server.js",
@@ -70,5 +70,5 @@
70
70
  "typescript": "5.9",
71
71
  "vitest": "^4.0.18"
72
72
  },
73
- "packageManager": "pnpm@10.12.4"
73
+ "packageManager": "pnpm@10.32.1"
74
74
  }