@page-agent/page-controller 0.0.6
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/LICENSE +21 -0
- package/dist/lib/PageController.d.ts +255 -0
- package/dist/lib/page-controller.js +1901 -0
- package/dist/lib/page-controller.js.map +1 -0
- package/package.json +40 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-controller.js","sources":["../../src/actions.ts","../../src/constants.ts","../../src/dom/dom_tree/index.js","../../src/dom/index.ts","../../src/dom/getPageInfo.ts","../../src/patches/react.ts","../../src/PageController.ts"],"sourcesContent":["/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\nimport type { InteractiveElementDomNode } from './dom/dom_tree/type'\n\n// ======= general utils =======\n\nasync function waitFor(seconds: number): Promise<void> {\n\tawait new Promise((resolve) => setTimeout(resolve, seconds * 1000))\n}\n\n// ======= dom utils =======\n\nexport async function movePointerToElement(element: HTMLElement) {\n\tconst rect = element.getBoundingClientRect()\n\tconst x = rect.left + rect.width / 2\n\tconst y = rect.top + rect.height / 2\n\n\twindow.dispatchEvent(new CustomEvent('PageAgent::MovePointerTo', { detail: { x, y } }))\n\n\tawait waitFor(0.3)\n}\n\n/**\n * Get the HTMLElement by index from a selectorMap.\n */\nexport function getElementByIndex(\n\tselectorMap: Map<number, InteractiveElementDomNode>,\n\tindex: number\n): HTMLElement {\n\tconst interactiveNode = selectorMap.get(index)\n\tif (!interactiveNode) {\n\t\tthrow new Error(`No interactive element found at index ${index}`)\n\t}\n\n\tconst element = interactiveNode.ref\n\tif (!element) {\n\t\tthrow new Error(`Element at index ${index} does not have a reference`)\n\t}\n\n\tif (!(element instanceof HTMLElement)) {\n\t\tthrow new Error(`Element at index ${index} is not an HTMLElement`)\n\t}\n\n\treturn element\n}\n\nlet lastClickedElement: HTMLElement | null = null\n\nfunction blurLastClickedElement() {\n\tif (lastClickedElement) {\n\t\tlastClickedElement.blur()\n\t\tlastClickedElement.dispatchEvent(\n\t\t\tnew MouseEvent('mouseout', { bubbles: true, cancelable: true })\n\t\t)\n\t\tlastClickedElement = null\n\t}\n}\n\n/**\n * Simulate a click on the element\n */\nexport async function clickElement(element: HTMLElement) {\n\tblurLastClickedElement()\n\n\tlastClickedElement = element\n\tawait scrollIntoViewIfNeeded(element)\n\tawait movePointerToElement(element)\n\twindow.dispatchEvent(new CustomEvent('PageAgent::ClickPointer'))\n\tawait waitFor(0.1)\n\n\t// hover it\n\telement.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true, cancelable: true }))\n\telement.dispatchEvent(new MouseEvent('mouseover', { bubbles: true, cancelable: true }))\n\n\t// dispatch a sequence of events to ensure all listeners are triggered\n\telement.dispatchEvent(new MouseEvent('mousedown', { bubbles: true, cancelable: true }))\n\n\t// focus it to ensure it gets the click event\n\telement.focus()\n\n\telement.dispatchEvent(new MouseEvent('mouseup', { bubbles: true, cancelable: true }))\n\telement.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true }))\n\n\t// dispatch a click event\n\t// element.click()\n\n\tawait waitFor(0.1) // Wait to ensure click event processing completes\n}\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst nativeInputValueSetter = Object.getOwnPropertyDescriptor(\n\twindow.HTMLInputElement.prototype,\n\t'value'\n)!.set!\n\n// eslint-disable-next-line @typescript-eslint/unbound-method\nconst nativeTextAreaValueSetter = Object.getOwnPropertyDescriptor(\n\twindow.HTMLTextAreaElement.prototype,\n\t'value'\n)!.set!\n\n/**\n * create a synthetic keyboard event\n * with key keycode code\n */\nexport async function createSyntheticInputEvent(elem: HTMLElement, key: string) {\n\telem.dispatchEvent(new KeyboardEvent('keydown', { bubbles: true, cancelable: true, key }))\n\tawait waitFor(0.01)\n\n\tif (elem instanceof HTMLInputElement || elem instanceof HTMLTextAreaElement) {\n\t\telem.dispatchEvent(new Event('beforeinput', { bubbles: true }))\n\t\tawait waitFor(0.01)\n\t\telem.dispatchEvent(new Event('input', { bubbles: true }))\n\t\tawait waitFor(0.01)\n\t}\n\n\telem.dispatchEvent(new KeyboardEvent('keyup', { bubbles: true, cancelable: true, key }))\n}\n\nexport async function inputTextElement(element: HTMLElement, text: string) {\n\tif (!(element instanceof HTMLInputElement || element instanceof HTMLTextAreaElement)) {\n\t\tthrow new Error('Element is not an input or textarea')\n\t}\n\n\tawait clickElement(element)\n\n\tif (element instanceof HTMLTextAreaElement) {\n\t\tnativeTextAreaValueSetter.call(element, text)\n\t} else {\n\t\tnativeInputValueSetter.call(element, text)\n\t}\n\n\tconst inputEvent = new Event('input', { bubbles: true })\n\telement.dispatchEvent(inputEvent)\n\n\tawait waitFor(0.1) // Wait to ensure input event processing completes\n\n\tblurLastClickedElement()\n}\n\n/**\n * @todo browser-use version is very complex and supports menu tags, need to follow up\n */\nexport async function selectOptionElement(selectElement: HTMLSelectElement, optionText: string) {\n\tif (!(selectElement instanceof HTMLSelectElement)) {\n\t\tthrow new Error('Element is not a select element')\n\t}\n\n\tconst options = Array.from(selectElement.options)\n\tconst option = options.find((opt) => opt.textContent?.trim() === optionText.trim())\n\n\tif (!option) {\n\t\tthrow new Error(`Option with text \"${optionText}\" not found in select element`)\n\t}\n\n\tselectElement.value = option.value\n\tselectElement.dispatchEvent(new Event('change', { bubbles: true }))\n\n\tawait waitFor(0.1) // Wait to ensure change event processing completes\n}\n\nexport async function scrollIntoViewIfNeeded(element: HTMLElement) {\n\tconst el = element as any\n\tif (el.scrollIntoViewIfNeeded) {\n\t\tel.scrollIntoViewIfNeeded()\n\t\t// await waitFor(0.5) // Animation playback\n\t} else {\n\t\t// @todo visibility check\n\t\tel.scrollIntoView({ behavior: 'auto', block: 'center', inline: 'nearest' })\n\t\t// await waitFor(0.5) // Animation playback\n\t}\n}\n\nexport async function scrollVertically(\n\tdown: boolean,\n\tscroll_amount: number,\n\telement?: HTMLElement | null\n) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tconsole.log(\n\t\t\t'[SCROLL DEBUG] Starting direct container scroll for element:',\n\t\t\ttargetElement.tagName\n\t\t)\n\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dy = scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableY = /(auto|scroll|overlay)/.test(computedStyle.overflowY)\n\t\t\tconst canScrollVertically = currentElement.scrollHeight > currentElement.clientHeight\n\n\t\t\tconsole.log(\n\t\t\t\t'[SCROLL DEBUG] Checking element:',\n\t\t\t\tcurrentElement.tagName,\n\t\t\t\t'hasScrollableY:',\n\t\t\t\thasScrollableY,\n\t\t\t\t'canScrollVertically:',\n\t\t\t\tcanScrollVertically,\n\t\t\t\t'scrollHeight:',\n\t\t\t\tcurrentElement.scrollHeight,\n\t\t\t\t'clientHeight:',\n\t\t\t\tcurrentElement.clientHeight\n\t\t\t)\n\n\t\t\tif (hasScrollableY && canScrollVertically) {\n\t\t\t\tconst beforeScroll = currentElement.scrollTop\n\t\t\t\tconst maxScroll = currentElement.scrollHeight - currentElement.clientHeight\n\n\t\t\t\tlet scrollAmount = dy / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollTop = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollTop\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t'[SCROLL DEBUG] Scroll attempt:',\n\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t'before:',\n\t\t\t\t\tbeforeScroll,\n\t\t\t\t\t'after:',\n\t\t\t\t\tafterScroll,\n\t\t\t\t\t'delta:',\n\t\t\t\t\tactualScrollDelta\n\t\t\t\t)\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t'[SCROLL DEBUG] Successfully scrolled container:',\n\t\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t\t'delta:',\n\t\t\t\t\t\tactualScrollDelta\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dy = scroll_amount\n\tconst bigEnough = (el: HTMLElement) => el.clientHeight >= window.innerHeight * 0.5\n\tconst canScroll = (el: HTMLElement | null) =>\n\t\tel &&\n\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowY) &&\n\t\tel.scrollHeight > el.clientHeight &&\n\t\tbigEnough(el)\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\twindow.scrollBy(0, dy)\n\t\treturn `✅ Scrolled page by ${dy}px.`\n\t} else {\n\t\tel!.scrollBy({ top: dy, behavior: 'smooth' })\n\t\tawait waitFor(0.1) // Animation playback\n\t\treturn `✅ Scrolled container (${el!.tagName}) by ${dy}px.`\n\t}\n}\n\nexport async function scrollHorizontally(\n\tright: boolean,\n\tscroll_amount: number,\n\telement?: HTMLElement | null\n) {\n\t// Element-specific scrolling if element is provided\n\tif (element) {\n\t\tconst targetElement = element\n\t\tconsole.log(\n\t\t\t'[SCROLL DEBUG] Starting direct container scroll for element:',\n\t\t\ttargetElement.tagName\n\t\t)\n\n\t\tlet currentElement = targetElement as HTMLElement | null\n\t\tlet scrollSuccess = false\n\t\tlet scrolledElement: HTMLElement | null = null\n\t\tlet scrollDelta = 0\n\t\tlet attempts = 0\n\t\tconst dx = right ? scroll_amount : -scroll_amount\n\n\t\twhile (currentElement && attempts < 10) {\n\t\t\tconst computedStyle = window.getComputedStyle(currentElement)\n\t\t\tconst hasScrollableX = /(auto|scroll|overlay)/.test(computedStyle.overflowX)\n\t\t\tconst canScrollHorizontally = currentElement.scrollWidth > currentElement.clientWidth\n\n\t\t\tconsole.log(\n\t\t\t\t'[SCROLL DEBUG] Checking element:',\n\t\t\t\tcurrentElement.tagName,\n\t\t\t\t'hasScrollableX:',\n\t\t\t\thasScrollableX,\n\t\t\t\t'canScrollHorizontally:',\n\t\t\t\tcanScrollHorizontally,\n\t\t\t\t'scrollWidth:',\n\t\t\t\tcurrentElement.scrollWidth,\n\t\t\t\t'clientWidth:',\n\t\t\t\tcurrentElement.clientWidth\n\t\t\t)\n\n\t\t\tif (hasScrollableX && canScrollHorizontally) {\n\t\t\t\tconst beforeScroll = currentElement.scrollLeft\n\t\t\t\tconst maxScroll = currentElement.scrollWidth - currentElement.clientWidth\n\n\t\t\t\tlet scrollAmount = dx / 3\n\n\t\t\t\tif (scrollAmount > 0) {\n\t\t\t\t\tscrollAmount = Math.min(scrollAmount, maxScroll - beforeScroll)\n\t\t\t\t} else {\n\t\t\t\t\tscrollAmount = Math.max(scrollAmount, -beforeScroll)\n\t\t\t\t}\n\n\t\t\t\tcurrentElement.scrollLeft = beforeScroll + scrollAmount\n\n\t\t\t\tconst afterScroll = currentElement.scrollLeft\n\t\t\t\tconst actualScrollDelta = afterScroll - beforeScroll\n\n\t\t\t\tconsole.log(\n\t\t\t\t\t'[SCROLL DEBUG] Scroll attempt:',\n\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t'before:',\n\t\t\t\t\tbeforeScroll,\n\t\t\t\t\t'after:',\n\t\t\t\t\tafterScroll,\n\t\t\t\t\t'delta:',\n\t\t\t\t\tactualScrollDelta\n\t\t\t\t)\n\n\t\t\t\tif (Math.abs(actualScrollDelta) > 0.5) {\n\t\t\t\t\tscrollSuccess = true\n\t\t\t\t\tscrolledElement = currentElement\n\t\t\t\t\tscrollDelta = actualScrollDelta\n\t\t\t\t\tconsole.log(\n\t\t\t\t\t\t'[SCROLL DEBUG] Successfully scrolled container:',\n\t\t\t\t\t\tcurrentElement.tagName,\n\t\t\t\t\t\t'delta:',\n\t\t\t\t\t\tactualScrollDelta\n\t\t\t\t\t)\n\t\t\t\t\tbreak\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (currentElement === document.body || currentElement === document.documentElement) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcurrentElement = currentElement.parentElement\n\t\t\tattempts++\n\t\t}\n\n\t\tif (scrollSuccess) {\n\t\t\treturn `Scrolled container (${scrolledElement?.tagName}) horizontally by ${scrollDelta}px`\n\t\t} else {\n\t\t\treturn `No horizontally scrollable container found for element (${targetElement.tagName})`\n\t\t}\n\t}\n\n\t// Page-level scrolling (default or fallback)\n\n\tconst dx = right ? scroll_amount : -scroll_amount\n\tconst bigEnough = (el: HTMLElement) => el.clientWidth >= window.innerWidth * 0.5\n\tconst canScroll = (el: HTMLElement | null) =>\n\t\tel &&\n\t\t/(auto|scroll|overlay)/.test(getComputedStyle(el).overflowX) &&\n\t\tel.scrollWidth > el.clientWidth &&\n\t\tbigEnough(el)\n\n\tlet el: HTMLElement | null = document.activeElement as HTMLElement | null\n\twhile (el && !canScroll(el) && el !== document.body) el = el.parentElement\n\n\tel = canScroll(el)\n\t\t? el\n\t\t: Array.from(document.querySelectorAll<HTMLElement>('*')).find(canScroll) ||\n\t\t\t(document.scrollingElement as HTMLElement) ||\n\t\t\t(document.documentElement as HTMLElement)\n\n\tif (el === document.scrollingElement || el === document.documentElement || el === document.body) {\n\t\twindow.scrollBy(dx, 0)\n\t\treturn `✅ Scrolled page horizontally by ${dx}px`\n\t} else {\n\t\tel!.scrollBy({ left: dx, behavior: 'smooth' })\n\t\tawait waitFor(0.1) // Animation playback\n\t\treturn `✅ Scrolled container (${el!.tagName}) horizontally by ${dx}px`\n\t}\n}\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n */\n\n/**\n * Viewport expansion for DOM tree extraction.\n * -1 means full page (no viewport restriction)\n * 0 means viewport only\n * positive values expand the viewport by that many pixels\n *\n * @note Since isTopElement depends on elementFromPoint,\n * it returns null when out of viewport, this feature has no practical use, only differ between -1 and 0\n */\n// export const VIEWPORT_EXPANSION = 100\nexport const VIEWPORT_EXPANSION = -1\n","/**\n * @file port from browser-use\n * @see https://github.com/browser-use/browser-use/commits/main/browser_use/dom/dom_tree/index.js\n * @match 0.5.9 d51b6e73daff7165fdd3e44debd667e7f5f7fdc5\n *\n * search @edit for all the changed lines.\n *\n * @edit export\n * @edit add interactiveBlacklist interactiveWhitelist\n * @edit adjustable opacity\n * @edit direct dom ref\n * @edit @workaround input.checked\n * @edit smaller zIndex for highlight\n * @edit no need for xpath\n * @edit add `extra` field for extra data\n * @edit scrollable element detection\n * @edit add `data-browser-use-ignore` attribute\n * @edit improve `sampleRect`, filter out rects with 0 area\n */\n\nexport default (\n\targs = {\n\t\tdoHighlightElements: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion: 0,\n\t\tdebugMode: false,\n\n\t\t/**\n\t\t * @edit\n\t\t */\n\t\t/** @type {Element[]} */\n\t\tinteractiveBlacklist: [],\n\t\t/** @type {Element[]} */\n\t\tinteractiveWhitelist: [],\n\t\thighlightOpacity: 0.1,\n\t\thighlightLabelOpacity: 0.5,\n\t}\n) => {\n\t/**\n\t * @edit\n\t */\n\tconst { interactiveBlacklist, interactiveWhitelist, highlightOpacity, highlightLabelOpacity } =\n\t\targs\n\n\tconst { doHighlightElements, focusHighlightIndex, viewportExpansion, debugMode } = args\n\tlet highlightIndex = 0 // Reset highlight index\n\n\t/**\n\t * @edit add `extra` field for extra data\n\t */\n\tconst extraData = new WeakMap()\n\tfunction addExtraData(element, data) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return\n\t\textraData.set(element, { ...extraData.get(element), ...data })\n\t}\n\n\t// Add caching mechanisms at the top level\n\tconst DOM_CACHE = {\n\t\tboundingRects: new WeakMap(),\n\t\tclientRects: new WeakMap(),\n\t\tcomputedStyles: new WeakMap(),\n\t\tclearCache: () => {\n\t\t\tDOM_CACHE.boundingRects = new WeakMap()\n\t\t\tDOM_CACHE.clientRects = new WeakMap()\n\t\t\tDOM_CACHE.computedStyles = new WeakMap()\n\t\t},\n\t}\n\n\t/**\n\t * Gets the cached bounding rect for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the bounding rect for.\n\t * @returns {DOMRect | null} The cached bounding rect, or null if the element is not found.\n\t */\n\tfunction getCachedBoundingRect(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.boundingRects.has(element)) {\n\t\t\treturn DOM_CACHE.boundingRects.get(element)\n\t\t}\n\n\t\tconst rect = element.getBoundingClientRect()\n\n\t\tif (rect) {\n\t\t\tDOM_CACHE.boundingRects.set(element, rect)\n\t\t}\n\t\treturn rect\n\t}\n\n\t/**\n\t * Gets the cached computed style for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the computed style for.\n\t * @returns {CSSStyleDeclaration | null} The cached computed style, or null if the element is not found.\n\t */\n\tfunction getCachedComputedStyle(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.computedStyles.has(element)) {\n\t\t\treturn DOM_CACHE.computedStyles.get(element)\n\t\t}\n\n\t\tconst style = window.getComputedStyle(element)\n\n\t\tif (style) {\n\t\t\tDOM_CACHE.computedStyles.set(element, style)\n\t\t}\n\t\treturn style\n\t}\n\n\t/**\n\t * Gets the cached client rects for an element.\n\t *\n\t * @param {HTMLElement} element - The element to get the client rects for.\n\t * @returns {DOMRectList | null} The cached client rects, or null if the element is not found.\n\t */\n\tfunction getCachedClientRects(element) {\n\t\tif (!element) return null\n\n\t\tif (DOM_CACHE.clientRects.has(element)) {\n\t\t\treturn DOM_CACHE.clientRects.get(element)\n\t\t}\n\n\t\tconst rects = element.getClientRects()\n\n\t\tif (rects) {\n\t\t\tDOM_CACHE.clientRects.set(element, rects)\n\t\t}\n\t\treturn rects\n\t}\n\n\t/**\n\t * Hash map of DOM nodes indexed by their highlight index.\n\t *\n\t * @type {Object<string, any>}\n\t */\n\tconst DOM_HASH_MAP = {}\n\n\tconst ID = { current: 0 }\n\n\tconst HIGHLIGHT_CONTAINER_ID = 'playwright-highlight-container'\n\n\t// Add a WeakMap cache for XPath strings\n\tconst xpathCache = new WeakMap()\n\n\t// // Initialize once and reuse\n\t// const viewportObserver = new IntersectionObserver(\n\t// (entries) => {\n\t// entries.forEach(entry => {\n\t// elementVisibilityMap.set(entry.target, entry.isIntersecting);\n\t// });\n\t// },\n\t// { rootMargin: `${viewportExpansion}px` }\n\t// );\n\n\t/**\n\t * Highlights an element in the DOM and returns the index of the next element.\n\t *\n\t * @param {HTMLElement} element - The element to highlight.\n\t * @param {number} index - The index of the element.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @returns {number} The index of the next element.\n\t */\n\tfunction highlightElement(element, index, parentIframe = null) {\n\t\tif (!element) return index\n\n\t\tconst overlays = []\n\t\t/**\n\t\t * @type {HTMLElement | null}\n\t\t */\n\t\tlet label = null\n\t\tlet labelWidth = 20\n\t\tlet labelHeight = 16\n\t\tlet cleanupFn = null\n\n\t\ttry {\n\t\t\t// Create or get highlight container\n\t\t\tlet container = document.getElementById(HIGHLIGHT_CONTAINER_ID)\n\t\t\tif (!container) {\n\t\t\t\tcontainer = document.createElement('div')\n\t\t\t\tcontainer.id = HIGHLIGHT_CONTAINER_ID\n\t\t\t\tcontainer.style.position = 'fixed'\n\t\t\t\tcontainer.style.pointerEvents = 'none'\n\t\t\t\tcontainer.style.top = '0'\n\t\t\t\tcontainer.style.left = '0'\n\t\t\t\tcontainer.style.width = '100%'\n\t\t\t\tcontainer.style.height = '100%'\n\n\t\t\t\t/**\n\t\t\t\t * @edit smaller zIndex for highlight\n\t\t\t\t */\n\t\t\t\t// Use the maximum valid value in zIndex to ensure the element is not blocked by overlapping elements.\n\t\t\t\t// container.style.zIndex = \"2147483647\";\n\t\t\t\tcontainer.style.zIndex = '2147483640'\n\n\t\t\t\tcontainer.style.backgroundColor = 'transparent'\n\t\t\t\tdocument.body.appendChild(container)\n\t\t\t}\n\n\t\t\t// Get element client rects\n\t\t\tconst rects = element.getClientRects() // Use getClientRects()\n\n\t\t\tif (!rects || rects.length === 0) return index // Exit if no rects\n\n\t\t\t// Generate a color based on the index\n\t\t\tconst colors = [\n\t\t\t\t'#FF0000',\n\t\t\t\t'#00FF00',\n\t\t\t\t'#0000FF',\n\t\t\t\t'#FFA500',\n\t\t\t\t'#800080',\n\t\t\t\t'#008080',\n\t\t\t\t'#FF69B4',\n\t\t\t\t'#4B0082',\n\t\t\t\t'#FF4500',\n\t\t\t\t'#2E8B57',\n\t\t\t\t'#DC143C',\n\t\t\t\t'#4682B4',\n\t\t\t]\n\t\t\tconst colorIndex = index % colors.length\n\t\t\tlet baseColor = colors[colorIndex]\n\n\t\t\t/**\n\t\t\t * @edit adjustable opacity\n\t\t\t */\n\t\t\t// const backgroundColor = baseColor + \"1A\"; // 10% opacity version of the color\n\t\t\tconst backgroundColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\t\t\tbaseColor =\n\t\t\t\tbaseColor +\n\t\t\t\tMath.floor(highlightLabelOpacity * 255)\n\t\t\t\t\t.toString(16)\n\t\t\t\t\t.padStart(2, '0')\n\n\t\t\t// Get iframe offset if necessary\n\t\t\tlet iframeOffset = { x: 0, y: 0 }\n\t\t\tif (parentIframe) {\n\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe offset\n\t\t\t\tiframeOffset.x = iframeRect.left\n\t\t\t\tiframeOffset.y = iframeRect.top\n\t\t\t}\n\n\t\t\t// Create fragment to hold overlay elements\n\t\t\tconst fragment = document.createDocumentFragment()\n\n\t\t\t// Create highlight overlays for each client rect\n\t\t\tfor (const rect of rects) {\n\t\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\t\tconst overlay = document.createElement('div')\n\t\t\t\toverlay.style.position = 'fixed'\n\t\t\t\toverlay.style.border = `2px solid ${baseColor}`\n\t\t\t\toverlay.style.backgroundColor = backgroundColor\n\t\t\t\toverlay.style.pointerEvents = 'none'\n\t\t\t\toverlay.style.boxSizing = 'border-box'\n\n\t\t\t\tconst top = rect.top + iframeOffset.y\n\t\t\t\tconst left = rect.left + iframeOffset.x\n\n\t\t\t\toverlay.style.top = `${top}px`\n\t\t\t\toverlay.style.left = `${left}px`\n\t\t\t\toverlay.style.width = `${rect.width}px`\n\t\t\t\toverlay.style.height = `${rect.height}px`\n\n\t\t\t\tfragment.appendChild(overlay)\n\t\t\t\toverlays.push({ element: overlay, initialRect: rect }) // Store overlay and its rect\n\t\t\t}\n\n\t\t\t// Create and position a single label relative to the first rect\n\t\t\tconst firstRect = rects[0]\n\t\t\tlabel = document.createElement('div')\n\t\t\tlabel.className = 'playwright-highlight-label'\n\t\t\tlabel.style.position = 'fixed'\n\t\t\tlabel.style.background = baseColor\n\t\t\tlabel.style.color = 'white'\n\t\t\tlabel.style.padding = '1px 4px'\n\t\t\tlabel.style.borderRadius = '4px'\n\t\t\tlabel.style.fontSize = `${Math.min(12, Math.max(8, firstRect.height / 2))}px`\n\t\t\tlabel.textContent = index.toString()\n\n\t\t\tlabelWidth = label.offsetWidth > 0 ? label.offsetWidth : labelWidth // Update actual width if possible\n\t\t\tlabelHeight = label.offsetHeight > 0 ? label.offsetHeight : labelHeight // Update actual height if possible\n\n\t\t\tconst firstRectTop = firstRect.top + iframeOffset.y\n\t\t\tconst firstRectLeft = firstRect.left + iframeOffset.x\n\n\t\t\tlet labelTop = firstRectTop + 2\n\t\t\tlet labelLeft = firstRectLeft + firstRect.width - labelWidth - 2\n\n\t\t\t// Adjust label position if first rect is too small\n\t\t\tif (firstRect.width < labelWidth + 4 || firstRect.height < labelHeight + 4) {\n\t\t\t\tlabelTop = firstRectTop - labelHeight - 2\n\t\t\t\tlabelLeft = firstRectLeft + firstRect.width - labelWidth // Align with right edge\n\t\t\t\tif (labelLeft < iframeOffset.x) labelLeft = firstRectLeft // Prevent going off-left\n\t\t\t}\n\n\t\t\t// Ensure label stays within viewport bounds slightly better\n\t\t\tlabelTop = Math.max(0, Math.min(labelTop, window.innerHeight - labelHeight))\n\t\t\tlabelLeft = Math.max(0, Math.min(labelLeft, window.innerWidth - labelWidth))\n\n\t\t\tlabel.style.top = `${labelTop}px`\n\t\t\tlabel.style.left = `${labelLeft}px`\n\n\t\t\tfragment.appendChild(label)\n\n\t\t\t// Update positions on scroll/resize\n\t\t\tconst updatePositions = () => {\n\t\t\t\tconst newRects = element.getClientRects() // Get fresh rects\n\t\t\t\tlet newIframeOffset = { x: 0, y: 0 }\n\n\t\t\t\tif (parentIframe) {\n\t\t\t\t\tconst iframeRect = parentIframe.getBoundingClientRect() // Keep getBoundingClientRect for iframe\n\t\t\t\t\tnewIframeOffset.x = iframeRect.left\n\t\t\t\t\tnewIframeOffset.y = iframeRect.top\n\t\t\t\t}\n\n\t\t\t\t// Update each overlay\n\t\t\t\toverlays.forEach((overlayData, i) => {\n\t\t\t\t\tif (i < newRects.length) {\n\t\t\t\t\t\t// Check if rect still exists\n\t\t\t\t\t\tconst newRect = newRects[i]\n\t\t\t\t\t\tconst newTop = newRect.top + newIframeOffset.y\n\t\t\t\t\t\tconst newLeft = newRect.left + newIframeOffset.x\n\n\t\t\t\t\t\toverlayData.element.style.top = `${newTop}px`\n\t\t\t\t\t\toverlayData.element.style.left = `${newLeft}px`\n\t\t\t\t\t\toverlayData.element.style.width = `${newRect.width}px`\n\t\t\t\t\t\toverlayData.element.style.height = `${newRect.height}px`\n\t\t\t\t\t\toverlayData.element.style.display =\n\t\t\t\t\t\t\tnewRect.width === 0 || newRect.height === 0 ? 'none' : 'block'\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If fewer rects now, hide extra overlays\n\t\t\t\t\t\toverlayData.element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t})\n\n\t\t\t\t// If there are fewer new rects than overlays, hide the extras\n\t\t\t\tif (newRects.length < overlays.length) {\n\t\t\t\t\tfor (let i = newRects.length; i < overlays.length; i++) {\n\t\t\t\t\t\toverlays[i].element.style.display = 'none'\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Update label position based on the first new rect\n\t\t\t\tif (label && newRects.length > 0) {\n\t\t\t\t\tconst firstNewRect = newRects[0]\n\t\t\t\t\tconst firstNewRectTop = firstNewRect.top + newIframeOffset.y\n\t\t\t\t\tconst firstNewRectLeft = firstNewRect.left + newIframeOffset.x\n\n\t\t\t\t\tlet newLabelTop = firstNewRectTop + 2\n\t\t\t\t\tlet newLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth - 2\n\n\t\t\t\t\tif (firstNewRect.width < labelWidth + 4 || firstNewRect.height < labelHeight + 4) {\n\t\t\t\t\t\tnewLabelTop = firstNewRectTop - labelHeight - 2\n\t\t\t\t\t\tnewLabelLeft = firstNewRectLeft + firstNewRect.width - labelWidth\n\t\t\t\t\t\tif (newLabelLeft < newIframeOffset.x) newLabelLeft = firstNewRectLeft\n\t\t\t\t\t}\n\n\t\t\t\t\t// Ensure label stays within viewport bounds\n\t\t\t\t\tnewLabelTop = Math.max(0, Math.min(newLabelTop, window.innerHeight - labelHeight))\n\t\t\t\t\tnewLabelLeft = Math.max(0, Math.min(newLabelLeft, window.innerWidth - labelWidth))\n\n\t\t\t\t\tlabel.style.top = `${newLabelTop}px`\n\t\t\t\t\tlabel.style.left = `${newLabelLeft}px`\n\t\t\t\t\tlabel.style.display = 'block'\n\t\t\t\t} else if (label) {\n\t\t\t\t\t// Hide label if element has no rects anymore\n\t\t\t\t\tlabel.style.display = 'none'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttleFunction = (func, delay) => {\n\t\t\t\tlet lastCall = 0\n\t\t\t\treturn (...args) => {\n\t\t\t\t\tconst now = performance.now()\n\t\t\t\t\tif (now - lastCall < delay) return\n\t\t\t\t\tlastCall = now\n\t\t\t\t\treturn func(...args)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst throttledUpdatePositions = throttleFunction(updatePositions, 16) // ~60fps\n\t\t\twindow.addEventListener('scroll', throttledUpdatePositions, true)\n\t\t\twindow.addEventListener('resize', throttledUpdatePositions)\n\n\t\t\t// Add cleanup function\n\t\t\tcleanupFn = () => {\n\t\t\t\twindow.removeEventListener('scroll', throttledUpdatePositions, true)\n\t\t\t\twindow.removeEventListener('resize', throttledUpdatePositions)\n\t\t\t\t// Remove overlay elements if needed\n\t\t\t\toverlays.forEach((overlay) => overlay.element.remove())\n\t\t\t\tif (label) label.remove()\n\t\t\t}\n\n\t\t\t// Then add fragment to container in one operation\n\t\t\tcontainer.appendChild(fragment)\n\n\t\t\treturn index + 1\n\t\t} finally {\n\t\t\t// Store cleanup function for later use\n\t\t\tif (cleanupFn) {\n\t\t\t\t// Keep a reference to cleanup functions in a global array\n\t\t\t\t;(window._highlightCleanupFunctions = window._highlightCleanupFunctions || []).push(\n\t\t\t\t\tcleanupFn\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t}\n\n\t// // Add this function to perform cleanup when needed\n\t// function cleanupHighlights() {\n\t// if (window._highlightCleanupFunctions && window._highlightCleanupFunctions.length) {\n\t// window._highlightCleanupFunctions.forEach(fn => fn());\n\t// window._highlightCleanupFunctions = [];\n\t// }\n\n\t// // Also remove the container\n\t// const container = document.getElementById(HIGHLIGHT_CONTAINER_ID);\n\t// if (container) container.remove();\n\t// }\n\n\t/**\n\t * Gets the position of an element in its parent.\n\t *\n\t * @param {HTMLElement} currentElement - The element to get the position for.\n\t * @returns {number} The position of the element in its parent.\n\t */\n\tfunction getElementPosition(currentElement) {\n\t\tif (!currentElement.parentElement) {\n\t\t\treturn 0 // No parent means no siblings\n\t\t}\n\n\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\n\t\tconst siblings = Array.from(currentElement.parentElement.children).filter(\n\t\t\t(sib) => sib.nodeName.toLowerCase() === tagName\n\t\t)\n\n\t\tif (siblings.length === 1) {\n\t\t\treturn 0 // Only element of its type\n\t\t}\n\n\t\tconst index = siblings.indexOf(currentElement) + 1 // 1-based index\n\t\treturn index\n\t}\n\n\tfunction getXPathTree(element, stopAtBoundary = true) {\n\t\tif (xpathCache.has(element)) return xpathCache.get(element)\n\n\t\tconst segments = []\n\t\tlet currentElement = element\n\n\t\twhile (currentElement && currentElement.nodeType === Node.ELEMENT_NODE) {\n\t\t\t// Stop if we hit a shadow root or iframe\n\t\t\tif (\n\t\t\t\tstopAtBoundary &&\n\t\t\t\t(currentElement.parentNode instanceof ShadowRoot ||\n\t\t\t\t\tcurrentElement.parentNode instanceof HTMLIFrameElement)\n\t\t\t) {\n\t\t\t\tbreak\n\t\t\t}\n\n\t\t\tconst position = getElementPosition(currentElement)\n\t\t\tconst tagName = currentElement.nodeName.toLowerCase()\n\t\t\tconst xpathIndex = position > 0 ? `[${position}]` : ''\n\t\t\tsegments.unshift(`${tagName}${xpathIndex}`)\n\n\t\t\tcurrentElement = currentElement.parentNode\n\t\t}\n\n\t\tconst result = segments.join('/')\n\t\txpathCache.set(element, result)\n\t\treturn result\n\t}\n\n\t/**\n\t * @edit scrollable element detection\n\t * Checks if an element is scrollable. if so, return the scrollable distance on each direction (left right top bottom). if not return null.\n\t * @note distance smaller than 4 will be considered as not scrollable.\n\t * @note only check block elements, not inline elements.\n\t */\n\tfunction isScrollableElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn null // Not a valid element\n\t\t}\n\n\t\tconst style = getCachedComputedStyle(element)\n\t\tif (!style) return null\n\n\t\t// Check if the element is a block-level element\n\t\tconst display = style.display\n\t\tif (display === 'inline' || display === 'inline-block') {\n\t\t\treturn null // Not a block-level element\n\t\t}\n\n\t\t// Check overflow properties\n\t\tconst overflowX = style.overflowX\n\t\tconst overflowY = style.overflowY\n\n\t\t// Check scrollable distances\n\t\tconst scrollableX = overflowX === 'auto' || overflowX === 'scroll'\n\t\tconst scrollableY = overflowY === 'auto' || overflowY === 'scroll'\n\n\t\tif (!scrollableX && !scrollableY) {\n\t\t\treturn null // Not scrollable in any direction\n\t\t}\n\n\t\tconst scrollWidth = element.scrollWidth - element.clientWidth\n\t\tconst scrollHeight = element.scrollHeight - element.clientHeight\n\n\t\t// Consider small distances as not scrollable\n\t\tconst threshold = 4\n\n\t\tif (scrollWidth < threshold && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable\n\t\t}\n\n\t\tif (!scrollableY && scrollWidth < threshold) {\n\t\t\treturn null // Not scrollable horizontally\n\t\t}\n\n\t\tif (!scrollableX && scrollHeight < threshold) {\n\t\t\treturn null // Not scrollable vertically\n\t\t}\n\n\t\tconst distanceToTop = element.scrollTop\n\t\tconst distanceToLeft = element.scrollLeft\n\t\tconst distanceToRight = element.scrollWidth - element.clientWidth - element.scrollLeft\n\t\tconst distanceToBottom = element.scrollHeight - element.clientHeight - element.scrollTop\n\n\t\tconst scrollData = {\n\t\t\ttop: distanceToTop,\n\t\t\tright: distanceToRight,\n\t\t\tbottom: distanceToBottom,\n\t\t\tleft: distanceToLeft,\n\t\t}\n\n\t\t// Store extra data for the element\n\t\taddExtraData(element, {\n\t\t\tscrollable: true,\n\t\t\tscrollData: scrollData,\n\t\t})\n\n\t\treturn scrollData\n\t}\n\n\t/**\n\t * Checks if a text node is visible.\n\t *\n\t * @param {Text} textNode - The text node to check.\n\t * @returns {boolean} Whether the text node is visible.\n\t */\n\tfunction isTextNodeVisible(textNode) {\n\t\ttry {\n\t\t\t// Special case: when viewportExpansion is -1, consider all text nodes as visible\n\t\t\tif (viewportExpansion === -1) {\n\t\t\t\t// Still check parent visibility for basic filtering\n\t\t\t\tconst parentElement = textNode.parentElement\n\t\t\t\tif (!parentElement) return false\n\n\t\t\t\ttry {\n\t\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t\t})\n\t\t\t\t} catch (e) {\n\t\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst range = document.createRange()\n\t\t\trange.selectNodeContents(textNode)\n\t\t\tconst rects = range.getClientRects() // Use getClientRects for Range\n\n\t\t\tif (!rects || rects.length === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\tlet isAnyRectVisible = false\n\t\t\tlet isAnyRectInViewport = false\n\n\t\t\tfor (const rect of rects) {\n\t\t\t\t// Check size\n\t\t\t\tif (rect.width > 0 && rect.height > 0) {\n\t\t\t\t\tisAnyRectVisible = true\n\n\t\t\t\t\t// Viewport check for this rect\n\t\t\t\t\tif (\n\t\t\t\t\t\t!(\n\t\t\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t\t\t)\n\t\t\t\t\t) {\n\t\t\t\t\t\tisAnyRectInViewport = true\n\t\t\t\t\t\tbreak // Found a visible rect in viewport, no need to check others\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!isAnyRectVisible || !isAnyRectInViewport) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check parent visibility\n\t\t\tconst parentElement = textNode.parentElement\n\t\t\tif (!parentElement) return false\n\n\t\t\ttry {\n\t\t\t\treturn parentElement.checkVisibility({\n\t\t\t\t\tcheckOpacity: true,\n\t\t\t\t\tcheckVisibilityCSS: true,\n\t\t\t\t})\n\t\t\t} catch (e) {\n\t\t\t\t// Fallback if checkVisibility is not supported\n\t\t\t\tconst style = window.getComputedStyle(parentElement)\n\t\t\t\treturn style.display !== 'none' && style.visibility !== 'hidden' && style.opacity !== '0'\n\t\t\t}\n\t\t} catch (e) {\n\t\t\tconsole.warn('Error checking text node visibility:', e)\n\t\t\treturn false\n\t\t}\n\t}\n\n\t/**\n\t * Checks if an element is accepted.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is accepted.\n\t */\n\tfunction isElementAccepted(element) {\n\t\tif (!element || !element.tagName) return false\n\n\t\t// Always accept body and common container elements\n\t\tconst alwaysAccept = new Set([\n\t\t\t'body',\n\t\t\t'div',\n\t\t\t'main',\n\t\t\t'article',\n\t\t\t'section',\n\t\t\t'nav',\n\t\t\t'header',\n\t\t\t'footer',\n\t\t])\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\tif (alwaysAccept.has(tagName)) return true\n\n\t\tconst leafElementDenyList = new Set([\n\t\t\t'svg',\n\t\t\t'script',\n\t\t\t'style',\n\t\t\t'link',\n\t\t\t'meta',\n\t\t\t'noscript',\n\t\t\t'template',\n\t\t])\n\n\t\treturn !leafElementDenyList.has(tagName)\n\t}\n\n\t/**\n\t * Checks if an element is visible.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is visible.\n\t */\n\tfunction isElementVisible(element) {\n\t\tconst style = getCachedComputedStyle(element)\n\t\treturn (\n\t\t\telement.offsetWidth > 0 &&\n\t\t\telement.offsetHeight > 0 &&\n\t\t\tstyle?.visibility !== 'hidden' &&\n\t\t\tstyle?.display !== 'none'\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element is interactive.\n\t *\n\t * lots of comments, and uncommented code - to show the logic of what we already tried\n\t *\n\t * One of the things we tried at the beginning was also to use event listeners, and other fancy class, style stuff -> what actually worked best was just combining most things with computed cursor style :)\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t */\n\tfunction isInteractiveElement(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\t/**\n\t\t * @edit add interactiveBlacklist interactiveWhitelist\n\t\t */\n\t\tif (interactiveBlacklist.includes(element)) {\n\t\t\treturn false // Skip blacklisted elements\n\t\t}\n\t\tif (interactiveWhitelist.includes(element)) {\n\t\t\treturn true // Skip whitelisted elements\n\t\t}\n\n\t\t// Cache the tagName and style lookups\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst style = getCachedComputedStyle(element)\n\n\t\t// Define interactive cursors\n\t\tconst interactiveCursors = new Set([\n\t\t\t'pointer', // Link/clickable elements\n\t\t\t'move', // Movable elements\n\t\t\t'text', // Text selection\n\t\t\t'grab', // Grabbable elements\n\t\t\t'grabbing', // Currently grabbing\n\t\t\t'cell', // Table cell selection\n\t\t\t'copy', // Copy operation\n\t\t\t'alias', // Alias creation\n\t\t\t'all-scroll', // Scrollable content\n\t\t\t'col-resize', // Column resize\n\t\t\t'context-menu', // Context menu available\n\t\t\t'crosshair', // Precise selection\n\t\t\t'e-resize', // East resize\n\t\t\t'ew-resize', // East-west resize\n\t\t\t'help', // Help available\n\t\t\t'n-resize', // North resize\n\t\t\t'ne-resize', // Northeast resize\n\t\t\t'nesw-resize', // Northeast-southwest resize\n\t\t\t'ns-resize', // North-south resize\n\t\t\t'nw-resize', // Northwest resize\n\t\t\t'nwse-resize', // Northwest-southeast resize\n\t\t\t'row-resize', // Row resize\n\t\t\t's-resize', // South resize\n\t\t\t'se-resize', // Southeast resize\n\t\t\t'sw-resize', // Southwest resize\n\t\t\t'vertical-text', // Vertical text selection\n\t\t\t'w-resize', // West resize\n\t\t\t'zoom-in', // Zoom in\n\t\t\t'zoom-out', // Zoom out\n\t\t])\n\n\t\t// Define non-interactive cursors\n\t\tconst nonInteractiveCursors = new Set([\n\t\t\t'not-allowed', // Action not allowed\n\t\t\t'no-drop', // Drop not allowed\n\t\t\t'wait', // Processing\n\t\t\t'progress', // In progress\n\t\t\t'initial', // Initial value\n\t\t\t'inherit', // Inherited value\n\t\t\t//? Let's just include all potentially clickable elements that are not specifically blocked\n\t\t\t// 'none', // No cursor\n\t\t\t// 'default', // Default cursor\n\t\t\t// 'auto', // Browser default\n\t\t])\n\n\t\t/**\n\t\t * Checks if an element has an interactive pointer.\n\t\t *\n\t\t * @param {HTMLElement} element - The element to check.\n\t\t * @returns {boolean} Whether the element has an interactive pointer.\n\t\t */\n\t\tfunction doesElementHaveInteractivePointer(element) {\n\t\t\tif (element.tagName.toLowerCase() === 'html') return false\n\n\t\t\tif (style?.cursor && interactiveCursors.has(style.cursor)) return true\n\n\t\t\treturn false\n\t\t}\n\n\t\tlet isInteractiveCursor = doesElementHaveInteractivePointer(element)\n\n\t\t// Genius fix for almost all interactive elements\n\t\tif (isInteractiveCursor) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveElements = new Set([\n\t\t\t'a', // Links\n\t\t\t'button', // Buttons\n\t\t\t'input', // All input types (text, checkbox, radio, etc.)\n\t\t\t'select', // Dropdown menus\n\t\t\t'textarea', // Text areas\n\t\t\t'details', // Expandable details\n\t\t\t'summary', // Summary element (clickable part of details)\n\t\t\t'label', // Form labels (often clickable)\n\t\t\t'option', // Select options\n\t\t\t'optgroup', // Option groups\n\t\t\t'fieldset', // Form fieldsets (can be interactive with legend)\n\t\t\t'legend', // Fieldset legends\n\t\t])\n\n\t\t// Define explicit disable attributes and properties\n\t\tconst explicitDisableTags = new Set([\n\t\t\t'disabled', // Standard disabled attribute\n\t\t\t// 'aria-disabled', // ARIA disabled state\n\t\t\t'readonly', // Read-only state\n\t\t\t// 'aria-readonly', // ARIA read-only state\n\t\t\t// 'aria-hidden', // Hidden from accessibility\n\t\t\t// 'hidden', // Hidden attribute\n\t\t\t// 'inert', // Inert attribute\n\t\t\t// 'aria-inert', // ARIA inert state\n\t\t\t// 'tabindex=\"-1\"', // Removed from tab order\n\t\t\t// 'aria-hidden=\"true\"' // Hidden from screen readers\n\t\t])\n\n\t\t// handle inputs, select, checkbox, radio, textarea, button and make sure they are not cursor style disabled/not-allowed\n\t\tif (interactiveElements.has(tagName)) {\n\t\t\t// Check for non-interactive cursor\n\t\t\tif (style?.cursor && nonInteractiveCursors.has(style.cursor)) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for explicit disable attributes\n\t\t\tfor (const disableTag of explicitDisableTags) {\n\t\t\t\tif (\n\t\t\t\t\telement.hasAttribute(disableTag) ||\n\t\t\t\t\telement.getAttribute(disableTag) === 'true' ||\n\t\t\t\t\telement.getAttribute(disableTag) === ''\n\t\t\t\t) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Check for disabled property on form elements\n\t\t\tif (element.disabled) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for readonly property on form elements\n\t\t\tif (element.readOnly) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\t// Check for inert property\n\t\t\tif (element.inert) {\n\t\t\t\treturn false\n\t\t\t}\n\n\t\t\treturn true\n\t\t}\n\n\t\tconst role = element.getAttribute('role')\n\t\tconst ariaRole = element.getAttribute('aria-role')\n\n\t\t// Check for contenteditable attribute\n\t\tif (element.getAttribute('contenteditable') === 'true' || element.isContentEditable) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Added enhancement to capture dropdown interactive elements\n\t\tif (\n\t\t\telement.classList &&\n\t\t\t(element.classList.contains('button') ||\n\t\t\t\telement.classList.contains('dropdown-toggle') ||\n\t\t\t\telement.getAttribute('data-index') ||\n\t\t\t\telement.getAttribute('data-toggle') === 'dropdown' ||\n\t\t\t\telement.getAttribute('aria-haspopup') === 'true')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst interactiveRoles = new Set([\n\t\t\t'button', // Directly clickable element\n\t\t\t// 'link', // Clickable link\n\t\t\t'menu', // Menu container (ARIA menus)\n\t\t\t'menubar', // Menu bar container\n\t\t\t'menuitem', // Clickable menu item\n\t\t\t'menuitemradio', // Radio-style menu item (selectable)\n\t\t\t'menuitemcheckbox', // Checkbox-style menu item (toggleable)\n\t\t\t'radio', // Radio button (selectable)\n\t\t\t'checkbox', // Checkbox (toggleable)\n\t\t\t'tab', // Tab (clickable to switch content)\n\t\t\t'switch', // Toggle switch (clickable to change state)\n\t\t\t'slider', // Slider control (draggable)\n\t\t\t'spinbutton', // Number input with up/down controls\n\t\t\t'combobox', // Dropdown with text input\n\t\t\t'searchbox', // Search input field\n\t\t\t'textbox', // Text input field\n\t\t\t'listbox', // Selectable list\n\t\t\t'option', // Selectable option in a list\n\t\t\t'scrollbar', // Scrollable control\n\t\t])\n\n\t\t// Basic role/attribute checks\n\t\tconst hasInteractiveRole =\n\t\t\tinteractiveElements.has(tagName) ||\n\t\t\t(role && interactiveRoles.has(role)) ||\n\t\t\t(ariaRole && interactiveRoles.has(ariaRole))\n\n\t\tif (hasInteractiveRole) return true\n\n\t\t// check whether element has event listeners by window.getEventListeners\n\t\ttry {\n\t\t\tif (typeof getEventListeners === 'function') {\n\t\t\t\tconst listeners = getEventListeners(element)\n\t\t\t\tconst mouseEvents = ['click', 'mousedown', 'mouseup', 'dblclick']\n\t\t\t\tfor (const eventType of mouseEvents) {\n\t\t\t\t\tif (listeners[eventType] && listeners[eventType].length > 0) {\n\t\t\t\t\t\treturn true // Found a mouse interaction listener\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListeners doesn't work in page.evaluate context)\n\t\t\tconst commonMouseAttrs = ['onclick', 'onmousedown', 'onmouseup', 'ondblclick']\n\t\t\tfor (const attr of commonMouseAttrs) {\n\t\t\t\tif (element.hasAttribute(attr) || typeof element[attr] === 'function') {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t/**\n\t\t * @edit scrollable element detection\n\t\t */\n\t\tif (isScrollableElement(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\treturn false\n\t}\n\n\t/**\n\t * Checks if an element is the topmost element at its position.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is the topmost element at its position.\n\t */\n\tfunction isTopElement(element) {\n\t\t// Special case: when viewportExpansion is -1, consider all elements as \"top\" elements\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = getCachedClientRects(element) // Replace element.getClientRects()\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\treturn false // No geometry, cannot be top\n\t\t}\n\n\t\tlet isAnyRectInViewport = false\n\t\tfor (const rect of rects) {\n\t\t\t// Use the same logic as isInExpandedViewport check\n\t\t\tif (\n\t\t\t\trect.width > 0 &&\n\t\t\t\trect.height > 0 &&\n\t\t\t\t!(\n\t\t\t\t\t// Only check non-empty rects\n\t\t\t\t\t(\n\t\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t\t)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\tisAnyRectInViewport = true\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\n\t\tif (!isAnyRectInViewport) {\n\t\t\treturn false // All rects are outside the viewport area\n\t\t}\n\n\t\t// Find the correct document context and root element\n\t\tlet doc = element.ownerDocument\n\n\t\t// If we're in an iframe, elements are considered top by default\n\t\tif (doc !== window.document) {\n\t\t\treturn true\n\t\t}\n\n\t\t/**\n\t\t * @edit improve `sampleRect`, filter out rects with 0 area\n\t\t */\n\t\t// find a rect that has width and height as sample\n\t\tlet rect = Array.from(rects).find((r) => r.width > 0 && r.height > 0)\n\t\tif (!rect) {\n\t\t\treturn false // No valid rect found\n\t\t}\n\n\t\t// For shadow DOM, we need to check within its own root context\n\t\tconst shadowRoot = element.getRootNode()\n\t\tif (shadowRoot instanceof ShadowRoot) {\n\t\t\tconst centerX = rect.left + rect.width / 2\n\t\t\tconst centerY = rect.top + rect.height / 2\n\n\t\t\ttry {\n\t\t\t\tconst topEl = shadowRoot.elementFromPoint(centerX, centerY)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== shadowRoot) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t}\n\n\t\tconst margin = 5\n\n\t\t// For elements in viewport, check if they're topmost. Do the check in the\n\t\t// center of the element and at the corners to ensure we catch more cases.\n\t\tconst checkPoints = [\n\t\t\t// Initially only this was used, but it was not enough\n\t\t\t{ x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 },\n\t\t\t{ x: rect.left + margin, y: rect.top + margin }, // top left\n\t\t\t// { x: rect.right - margin, y: rect.top + margin }, // top right\n\t\t\t// { x: rect.left + margin, y: rect.bottom - margin }, // bottom left\n\t\t\t{ x: rect.right - margin, y: rect.bottom - margin }, // bottom right\n\t\t]\n\n\t\treturn checkPoints.some(({ x, y }) => {\n\t\t\ttry {\n\t\t\t\tconst topEl = document.elementFromPoint(x, y)\n\t\t\t\tif (!topEl) return false\n\n\t\t\t\tlet current = topEl\n\t\t\t\twhile (current && current !== document.documentElement) {\n\t\t\t\t\tif (current === element) return true\n\t\t\t\t\tcurrent = current.parentElement\n\t\t\t\t}\n\t\t\t\treturn false\n\t\t\t} catch (e) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t})\n\t}\n\n\t/**\n\t * Checks if an element is within the expanded viewport.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @param {number} viewportExpansion - The viewport expansion.\n\t * @returns {boolean} Whether the element is within the expanded viewport.\n\t */\n\tfunction isInExpandedViewport(element, viewportExpansion) {\n\t\tif (viewportExpansion === -1) {\n\t\t\treturn true\n\t\t}\n\n\t\tconst rects = element.getClientRects() // Use getClientRects\n\n\t\tif (!rects || rects.length === 0) {\n\t\t\t// Fallback to getBoundingClientRect if getClientRects is empty,\n\t\t\t// useful for elements like <svg> that might not have client rects but have a bounding box.\n\t\t\tconst boundingRect = getCachedBoundingRect(element)\n\t\t\tif (!boundingRect || boundingRect.width === 0 || boundingRect.height === 0) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !(\n\t\t\t\tboundingRect.bottom < -viewportExpansion ||\n\t\t\t\tboundingRect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\tboundingRect.right < -viewportExpansion ||\n\t\t\t\tboundingRect.left > window.innerWidth + viewportExpansion\n\t\t\t)\n\t\t}\n\n\t\t// Check if *any* client rect is within the viewport\n\t\tfor (const rect of rects) {\n\t\t\tif (rect.width === 0 || rect.height === 0) continue // Skip empty rects\n\n\t\t\tif (\n\t\t\t\t!(\n\t\t\t\t\trect.bottom < -viewportExpansion ||\n\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\trect.left > window.innerWidth + viewportExpansion\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn true // Found at least one rect in the viewport\n\t\t\t}\n\t\t}\n\n\t\treturn false // No rects were found in the viewport\n\t}\n\n\t// /**\n\t// * Gets the effective scroll of an element.\n\t// *\n\t// * @param {HTMLElement} element - The element to get the effective scroll for.\n\t// * @returns {Object} The effective scroll of the element.\n\t// */\n\t// function getEffectiveScroll(element) {\n\t// let currentEl = element;\n\t// let scrollX = 0;\n\t// let scrollY = 0;\n\n\t// while (currentEl && currentEl !== document.documentElement) {\n\t// if (currentEl.scrollLeft || currentEl.scrollTop) {\n\t// scrollX += currentEl.scrollLeft;\n\t// scrollY += currentEl.scrollTop;\n\t// }\n\t// currentEl = currentEl.parentElement;\n\t// }\n\n\t// scrollX += window.scrollX;\n\t// scrollY += window.scrollY;\n\n\t// return { scrollX, scrollY };\n\t// }\n\n\t/**\n\t * Checks if an element is an interactive candidate.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is an interactive candidate.\n\t */\n\tfunction isInteractiveCandidate(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\n\t\t// Fast-path for common interactive elements\n\t\tconst interactiveElements = new Set([\n\t\t\t'a',\n\t\t\t'button',\n\t\t\t'input',\n\t\t\t'select',\n\t\t\t'textarea',\n\t\t\t'details',\n\t\t\t'summary',\n\t\t\t'label',\n\t\t])\n\n\t\tif (interactiveElements.has(tagName)) return true\n\n\t\t// Quick attribute checks without getting full lists\n\t\tconst hasQuickInteractiveAttr =\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\telement.hasAttribute('aria-') ||\n\t\t\telement.hasAttribute('data-action') ||\n\t\t\telement.getAttribute('contenteditable') === 'true'\n\n\t\treturn hasQuickInteractiveAttr\n\t}\n\n\t// --- Define constants for distinct interaction check ---\n\tconst DISTINCT_INTERACTIVE_TAGS = new Set([\n\t\t'a',\n\t\t'button',\n\t\t'input',\n\t\t'select',\n\t\t'textarea',\n\t\t'summary',\n\t\t'details',\n\t\t'label',\n\t\t'option',\n\t])\n\tconst INTERACTIVE_ROLES = new Set([\n\t\t'button',\n\t\t'link',\n\t\t'menuitem',\n\t\t'menuitemradio',\n\t\t'menuitemcheckbox',\n\t\t'radio',\n\t\t'checkbox',\n\t\t'tab',\n\t\t'switch',\n\t\t'slider',\n\t\t'spinbutton',\n\t\t'combobox',\n\t\t'searchbox',\n\t\t'textbox',\n\t\t'listbox',\n\t\t'option',\n\t\t'scrollbar',\n\t])\n\n\t/**\n\t * Heuristically determines if an element should be considered as independently interactive,\n\t * even if it's nested inside another interactive container.\n\t *\n\t * This function helps detect deeply nested actionable elements (e.g., menu items within a button)\n\t * that may not be picked up by strict interactivity checks.\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is heuristically interactive.\n\t */\n\tfunction isHeuristicallyInteractive(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) return false\n\n\t\t// Skip non-visible elements early for performance\n\t\tif (!isElementVisible(element)) return false\n\n\t\t// Check for common attributes that often indicate interactivity\n\t\tconst hasInteractiveAttributes =\n\t\t\telement.hasAttribute('role') ||\n\t\t\telement.hasAttribute('tabindex') ||\n\t\t\telement.hasAttribute('onclick') ||\n\t\t\ttypeof element.onclick === 'function'\n\n\t\t// Check for semantic class names suggesting interactivity\n\t\tconst hasInteractiveClass = /\\b(btn|clickable|menu|item|entry|link)\\b/i.test(\n\t\t\telement.className || ''\n\t\t)\n\n\t\t// Determine whether the element is inside a known interactive container\n\t\tconst isInKnownContainer = Boolean(\n\t\t\telement.closest('button,a,[role=\"button\"],.menu,.dropdown,.list,.toolbar')\n\t\t)\n\n\t\t// Ensure the element has at least one visible child (to avoid marking empty wrappers)\n\t\tconst hasVisibleChildren = [...element.children].some(isElementVisible)\n\n\t\t// Avoid highlighting elements whose parent is <body> (top-level wrappers)\n\t\tconst isParentBody = element.parentElement && element.parentElement.isSameNode(document.body)\n\n\t\treturn (\n\t\t\t(isInteractiveElement(element) || hasInteractiveAttributes || hasInteractiveClass) &&\n\t\t\thasVisibleChildren &&\n\t\t\tisInKnownContainer &&\n\t\t\t!isParentBody\n\t\t)\n\t}\n\n\t/**\n\t * Checks if an element likely represents a distinct interaction\n\t * separate from its parent (if the parent is also interactive).\n\t *\n\t * @param {HTMLElement} element - The element to check.\n\t * @returns {boolean} Whether the element is a distinct interaction.\n\t */\n\tfunction isElementDistinctInteraction(element) {\n\t\tif (!element || element.nodeType !== Node.ELEMENT_NODE) {\n\t\t\treturn false\n\t\t}\n\n\t\tconst tagName = element.tagName.toLowerCase()\n\t\tconst role = element.getAttribute('role')\n\n\t\t// Check if it's an iframe - always distinct boundary\n\t\tif (tagName === 'iframe') {\n\t\t\treturn true\n\t\t}\n\n\t\t// Check tag name\n\t\tif (DISTINCT_INTERACTIVE_TAGS.has(tagName)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check interactive roles\n\t\tif (role && INTERACTIVE_ROLES.has(role)) {\n\t\t\treturn true\n\t\t}\n\t\t// Check contenteditable\n\t\tif (element.isContentEditable || element.getAttribute('contenteditable') === 'true') {\n\t\t\treturn true\n\t\t}\n\t\t// Check for common testing/automation attributes\n\t\tif (\n\t\t\telement.hasAttribute('data-testid') ||\n\t\t\telement.hasAttribute('data-cy') ||\n\t\t\telement.hasAttribute('data-test')\n\t\t) {\n\t\t\treturn true\n\t\t}\n\t\t// Check for explicit onclick handler (attribute or property)\n\t\tif (element.hasAttribute('onclick') || typeof element.onclick === 'function') {\n\t\t\treturn true\n\t\t}\n\n\t\t// return false\n\n\t\t// Check for other common interaction event listeners\n\t\ttry {\n\t\t\tconst getEventListenersForNode =\n\t\t\t\telement?.ownerDocument?.defaultView?.getEventListenersForNode ||\n\t\t\t\twindow.getEventListenersForNode\n\t\t\tif (typeof getEventListenersForNode === 'function') {\n\t\t\t\tconst listeners = getEventListenersForNode(element)\n\t\t\t\tconst interactionEvents = [\n\t\t\t\t\t'click',\n\t\t\t\t\t'mousedown',\n\t\t\t\t\t'mouseup',\n\t\t\t\t\t'keydown',\n\t\t\t\t\t'keyup',\n\t\t\t\t\t'submit',\n\t\t\t\t\t'change',\n\t\t\t\t\t'input',\n\t\t\t\t\t'focus',\n\t\t\t\t\t'blur',\n\t\t\t\t]\n\t\t\t\tfor (const eventType of interactionEvents) {\n\t\t\t\t\tfor (const listener of listeners) {\n\t\t\t\t\t\tif (listener.type === eventType) {\n\t\t\t\t\t\t\treturn true // Found a common interaction listener\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Fallback: Check common event attributes if getEventListeners is not available (getEventListenersForNode doesn't work in page.evaluate context)\n\t\t\tconst commonEventAttrs = [\n\t\t\t\t'onmousedown',\n\t\t\t\t'onmouseup',\n\t\t\t\t'onkeydown',\n\t\t\t\t'onkeyup',\n\t\t\t\t'onsubmit',\n\t\t\t\t'onchange',\n\t\t\t\t'oninput',\n\t\t\t\t'onfocus',\n\t\t\t\t'onblur',\n\t\t\t]\n\t\t\tif (commonEventAttrs.some((attr) => element.hasAttribute(attr))) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t} catch (e) {\n\t\t\t// console.warn(`Could not check event listeners for ${element.tagName}:`, e);\n\t\t\t// If checking listeners fails, rely on other checks\n\t\t}\n\n\t\t// if the element is not strictly interactive but appears clickable based on heuristic signals\n\t\tif (isHeuristicallyInteractive(element)) {\n\t\t\treturn true\n\t\t}\n\n\t\t// Default to false: if it's interactive but doesn't match above,\n\t\t// assume it triggers the same action as the parent.\n\t\treturn false\n\t}\n\t// --- End distinct interaction check ---\n\n\t/**\n * Handles the logic for deciding whether to highlight an element and performing the highlight.\n * @param {\n {\n tagName: string;\n attributes: Record<string, string>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }} nodeData - The node data object.\n * @param {HTMLElement} node - The node to highlight.\n * @param {HTMLElement | null} parentIframe - The parent iframe node.\n * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n * @returns {boolean} Whether the element was highlighted.\n */\n\tfunction handleHighlighting(nodeData, node, parentIframe, isParentHighlighted) {\n\t\tif (!nodeData.isInteractive) return false // Not interactive, definitely don't highlight\n\n\t\tlet shouldHighlight = false\n\t\tif (!isParentHighlighted) {\n\t\t\t// Parent wasn't highlighted, this interactive node can be highlighted.\n\t\t\tshouldHighlight = true\n\t\t} else {\n\t\t\t// Parent *was* highlighted. Only highlight this node if it represents a distinct interaction.\n\t\t\tif (isElementDistinctInteraction(node)) {\n\t\t\t\tshouldHighlight = true\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (parent highlighted)`);\n\t\t\t\tshouldHighlight = false\n\t\t\t}\n\t\t}\n\n\t\tif (shouldHighlight) {\n\t\t\t// Check viewport status before assigning index and highlighting\n\t\t\tnodeData.isInViewport = isInExpandedViewport(node, viewportExpansion)\n\n\t\t\t// When viewportExpansion is -1, all interactive elements should get a highlight index\n\t\t\t// regardless of viewport status\n\t\t\tif (nodeData.isInViewport || viewportExpansion === -1) {\n\t\t\t\tnodeData.highlightIndex = highlightIndex++\n\n\t\t\t\tif (doHighlightElements) {\n\t\t\t\t\tif (focusHighlightIndex >= 0) {\n\t\t\t\t\t\tif (focusHighlightIndex === nodeData.highlightIndex) {\n\t\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\thighlightElement(node, nodeData.highlightIndex, parentIframe)\n\t\t\t\t\t}\n\t\t\t\t\treturn true // Successfully highlighted\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// console.log(`Skipping highlight for ${nodeData.tagName} (outside viewport)`);\n\t\t\t}\n\t\t}\n\n\t\treturn false // Did not highlight\n\t}\n\n\t/**\n\t * Creates a node data object for a given node and its descendants.\n\t *\n\t * @param {HTMLElement} node - The node to process.\n\t * @param {HTMLElement | null} parentIframe - The parent iframe node.\n\t * @param {boolean} isParentHighlighted - Whether the parent node is highlighted.\n\t * @returns {string | null} The ID of the node data object, or null if the node is not processed.\n\t */\n\tfunction buildDomTree(node, parentIframe = null, isParentHighlighted = false) {\n\t\t// Fast rejection checks first\n\t\tif (\n\t\t\t!node ||\n\t\t\tnode.id === HIGHLIGHT_CONTAINER_ID ||\n\t\t\t(node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE)\n\t\t) {\n\t\t\treturn null\n\t\t}\n\n\t\tif (!node || node.id === HIGHLIGHT_CONTAINER_ID) {\n\t\t\treturn null\n\t\t}\n\n\t\t/**\n\t\t * @edit add `data-browser-use-ignore` attribute\n\t\t */\n\t\tif (node.dataset?.browserUseIgnore === 'true') {\n\t\t\treturn true // Skip this node and its children\n\t\t}\n\n\t\t// Special handling for root node (body)\n\t\tif (node === document.body) {\n\t\t\tconst nodeData = {\n\t\t\t\ttagName: 'body',\n\t\t\t\tattributes: {},\n\t\t\t\txpath: '/body',\n\t\t\t\tchildren: [],\n\t\t\t}\n\n\t\t\t// Process children of body\n\t\t\tfor (const child of node.childNodes) {\n\t\t\t\tconst domElement = buildDomTree(child, parentIframe, false) // Body's children have no highlighted parent initially\n\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = nodeData\n\t\t\treturn id\n\t\t}\n\n\t\t// Early bailout for non-element nodes except text\n\t\tif (node.nodeType !== Node.ELEMENT_NODE && node.nodeType !== Node.TEXT_NODE) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Process text nodes\n\t\tif (node.nodeType === Node.TEXT_NODE) {\n\t\t\tconst textContent = node.textContent?.trim()\n\t\t\tif (!textContent) {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\t// Only check visibility for text nodes that might be visible\n\t\t\tconst parentElement = node.parentElement\n\t\t\tif (!parentElement || parentElement.tagName.toLowerCase() === 'script') {\n\t\t\t\treturn null\n\t\t\t}\n\n\t\t\tconst id = `${ID.current++}`\n\t\t\tDOM_HASH_MAP[id] = {\n\t\t\t\ttype: 'TEXT_NODE',\n\t\t\t\ttext: textContent,\n\t\t\t\tisVisible: isTextNodeVisible(node),\n\t\t\t}\n\t\t\treturn id\n\t\t}\n\n\t\t// Quick checks for element nodes\n\t\tif (node.nodeType === Node.ELEMENT_NODE && !isElementAccepted(node)) {\n\t\t\treturn null\n\t\t}\n\n\t\t// Early viewport check - only filter out elements clearly outside viewport\n\t\t// The getBoundingClientRect() of the Shadow DOM host element may return width/height = 0\n\t\tif (viewportExpansion !== -1 && !node.shadowRoot) {\n\t\t\tconst rect = getCachedBoundingRect(node) // Keep for initial quick check\n\t\t\tconst style = getCachedComputedStyle(node)\n\n\t\t\t// Skip viewport check for fixed/sticky elements as they may appear anywhere\n\t\t\tconst isFixedOrSticky = style && (style.position === 'fixed' || style.position === 'sticky')\n\n\t\t\t// Check if element has actual dimensions using offsetWidth/Height (quick check)\n\t\t\tconst hasSize = node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\t// Use getBoundingClientRect for the quick OUTSIDE check.\n\t\t\t// isInExpandedViewport will do the more accurate check later if needed.\n\t\t\tif (\n\t\t\t\t!rect ||\n\t\t\t\t(!isFixedOrSticky &&\n\t\t\t\t\t!hasSize &&\n\t\t\t\t\t(rect.bottom < -viewportExpansion ||\n\t\t\t\t\t\trect.top > window.innerHeight + viewportExpansion ||\n\t\t\t\t\t\trect.right < -viewportExpansion ||\n\t\t\t\t\t\trect.left > window.innerWidth + viewportExpansion))\n\t\t\t) {\n\t\t\t\t// console.log(\"Skipping node outside viewport (quick check):\", node.tagName, rect);\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n * @type {\n {\n tagName: string;\n attributes: Record<string, string | null>;\n xpath: any;\n children: never[];\n isVisible?: boolean;\n isTopElement?: boolean;\n isInteractive?: boolean;\n isInViewport?: boolean;\n highlightIndex?: number;\n shadowRoot?: boolean;\n }\n } nodeData - The node data object.\n */\n\t\tconst nodeData = {\n\t\t\ttagName: node.tagName.toLowerCase(),\n\t\t\tattributes: {},\n\n\t\t\t/**\n\t\t\t * @edit no need for xpath\n\t\t\t */\n\t\t\t// xpath: getXPathTree(node, true),\n\n\t\t\tchildren: [],\n\t\t}\n\n\t\t// Get attributes for interactive elements or potential text containers\n\t\tif (\n\t\t\tisInteractiveCandidate(node) ||\n\t\t\tnode.tagName.toLowerCase() === 'iframe' ||\n\t\t\tnode.tagName.toLowerCase() === 'body'\n\t\t) {\n\t\t\tconst attributeNames = node.getAttributeNames?.() || []\n\t\t\tfor (const name of attributeNames) {\n\t\t\t\tconst value = node.getAttribute(name)\n\t\t\t\tnodeData.attributes[name] = value\n\t\t\t}\n\n\t\t\t/**\n\t\t\t * @edit @workaround input.checked\n\t\t\t */\n\t\t\tif (\n\t\t\t\tnode.tagName.toLowerCase() === 'input' &&\n\t\t\t\t(node.type === 'checkbox' || node.type === 'radio')\n\t\t\t) {\n\t\t\t\tnodeData.attributes.checked = node.checked ? 'true' : 'false' // Store as string for consistency\n\t\t\t}\n\t\t}\n\n\t\tlet nodeWasHighlighted = false\n\t\t// Perform visibility, interactivity, and highlighting checks\n\t\tif (node.nodeType === Node.ELEMENT_NODE) {\n\t\t\tnodeData.isVisible = isElementVisible(node) // isElementVisible uses offsetWidth/Height, which is fine\n\t\t\tif (nodeData.isVisible) {\n\t\t\t\tnodeData.isTopElement = isTopElement(node)\n\n\t\t\t\t// Special handling for ARIA menu containers - check interactivity even if not top element\n\t\t\t\tconst role = node.getAttribute('role')\n\t\t\t\tconst isMenuContainer = role === 'menu' || role === 'menubar' || role === 'listbox'\n\n\t\t\t\tif (nodeData.isTopElement || isMenuContainer) {\n\t\t\t\t\tnodeData.isInteractive = isInteractiveElement(node)\n\t\t\t\t\t// Call the dedicated highlighting function\n\t\t\t\t\tnodeWasHighlighted = handleHighlighting(nodeData, node, parentIframe, isParentHighlighted)\n\n\t\t\t\t\t/**\n\t\t\t\t\t * @edit direct dom ref\n\t\t\t\t\t */\n\t\t\t\t\tnodeData.ref = node\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Process children, with special handling for iframes and rich text editors\n\t\tif (node.tagName) {\n\t\t\tconst tagName = node.tagName.toLowerCase()\n\n\t\t\t// Handle iframes\n\t\t\tif (tagName === 'iframe') {\n\t\t\t\ttry {\n\t\t\t\t\tconst iframeDoc = node.contentDocument || node.contentWindow?.document\n\t\t\t\t\tif (iframeDoc) {\n\t\t\t\t\t\tfor (const child of iframeDoc.childNodes) {\n\t\t\t\t\t\t\tconst domElement = buildDomTree(child, node, false)\n\t\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {\n\t\t\t\t\tconsole.warn('Unable to access iframe:', e)\n\t\t\t\t}\n\t\t\t}\n\t\t\t// Handle rich text editors and contenteditable elements\n\t\t\telse if (\n\t\t\t\tnode.isContentEditable ||\n\t\t\t\tnode.getAttribute('contenteditable') === 'true' ||\n\t\t\t\tnode.id === 'tinymce' ||\n\t\t\t\tnode.classList.contains('mce-content-body') ||\n\t\t\t\t(tagName === 'body' && node.getAttribute('data-id')?.startsWith('mce_'))\n\t\t\t) {\n\t\t\t\t// Process all child nodes to capture formatted text\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Handle shadow DOM\n\t\t\t\tif (node.shadowRoot) {\n\t\t\t\t\tnodeData.shadowRoot = true\n\t\t\t\t\tfor (const child of node.shadowRoot.childNodes) {\n\t\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, nodeWasHighlighted)\n\t\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Handle regular elements\n\t\t\t\tfor (const child of node.childNodes) {\n\t\t\t\t\t// Pass the highlighted status of the *current* node to its children\n\t\t\t\t\tconst passHighlightStatusToChild = nodeWasHighlighted || isParentHighlighted\n\t\t\t\t\tconst domElement = buildDomTree(child, parentIframe, passHighlightStatusToChild)\n\t\t\t\t\tif (domElement) nodeData.children.push(domElement)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Skip empty anchor tags only if they have no dimensions and no children\n\t\tif (nodeData.tagName === 'a' && nodeData.children.length === 0 && !nodeData.attributes.href) {\n\t\t\t// Check if the anchor has actual dimensions\n\t\t\tconst rect = getCachedBoundingRect(node)\n\t\t\tconst hasSize =\n\t\t\t\t(rect && rect.width > 0 && rect.height > 0) || node.offsetWidth > 0 || node.offsetHeight > 0\n\n\t\t\tif (!hasSize) {\n\t\t\t\treturn null\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * @edit add `extra` field for extra data\n\t\t */\n\t\tnodeData.extra = extraData.get(node) || null\n\n\t\tconst id = `${ID.current++}`\n\t\tDOM_HASH_MAP[id] = nodeData\n\t\treturn id\n\t}\n\n\tconst rootId = buildDomTree(document.body)\n\n\t// Clear the cache before starting\n\tDOM_CACHE.clearCache()\n\n\treturn { rootId, map: DOM_HASH_MAP }\n}\n","import { VIEWPORT_EXPANSION } from '../constants'\nimport domTree from './dom_tree/index.js'\nimport {\n\tElementDomNode,\n\tFlatDomTree,\n\tInteractiveElementDomNode,\n\tTextDomNode,\n} from './dom_tree/type'\n\nexport interface DomConfig {\n\tinteractiveBlacklist?: (Element | (() => Element))[]\n\tinteractiveWhitelist?: (Element | (() => Element))[]\n\tinclude_attributes?: string[]\n\thighlightOpacity?: number\n\thighlightLabelOpacity?: number\n}\n\n/**\n * 用于检测可交互元素是否是新出现的。\n */\nconst newElementsCache = new WeakMap<HTMLElement, string>()\n\nexport function getFlatTree(config: DomConfig): FlatDomTree {\n\tconst interactiveBlacklist = [] as Element[]\n\tfor (const item of config.interactiveBlacklist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveBlacklist.push(item())\n\t\t} else {\n\t\t\tinteractiveBlacklist.push(item)\n\t\t}\n\t}\n\n\tconst interactiveWhitelist = [] as Element[]\n\tfor (const item of config.interactiveWhitelist || []) {\n\t\tif (typeof item === 'function') {\n\t\t\tinteractiveWhitelist.push(item())\n\t\t} else {\n\t\t\tinteractiveWhitelist.push(item)\n\t\t}\n\t}\n\n\tconst elements = domTree({\n\t\tdoHighlightElements: true,\n\t\tdebugMode: true,\n\t\tfocusHighlightIndex: -1,\n\t\tviewportExpansion: VIEWPORT_EXPANSION,\n\t\tinteractiveBlacklist,\n\t\tinteractiveWhitelist,\n\t\thighlightOpacity: config.highlightOpacity ?? 0.0,\n\t\thighlightLabelOpacity: config.highlightLabelOpacity ?? 0.1,\n\t}) as FlatDomTree\n\n\tconst currentUrl = window.location.href\n\n\t/**\n\t * 标记新出现的元素\n\t * @todo browser-use 使用 hash(位置,属性等信息) 来判断是否同一个元素,\n\t * 能够解决 1. 元素被删除后重新添加 2. 页面卸载 等问题。\n\t * 这里先简单做.\n\t */\n\tfor (const nodeId in elements.map) {\n\t\tconst node = elements.map[nodeId]\n\t\tif (node.isInteractive && node.ref) {\n\t\t\tconst ref = node.ref as HTMLElement\n\t\t\t// @note 这样太严格,元素是可以跨页面存在的\n\t\t\t// if (newElementsCache.get(ref) !== currentUrl) {\n\t\t\tif (!newElementsCache.has(ref)) {\n\t\t\t\tnewElementsCache.set(ref, currentUrl)\n\t\t\t\tnode.isNew = true\n\t\t\t}\n\t\t}\n\t}\n\n\treturn elements\n}\n\n/**\n * elementsToString 内部使用的类型\n */\ninterface TreeNode {\n\ttype: 'text' | 'element'\n\tparent: TreeNode | null\n\tchildren: TreeNode[]\n\tisVisible: boolean\n\t// Text node properties\n\ttext?: string\n\t// Element node properties\n\ttagName?: string\n\tattributes?: Record<string, string>\n\tisInteractive?: boolean\n\tisTopElement?: boolean\n\tisNew?: boolean\n\thighlightIndex?: number\n\textra?: Record<string, any>\n}\n\n/**\n * 对应 python 中的 views::clickable_elements_to_string,\n * 将 dom 信息处理成适合 llm 阅读的文本格式\n * @形如\n * ``` text\n * [0]<a aria-label=page-agent.js 首页 />\n * [1]<div >P />\n * [2]<div >page-agent.js\n * UI Agent in your webpage />\n * [3]<a >文档 />\n * [4]<a aria-label=查看源码(在新窗口打开)>源码 />\n * UI Agent in your webpage\n * 用户输入需求,AI 理解页面并自动操作。\n * [5]<a role=button>快速开始 />\n * [6]<a role=button>查看文档 />\n * 无需后端\n * ```\n * 其中可交互元素用序号标出,提示llm可以用序号操作。\n * 缩进代表父子关系。\n * 普通文本则直接列出来。\n *\n * @todo 数据脱敏过滤器\n */\nexport function flatTreeToString(flatTree: FlatDomTree, include_attributes?: string[]): string {\n\tconst DEFAULT_INCLUDE_ATTRIBUTES = [\n\t\t'title',\n\t\t'type',\n\t\t'checked',\n\t\t'name',\n\t\t'role',\n\t\t'value',\n\t\t'placeholder',\n\t\t'data-date-format',\n\t\t'alt',\n\t\t'aria-label',\n\t\t'aria-expanded',\n\t\t'data-state',\n\t\t'aria-checked',\n\n\t\t// @edit added for better form handling\n\t\t'id',\n\t\t'for',\n\n\t\t// for jump check\n\t\t'target',\n\n\t\t// absolute 定位的下拉菜单\n\t\t'aria-haspopup',\n\t\t'aria-controls',\n\t\t'aria-owns',\n\t]\n\n\tconst includeAttrs = [...(include_attributes || []), ...DEFAULT_INCLUDE_ATTRIBUTES]\n\n\t// Helper function to cap text length\n\tconst capTextLength = (text: string, maxLength: number): string => {\n\t\tif (text.length > maxLength) {\n\t\t\treturn text.substring(0, maxLength) + '...'\n\t\t}\n\t\treturn text\n\t}\n\n\t// Build tree structure from flat map\n\tconst buildTreeNode = (nodeId: string): TreeNode | null => {\n\t\tconst node = flatTree.map[nodeId]\n\t\tif (!node) return null\n\n\t\tif (node.type === 'TEXT_NODE') {\n\t\t\tconst textNode = node as TextDomNode\n\t\t\treturn {\n\t\t\t\ttype: 'text',\n\t\t\t\ttext: textNode.text,\n\t\t\t\tisVisible: textNode.isVisible,\n\t\t\t\tparent: null,\n\t\t\t\tchildren: [],\n\t\t\t}\n\t\t} else {\n\t\t\tconst elementNode = node as ElementDomNode\n\t\t\tconst children: TreeNode[] = []\n\n\t\t\tif (elementNode.children) {\n\t\t\t\tfor (const childId of elementNode.children) {\n\t\t\t\t\tconst child = buildTreeNode(childId)\n\t\t\t\t\tif (child) {\n\t\t\t\t\t\tchild.parent = null // Will be set later\n\t\t\t\t\t\tchildren.push(child)\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\ttype: 'element',\n\t\t\t\ttagName: elementNode.tagName,\n\t\t\t\tattributes: elementNode.attributes ?? {},\n\t\t\t\tisVisible: elementNode.isVisible ?? false,\n\t\t\t\tisInteractive: elementNode.isInteractive ?? false,\n\t\t\t\tisTopElement: elementNode.isTopElement ?? false,\n\t\t\t\tisNew: elementNode.isNew ?? false,\n\t\t\t\thighlightIndex: elementNode.highlightIndex,\n\t\t\t\tparent: null,\n\t\t\t\tchildren,\n\t\t\t\textra: elementNode.extra ?? {},\n\t\t\t}\n\t\t}\n\t}\n\n\t// Set parent references\n\tconst setParentReferences = (node: TreeNode, parent: TreeNode | null = null) => {\n\t\tnode.parent = parent\n\t\tfor (const child of node.children) {\n\t\t\tsetParentReferences(child, node)\n\t\t}\n\t}\n\n\t// Build root node\n\tconst rootNode = buildTreeNode(flatTree.rootId)\n\tif (!rootNode) return ''\n\n\tsetParentReferences(rootNode)\n\n\t// Helper to check if text node has parent with highlight index\n\tconst hasParentWithHighlightIndex = (node: TreeNode): boolean => {\n\t\tlet current = node.parent\n\t\twhile (current) {\n\t\t\tif (current.type === 'element' && current.highlightIndex !== undefined) {\n\t\t\t\treturn true\n\t\t\t}\n\t\t\tcurrent = current.parent\n\t\t}\n\t\treturn false\n\t}\n\n\t// Helper to check if parent is top element\n\t// const isParentTopElement = (node: TreeNode): boolean => {\n\t// \treturn node.parent?.type === 'element' && node.parent.isTopElement === true\n\t// }\n\n\t// Main processing function\n\tconst processNode = (node: TreeNode, depth: number, result: string[]): void => {\n\t\tlet nextDepth = depth\n\t\tconst depthStr = '\\t'.repeat(depth)\n\n\t\tif (node.type === 'element') {\n\t\t\t// Add element with highlight_index\n\t\t\tif (node.highlightIndex !== undefined) {\n\t\t\t\tnextDepth += 1\n\n\t\t\t\tconst text = getAllTextTillNextClickableElement(node)\n\t\t\t\tlet attributesHtmlStr = ''\n\n\t\t\t\tif (includeAttrs.length > 0 && node.attributes) {\n\t\t\t\t\tconst attributesToInclude: Record<string, string> = {}\n\n\t\t\t\t\t// Filter attributes\n\t\t\t\t\tfor (const key of includeAttrs) {\n\t\t\t\t\t\tconst value = node.attributes[key]\n\t\t\t\t\t\tif (value && value.trim() !== '') {\n\t\t\t\t\t\t\tattributesToInclude[key] = value.trim()\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove duplicate values (for attributes longer than 5 chars)\n\t\t\t\t\tconst orderedKeys = includeAttrs.filter((key) => key in attributesToInclude)\n\t\t\t\t\tif (orderedKeys.length > 1) {\n\t\t\t\t\t\tconst keysToRemove = new Set<string>()\n\t\t\t\t\t\tconst seenValues: Record<string, string> = {}\n\n\t\t\t\t\t\tfor (const key of orderedKeys) {\n\t\t\t\t\t\t\tconst value = attributesToInclude[key]\n\t\t\t\t\t\t\tif (value.length > 5) {\n\t\t\t\t\t\t\t\tif (value in seenValues) {\n\t\t\t\t\t\t\t\t\tkeysToRemove.add(key)\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\tseenValues[value] = key\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (const key of keysToRemove) {\n\t\t\t\t\t\t\tdelete attributesToInclude[key]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove role if it matches tagName\n\t\t\t\t\tif (attributesToInclude.role === node.tagName) {\n\t\t\t\t\t\tdelete attributesToInclude.role\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove attributes that duplicate text content\n\t\t\t\t\tconst attrsToRemoveIfTextMatches = ['aria-label', 'placeholder', 'title']\n\t\t\t\t\tfor (const attr of attrsToRemoveIfTextMatches) {\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tattributesToInclude[attr] &&\n\t\t\t\t\t\t\tattributesToInclude[attr].toLowerCase().trim() === text.toLowerCase().trim()\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tdelete attributesToInclude[attr]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (Object.keys(attributesToInclude).length > 0) {\n\t\t\t\t\t\tattributesHtmlStr = Object.entries(attributesToInclude)\n\t\t\t\t\t\t\t.map(([key, value]) => `${key}=${capTextLength(value, 20)}`)\n\t\t\t\t\t\t\t.join(' ')\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Build the line\n\t\t\t\tconst highlightIndicator = node.isNew\n\t\t\t\t\t? `*[${node.highlightIndex}]`\n\t\t\t\t\t: `[${node.highlightIndex}]`\n\t\t\t\tlet line = `${depthStr}${highlightIndicator}<${node.tagName ?? ''}`\n\n\t\t\t\tif (attributesHtmlStr) {\n\t\t\t\t\tline += ` ${attributesHtmlStr}`\n\t\t\t\t}\n\n\t\t\t\t/**\n\t\t\t\t * @edit scrollable 数据\n\t\t\t\t */\n\t\t\t\tif (node.extra) {\n\t\t\t\t\tif (node.extra.scrollable) {\n\t\t\t\t\t\tlet scrollDataText = ''\n\t\t\t\t\t\tif (node.extra.scrollData?.left)\n\t\t\t\t\t\t\tscrollDataText += `left=${node.extra.scrollData.left}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.top) scrollDataText += `top=${node.extra.scrollData.top}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.right)\n\t\t\t\t\t\t\tscrollDataText += `right=${node.extra.scrollData.right}, `\n\t\t\t\t\t\tif (node.extra.scrollData?.bottom)\n\t\t\t\t\t\t\tscrollDataText += `bottom=${node.extra.scrollData.bottom}`\n\n\t\t\t\t\t\tline += ` data-scrollable=\"${scrollDataText}\"`\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (text) {\n\t\t\t\t\tconst trimmedText = text.trim()\n\t\t\t\t\tif (!attributesHtmlStr) {\n\t\t\t\t\t\tline += ' '\n\t\t\t\t\t}\n\t\t\t\t\tline += `>${trimmedText}`\n\t\t\t\t} else if (!attributesHtmlStr) {\n\t\t\t\t\tline += ' '\n\t\t\t\t}\n\n\t\t\t\tline += ' />'\n\t\t\t\tresult.push(line)\n\t\t\t}\n\n\t\t\t// Process children regardless\n\t\t\tfor (const child of node.children) {\n\t\t\t\tprocessNode(child, nextDepth, result)\n\t\t\t}\n\t\t} else if (node.type === 'text') {\n\t\t\t// Add text only if it doesn't have a highlighted parent\n\t\t\tif (hasParentWithHighlightIndex(node)) {\n\t\t\t\treturn\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\tnode.parent &&\n\t\t\t\tnode.parent.type === 'element' &&\n\t\t\t\tnode.parent.isVisible &&\n\t\t\t\tnode.parent.isTopElement\n\t\t\t) {\n\t\t\t\tresult.push(`${depthStr}${node.text ?? ''}`)\n\t\t\t}\n\t\t}\n\t}\n\n\tconst result: string[] = []\n\tprocessNode(rootNode, 0, result)\n\treturn result.join('\\n')\n}\n\n// Get all text until next clickable element\nexport const getAllTextTillNextClickableElement = (node: TreeNode, maxDepth = -1): string => {\n\tconst textParts: string[] = []\n\n\tconst collectText = (currentNode: TreeNode, currentDepth: number) => {\n\t\tif (maxDepth !== -1 && currentDepth > maxDepth) {\n\t\t\treturn\n\t\t}\n\n\t\t// Skip this branch if we hit a highlighted element (except for the current node)\n\t\tif (\n\t\t\tcurrentNode.type === 'element' &&\n\t\t\tcurrentNode !== node &&\n\t\t\tcurrentNode.highlightIndex !== undefined\n\t\t) {\n\t\t\treturn\n\t\t}\n\n\t\tif (currentNode.type === 'text' && currentNode.text) {\n\t\t\ttextParts.push(currentNode.text)\n\t\t} else if (currentNode.type === 'element') {\n\t\t\tfor (const child of currentNode.children) {\n\t\t\t\tcollectText(child, currentDepth + 1)\n\t\t\t}\n\t\t}\n\t}\n\n\tcollectText(node, 0)\n\treturn textParts.join('\\n').trim()\n}\n\nexport function getSelectorMap(flatTree: FlatDomTree): Map<number, InteractiveElementDomNode> {\n\tconst selectorMap = new Map<number, InteractiveElementDomNode>()\n\n\tconst keys = Object.keys(flatTree.map)\n\tfor (const key of keys) {\n\t\tconst node = flatTree.map[key]\n\t\tif (node.isInteractive && typeof node.highlightIndex === 'number') {\n\t\t\tselectorMap.set(node.highlightIndex, node as InteractiveElementDomNode)\n\t\t}\n\t}\n\n\treturn selectorMap\n}\n\nexport function getElementTextMap(simplifiedHTML: string) {\n\tconst lines = simplifiedHTML\n\t\t.split('\\n')\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\tconst elementTextMap = new Map<number, string>()\n\tfor (const line of lines) {\n\t\tconst regex = /^\\[(\\d+)\\]<[^>]+>([^<]*)/\n\t\tconst match = regex.exec(line)\n\t\tif (match) {\n\t\t\tconst index = parseInt(match[1], 10)\n\t\t\telementTextMap.set(index, line)\n\t\t}\n\t}\n\n\treturn elementTextMap\n}\n\nexport function cleanUpHighlights() {\n\tconst cleanupFunctions = (window as any)._highlightCleanupFunctions || []\n\tfor (const cleanup of cleanupFunctions) {\n\t\tif (typeof cleanup === 'function') {\n\t\t\tcleanup()\n\t\t}\n\t}\n\n\t;(window as any)._highlightCleanupFunctions = []\n}\n\n// 监听 URL 的任何变化,立刻清空 highLights\nwindow.addEventListener('popstate', () => {\n\t// console.log('URL changed (popstate), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('hashchange', () => {\n\t// console.log('URL changed (hashchange), highlights cleaned up.')\n\tcleanUpHighlights()\n})\nwindow.addEventListener('beforeunload', () => {\n\t// console.log('Page is unloading, highlights cleaned up.')\n\tcleanUpHighlights()\n})\n\nconst navigation = (window as any).navigation\nif (navigation && typeof navigation.addEventListener === 'function') {\n\tnavigation.addEventListener('navigate', () => {\n\t\t// console.log('Navigation event detected, highlights cleaned up.')\n\t\tcleanUpHighlights()\n\t})\n} else {\n\t// 定时器\n\tlet currentUrl = window.location.href\n\tsetInterval(() => {\n\t\tif (window.location.href !== currentUrl) {\n\t\t\tcurrentUrl = window.location.href\n\t\t\t// console.log('URL changed (interval), highlights cleaned up.')\n\t\t\tcleanUpHighlights()\n\t\t}\n\t}, 500)\n}\n","export function getPageInfo() {\n\tconst viewport_width = window.innerWidth\n\tconst viewport_height = window.innerHeight\n\n\tconst page_width = Math.max(document.documentElement.scrollWidth, document.body.scrollWidth || 0)\n\tconst page_height = Math.max(\n\t\tdocument.documentElement.scrollHeight,\n\t\tdocument.body.scrollHeight || 0\n\t)\n\n\tconst scroll_x = window.scrollX || window.pageXOffset || document.documentElement.scrollLeft || 0\n\tconst scroll_y = window.scrollY || window.pageYOffset || document.documentElement.scrollTop || 0\n\n\tconst pixels_below = Math.max(0, page_height - (window.innerHeight + scroll_y))\n\tconst pixels_right = Math.max(0, page_width - (window.innerWidth + scroll_x))\n\n\treturn {\n\t\t// Current viewport dimensions\n\t\tviewport_width,\n\t\tviewport_height,\n\n\t\t// Total page dimensions\n\t\tpage_width,\n\t\tpage_height,\n\n\t\t// Current scroll position\n\t\tscroll_x,\n\t\tscroll_y,\n\n\t\tpixels_above: scroll_y,\n\t\tpixels_below,\n\n\t\tpages_above: viewport_height > 0 ? scroll_y / viewport_height : 0,\n\t\tpages_below: viewport_height > 0 ? pixels_below / viewport_height : 0,\n\t\ttotal_pages: viewport_height > 0 ? page_height / viewport_height : 0,\n\n\t\tcurrent_page_position: scroll_y / Math.max(1, page_height - viewport_height),\n\n\t\tpixels_left: scroll_x,\n\t\tpixels_right,\n\t}\n}\n","import type { PageController } from '../PageController'\n\n// Find common React root elements and add data-page-agent-not-interactive attribute\nexport function patchReact(pageController: PageController) {\n\tconst reactRootElements = document.querySelectorAll(\n\t\t'[data-reactroot], [data-reactid], [data-react-checksum], #root, #app, [id^=\"root-\"], [id^=\"app-\"], #adex-wrapper, #adex-root'\n\t)\n\n\tfor (const element of reactRootElements) {\n\t\telement.setAttribute('data-page-agent-not-interactive', 'true')\n\t}\n}\n\n/**\n * @todo (Heavy, might have false negatives) Interaction detection, if element width/height equals body offsetWidth/Height, consider it root element and non-interactive (React often attaches many events to root elements, causing false positives)\n */\n","/**\n * Copyright (C) 2025 Alibaba Group Holding Limited\n * All rights reserved.\n *\n * PageController - Manages DOM operations and element interactions.\n * Designed to be independent of LLM and can be tested in unit tests.\n * All public methods are async for potential remote calling support.\n */\nimport {\n\tclickElement,\n\tgetElementByIndex,\n\tinputTextElement,\n\tscrollHorizontally,\n\tscrollVertically,\n\tselectOptionElement,\n} from './actions'\nimport { VIEWPORT_EXPANSION } from './constants'\nimport * as dom from './dom'\nimport type { FlatDomTree, InteractiveElementDomNode } from './dom/dom_tree/type'\nimport { getPageInfo } from './dom/getPageInfo'\nimport { patchReact } from './patches/react'\n\n/**\n * Configuration for PageController\n */\nexport interface PageControllerConfig extends dom.DomConfig {\n\tviewportExpansion?: number\n}\n\ninterface ActionResult {\n\tsuccess: boolean\n\tmessage: string\n}\n\n/**\n * PageController manages DOM state and element interactions.\n * It provides async methods for all DOM operations, keeping state isolated.\n *\n * @lifecycle\n * - beforeUpdate: Emitted before the DOM tree is updated.\n * - afterUpdate: Emitted after the DOM tree is updated.\n */\nexport class PageController extends EventTarget {\n\tprivate config: PageControllerConfig\n\n\t/** Corresponds to eval_page in browser-use */\n\tprivate flatTree: FlatDomTree | null = null\n\n\t/**\n\t * All highlighted index-mapped interactive elements\n\t * Corresponds to DOMState.selector_map in browser-use\n\t */\n\tprivate selectorMap = new Map<number, InteractiveElementDomNode>()\n\n\t/** Index -> element text description mapping */\n\tprivate elementTextMap = new Map<number, string>()\n\n\t/**\n\t * Simplified HTML for LLM consumption.\n\t * Corresponds to clickable_elements_to_string in browser-use\n\t */\n\tprivate simplifiedHTML = '<EMPTY>'\n\n\t/** last time the tree was updated */\n\tprivate lastTimeUpdate = 0\n\n\tconstructor(config: PageControllerConfig = {}) {\n\t\tsuper()\n\n\t\tthis.config = config\n\n\t\tpatchReact(this)\n\t}\n\n\t// ======= State Queries =======\n\n\t/**\n\t * Get current page URL\n\t */\n\tasync getCurrentUrl(): Promise<string> {\n\t\treturn window.location.href\n\t}\n\n\t/**\n\t * Get current page title\n\t */\n\tasync getPageTitle(): Promise<string> {\n\t\treturn document.title\n\t}\n\n\t/**\n\t * Get page scroll and size info\n\t */\n\tasync getPageInfo() {\n\t\treturn getPageInfo()\n\t}\n\n\t/**\n\t * Get the simplified HTML representation of the page.\n\t * This is used by LLM to understand the page structure.\n\t */\n\tasync getSimplifiedHTML(): Promise<string> {\n\t\treturn this.simplifiedHTML\n\t}\n\n\t/**\n\t * Get text description for an element by index\n\t */\n\tasync getElementText(index: number): Promise<string | undefined> {\n\t\treturn this.elementTextMap.get(index)\n\t}\n\n\t/**\n\t * Get total number of indexed interactive elements\n\t */\n\tasync getElementCount(): Promise<number> {\n\t\treturn this.selectorMap.size\n\t}\n\n\t/**\n\t * Get last tree update timestamp\n\t */\n\tasync getLastUpdateTime(): Promise<number> {\n\t\treturn this.lastTimeUpdate\n\t}\n\n\t/**\n\t * Get the viewport expansion setting\n\t */\n\tasync getViewportExpansion(): Promise<number> {\n\t\treturn this.config.viewportExpansion ?? VIEWPORT_EXPANSION\n\t}\n\n\t// ======= DOM Tree Operations =======\n\n\t/**\n\t * Update DOM tree, returns simplified HTML for LLM.\n\t * This is the main method to refresh the page state.\n\t */\n\tasync updateTree(): Promise<string> {\n\t\tthis.dispatchEvent(new Event('beforeUpdate'))\n\n\t\tthis.lastTimeUpdate = Date.now()\n\n\t\tdom.cleanUpHighlights()\n\n\t\tconst blacklist = [\n\t\t\t...(this.config.interactiveBlacklist || []),\n\t\t\t...document.querySelectorAll('[data-page-agent-not-interactive]').values(),\n\t\t]\n\n\t\tthis.flatTree = dom.getFlatTree({\n\t\t\t...this.config,\n\t\t\tinteractiveBlacklist: blacklist,\n\t\t})\n\n\t\tthis.simplifiedHTML = dom.flatTreeToString(this.flatTree, this.config.include_attributes)\n\n\t\tthis.selectorMap.clear()\n\t\tthis.selectorMap = dom.getSelectorMap(this.flatTree)\n\n\t\tthis.elementTextMap.clear()\n\t\tthis.elementTextMap = dom.getElementTextMap(this.simplifiedHTML)\n\n\t\tthis.dispatchEvent(new Event('afterUpdate'))\n\n\t\treturn this.simplifiedHTML\n\t}\n\n\t/**\n\t * Clean up all element highlights\n\t */\n\tasync cleanUpHighlights(): Promise<void> {\n\t\tdom.cleanUpHighlights()\n\t}\n\n\t// ======= Element Actions =======\n\n\t/**\n\t * Click element by index\n\t */\n\tasync clickElement(index: number): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait clickElement(element)\n\n\t\t\t// Handle links that open in new tabs\n\t\t\tif (element instanceof HTMLAnchorElement && element.target === '_blank') {\n\t\t\t\treturn {\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tmessage: `✅ Clicked element (${elemText ?? index}). ⚠️ Link opens in a new tab. You are not capable of reading new tabs.`,\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `✅ Clicked element (${elemText ?? index}).`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Failed to click element: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Input text into element by index\n\t */\n\tasync inputText(index: number, text: string): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait inputTextElement(element, text)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `✅ Input text (${text}) into element (${elemText ?? index}).`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Failed to input text: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Select dropdown option by index and option text\n\t */\n\tasync selectOption(index: number, optionText: string): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst element = getElementByIndex(this.selectorMap, index)\n\t\t\tconst elemText = this.elementTextMap.get(index)\n\t\t\tawait selectOptionElement(element as HTMLSelectElement, optionText)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `✅ Selected option (${optionText}) in element (${elemText ?? index}).`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Failed to select option: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Scroll vertically\n\t */\n\tasync scroll(options: {\n\t\tdown: boolean\n\t\tnumPages: number\n\t\tpixels?: number\n\t\tindex?: number\n\t}): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst { down, numPages, pixels, index } = options\n\n\t\t\tconst scrollAmount = pixels ?? numPages * (down ? 1 : -1) * window.innerHeight\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null\n\n\t\t\tconst message = await scrollVertically(down, scrollAmount, element)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Failed to scroll: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Scroll horizontally\n\t */\n\tasync scrollHorizontally(options: {\n\t\tright: boolean\n\t\tpixels: number\n\t\tindex?: number\n\t}): Promise<ActionResult> {\n\t\ttry {\n\t\t\tconst { right, pixels, index } = options\n\n\t\t\tconst scrollAmount = pixels * (right ? 1 : -1)\n\n\t\t\tconst element = index !== undefined ? getElementByIndex(this.selectorMap, index) : null\n\n\t\t\tconst message = await scrollHorizontally(right, scrollAmount, element)\n\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Failed to scroll horizontally: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Execute arbitrary JavaScript on the page\n\t */\n\tasync executeJavascript(script: string): Promise<ActionResult> {\n\t\ttry {\n\t\t\t// Wrap script in async function to support await\n\t\t\tconst asyncFunction = eval(`(async () => { ${script} })`)\n\t\t\tconst result = await asyncFunction()\n\t\t\treturn {\n\t\t\t\tsuccess: true,\n\t\t\t\tmessage: `✅ Executed JavaScript. Result: ${result}`,\n\t\t\t}\n\t\t} catch (error) {\n\t\t\treturn {\n\t\t\t\tsuccess: false,\n\t\t\t\tmessage: `❌ Error executing JavaScript: ${error}`,\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Dispose and clean up resources\n\t */\n\tdispose(): void {\n\t\tdom.cleanUpHighlights()\n\t\tthis.flatTree = null\n\t\tthis.selectorMap.clear()\n\t\tthis.elementTextMap.clear()\n\t\tthis.simplifiedHTML = '<EMPTY>'\n\t}\n}\n"],"names":["dy","el","dx","args","parentElement","element","rect","viewportExpansion","nodeData","id","result","dom.cleanUpHighlights","dom.getFlatTree","dom.flatTreeToString","dom.getSelectorMap","dom.getElementTextMap"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@page-agent/page-controller",
|
|
3
|
+
"version": "0.0.6",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/lib/page-controller.js",
|
|
6
|
+
"module": "./dist/lib/page-controller.js",
|
|
7
|
+
"types": "./dist/lib/PageController.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/lib/PageController.d.ts",
|
|
11
|
+
"import": "./dist/lib/page-controller.js",
|
|
12
|
+
"default": "./dist/lib/page-controller.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist/",
|
|
17
|
+
"README.md",
|
|
18
|
+
"LICENSE"
|
|
19
|
+
],
|
|
20
|
+
"description": "Page controller for page-agent - DOM operations and element interactions",
|
|
21
|
+
"keywords": [
|
|
22
|
+
"page-agent",
|
|
23
|
+
"dom",
|
|
24
|
+
"browser-automation",
|
|
25
|
+
"web-automation"
|
|
26
|
+
],
|
|
27
|
+
"author": "Simon<gaomeng1900>",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "https://github.com/alibaba/page-agent.git"
|
|
32
|
+
},
|
|
33
|
+
"homepage": "https://alibaba.github.io/page-agent/",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "vite build",
|
|
36
|
+
"build:watch": "vite build --watch",
|
|
37
|
+
"prepublishOnly": "node -e \"const fs=require('fs');['LICENSE'].forEach(f=>fs.copyFileSync('../../'+f,f))\"",
|
|
38
|
+
"postpublish": "node -e \"['LICENSE'].forEach(f=>{try{require('fs').unlinkSync(f)}catch{}})\""
|
|
39
|
+
}
|
|
40
|
+
}
|