ff-dom 2.0.8 → 3.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.browser.js","sources":["../src/utils/xpathHelpers.ts","../src/utils/xpath.ts","../src/utils/referenceXpath.ts","../src/utils/cssSelector.ts","../src/utils/getElementsFromHTML.ts","../src/browser/xpath.ts"],"sourcesContent":["export const reWhiteSpace = /^[\\S]+( [\\S]+)*$/i;\r\nexport let cspEnabled: boolean = false;\r\nconst xpathCache: { [x: string]: number } = {};\r\nlet relativeXPathCache = new Map();\r\nexport let modifiedElementAttributes: {\r\n url: string | null;\r\n attributeName: string | null;\r\n element: HTMLElement | Element;\r\n doc: Document;\r\n}[] = [];\r\nlet mutationObserver: MutationObserver;\r\n\r\nexport const createObserver = (addedNodeCallBack: Function) => {\r\n mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n if (mutation?.addedNodes?.length) {\r\n addedNodeCallBack(mutation?.addedNodes);\r\n }\r\n\r\n if (mutation.target instanceof HTMLElement) {\r\n if (\r\n mutation?.type === \"attributes\" &&\r\n mutation.attributeName === \"class\" &&\r\n ((isSvg(mutation.target) &&\r\n mutation.oldValue?.trim() ===\r\n mutation.target.classList.value?.trim()) ||\r\n mutation.target.classList?.value\r\n ?.replace(mutation.oldValue!, \"\")\r\n .trim() === \"marked-element-temp\" ||\r\n mutation?.oldValue\r\n ?.replace(mutation.target.classList?.value, \"\")\r\n .trim() === \"marked-element-temp\")\r\n ) {\r\n } else if (\r\n mutation?.type === \"attributes\" &&\r\n ![\"flndisabled\"].includes(mutation.attributeName!)\r\n ) {\r\n modifiedElementAttributes.push({\r\n url: mutation.target.baseURI,\r\n attributeName: mutation.attributeName,\r\n element: mutation.target,\r\n doc: mutation.target.ownerDocument\r\n });\r\n }\r\n }\r\n });\r\n });\r\n};\r\nexport const startObserver = (\r\n target: Node,\r\n options: MutationObserverInit | undefined\r\n) => {\r\n mutationObserver?.observe(target, options);\r\n};\r\n\r\nexport const stopObserver = () => {\r\n mutationObserver?.disconnect();\r\n};\r\n\r\nexport const isNumberExist = (str: string): boolean => {\r\n const hasNumber = /\\d/;\r\n return hasNumber.test(str);\r\n};\r\n\r\nexport const buildPattern = (\r\n pattern: string,\r\n isSvg: boolean,\r\n tagName: string\r\n): string => {\r\n return isSvg\r\n ? `//*[local-name()='${tagName}' and ${pattern}]`\r\n : `//${tagName}[${pattern}]`;\r\n};\r\n\r\nexport const getTextContent = (\r\n targetElement: HTMLElement | Element\r\n): string => {\r\n const textContent = targetElement?.textContent;\r\n if (cspEnabled) {\r\n if (textContent) {\r\n const tooltip = document.querySelector(\".flntooltip\") as HTMLElement;\r\n if (tooltip) {\r\n const lastIndex = textContent.lastIndexOf(tooltip.innerText);\r\n if (\r\n lastIndex &&\r\n textContent.length === lastIndex + tooltip.innerText.length\r\n ) {\r\n return textContent.substring(0, lastIndex);\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nexport const getFilteredText = (element: Node): string => {\r\n return element?.childNodes[0]?.nodeValue || \"\";\r\n};\r\n\r\nexport const getCountOfXPath = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Node,\r\n multiElementReferenceMode: boolean = false\r\n): number => {\r\n try {\r\n let count;\r\n // Check if result is cached\r\n if (xpathCache[xpath] !== undefined) {\r\n count = xpathCache[xpath];\r\n } else {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n count = owner.evaluate(\r\n `count(${xpath})`,\r\n docmt,\r\n null,\r\n XPathResult.NUMBER_TYPE,\r\n null\r\n ).numberValue;\r\n xpathCache[xpath] = count;\r\n }\r\n\r\n if (multiElementReferenceMode && Array.isArray(element)) {\r\n if (count > 1) {\r\n const elementsFromXpath = getElementFromXpath(xpath, docmt, true);\r\n let nodex,\r\n matchedCount = 0;\r\n if (elementsFromXpath instanceof XPathResult) {\r\n while ((nodex = elementsFromXpath?.iterateNext())) {\r\n if (element.includes(nodex)) {\r\n matchedCount += 1;\r\n\r\n if (matchedCount === 2) break;\r\n }\r\n }\r\n }\r\n\r\n if (matchedCount !== 2) return 0;\r\n }\r\n } else {\r\n // Short-circuit if we only need to match one element\r\n if (count === 1) {\r\n const elementFromXpath = getElementFromXpath(xpath, docmt);\r\n return elementFromXpath === element ? count : 0; // Return 0 if no match\r\n }\r\n }\r\n return count; // Return the count\r\n } catch (error) {\r\n console.error(`Error evaluating XPath: ${xpath}`, error);\r\n return 0; // Return 0 on error to avoid re-processing\r\n }\r\n};\r\n\r\nexport const escapeCharacters = (text: string): string => {\r\n if (text) {\r\n if (!(text.indexOf('\"') === -1)) {\r\n return `'${text}'`;\r\n }\r\n if (!(text.indexOf(\"'\") === -1)) {\r\n return `\"${text}\"`;\r\n }\r\n }\r\n return `'${text}'`;\r\n};\r\n\r\nexport const removeParenthesis = (xpath: string): string => {\r\n const charArr = xpath.split(\"\");\r\n\r\n let count = charArr.length;\r\n const indexArray = [];\r\n\r\n while (charArr[count - 2] !== \"[\") {\r\n indexArray.push(charArr[count - 2]);\r\n count--;\r\n }\r\n\r\n indexArray.reverse();\r\n let finalStr = \"\";\r\n for (let i = 0; i < indexArray.length; i++) {\r\n finalStr += indexArray[i];\r\n }\r\n\r\n const endBracketLength = finalStr.length + 2;\r\n let firstpart = xpath.slice(0, xpath.length - endBracketLength);\r\n\r\n if (firstpart.startsWith(\"(\") && firstpart.endsWith(\")\")) {\r\n firstpart = firstpart.slice(1, -1);\r\n } else {\r\n firstpart = xpath;\r\n }\r\n\r\n return firstpart;\r\n};\r\n\r\nexport const findXpathWithIndex = (\r\n val: string,\r\n node: HTMLElement | Element,\r\n docmt: Node,\r\n count: number\r\n) => {\r\n try {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n let index = 0;\r\n if (count) {\r\n if (getCountOfXPath(`${val}[${count}]`, node, docmt) === 1) {\r\n return `${val}[${count}]`;\r\n }\r\n\r\n if (getCountOfXPath(`(${val})[${count}]`, node, docmt) === 1) {\r\n return `(${val})[${count}]`;\r\n }\r\n }\r\n\r\n const nodes = owner.evaluate(val, docmt, null, XPathResult.ANY_TYPE, null);\r\n let nodex;\r\n while ((nodex = nodes.iterateNext())) {\r\n index++;\r\n if (nodex.isSameNode(node)) {\r\n if (getCountOfXPath(`${val}[${index}]`, node, docmt) === 1) {\r\n return `${val}[${index}]`;\r\n }\r\n if (getCountOfXPath(`(${val})[${index}]`, node, docmt) === 1) {\r\n return `(${val})[${index}]`;\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nconst deleteLineGap = (a: string): string => {\r\n a &&= a.split(\"\\n\")[0].length > 0 ? a.split(\"\\n\")[0] : a.split(\"\\n\")[1];\r\n return a;\r\n};\r\n\r\nconst deleteGarbageFromInnerText = (a: string): string => {\r\n a = deleteLineGap(a);\r\n a = a\r\n .split(/[^\\u0000-\\u00ff]/)\r\n .reduce((b, c) => {\r\n return b.length > c.length ? b : c;\r\n }, \"\")\r\n .trim();\r\n return (a = a.split(\"/\")[0].trim());\r\n};\r\n\r\nexport const replaceWhiteSpaces = (str: string): string => {\r\n if (str) {\r\n return str.replace(/\\s\\s+/g, \" \").trim();\r\n }\r\n\r\n return str;\r\n};\r\n\r\nexport const getShadowRoot = (el: HTMLElement | Element): Element | null => {\r\n if (!el || !el?.getRootNode) return null;\r\n\r\n const root = el.getRootNode() as ShadowRoot;\r\n return root && root?.host ? (root as unknown as Element) : null;\r\n};\r\n\r\nexport const checkBlockedAttributes = (\r\n attribute: {\r\n name: string;\r\n value: string;\r\n },\r\n targetElement: HTMLElement | Element,\r\n isTarget: boolean\r\n): boolean => {\r\n\r\n if (!attribute?.value || typeof attribute?.value === \"boolean\") {\r\n return false;\r\n }\r\n const blockedValues = [\"true\", \"false\", \"on\", \"off\", \"flntooltip\"];\r\n if (blockedValues.some((x) => x === attribute.value)) {\r\n return false;\r\n }\r\n const blockedNames = [\"type\", \"style\", \"locator-data-tooltip\", \"value\"];\r\n if (blockedNames.some((x) => x === attribute.name)) {\r\n return false;\r\n }\r\n\r\n const isModified = modifiedElementAttributes?.find(\r\n (x) =>\r\n x.doc === targetElement.ownerDocument &&\r\n x.element === targetElement &&\r\n x.attributeName === attribute.name\r\n );\r\n if (isModified) {\r\n return false;\r\n }\r\n\r\n if (attribute?.name?.indexOf(\"on\") === 0 && attribute?.name?.length > 3) {\r\n return false;\r\n }\r\n\r\n if (typeof attribute.value === \"function\") {\r\n return false;\r\n }\r\n\r\n if (isTarget && isNumberExist(attribute.value)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\n\r\nexport const getRelationship = (a: HTMLElement, b: HTMLElement): string => {\r\n let pos = a.compareDocumentPosition(b);\r\n return pos === 2\r\n ? \"preceding\"\r\n : pos === 4\r\n ? \"following\"\r\n : pos === 8\r\n ? \"ancestor\"\r\n : pos === 16\r\n ? \"descendant\"\r\n : pos === 32\r\n ? \"self\"\r\n : \"\";\r\n};\r\n\r\nexport const isSvg = (element: HTMLElement | Element) => {\r\n return element instanceof SVGElement;\r\n};\r\n\r\nexport const replaceTempAttributes = (str: string): string => {\r\n if (!str) return str;\r\n\r\n return str.replace(/\\b[a-zA-Z_]*disabled\\b/gi, \"disabled\");\r\n};\r\n\r\nconst getElementFromXpath = (xpath: string, docmt: Node, multi = false) => {\r\n let contextNode: Node = docmt;\r\n\r\n // XPath does NOT support DocumentFragment / ShadowRoot\r\n if (docmt.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\r\n contextNode = (docmt as ShadowRoot).host ?? docmt;\r\n }\r\n\r\n const owner =\r\n contextNode.nodeType === Node.DOCUMENT_NODE\r\n ? (contextNode as Document)\r\n : contextNode.ownerDocument!;\r\n\r\n if (multi) {\r\n return owner.evaluate(xpath, contextNode, null, XPathResult.ANY_TYPE, null);\r\n }\r\n\r\n return owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n ).singleNodeValue;\r\n};\r\n\r\nexport const getPropertyXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n prop: string,\r\n value: string,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (value) {\r\n const { tagName } = element;\r\n let count;\r\n let combinePattern = \"\";\r\n const mergePattern = [];\r\n let pattern;\r\n\r\n if (value && (!isTarget || !isNumberExist(value))) {\r\n if (!reWhiteSpace.test(value)) {\r\n pattern = buildPattern(\r\n `normalize-space(${prop})=${escapeCharacters(\r\n replaceWhiteSpaces(value)\r\n ).trim()}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n } else {\r\n pattern = `//${tagName}[${prop}=${escapeCharacters(value)}]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n if (value && isTarget) {\r\n const splitText = value.split(\" \");\r\n if (splitText?.length) {\r\n if (splitText.length === 1) {\r\n const contentRes = [...new Set(splitText[0].match(/([^0-9]+)/g))];\r\n if (contentRes?.length >= 1) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 1\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (contentRes?.length > 1) {\r\n if (\r\n contentRes[contentRes.length - 1] &&\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1].trim())\r\n ?.length > 1\r\n ) {\r\n if (value.endsWith(contentRes[contentRes.length - 1])) {\r\n if (!reWhiteSpace.test(contentRes[contentRes.length - 1])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[contentRes.length - 1]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n } else {\r\n const endIndex =\r\n splitText.length % 2 === 0\r\n ? splitText.length / 2\r\n : splitText.length % 2;\r\n const startIndexString = splitText.slice(0, endIndex).join(\" \");\r\n let contentRes = [...new Set(startIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n const endIndexString = splitText\r\n .slice(endIndex, splitText.length - 1)\r\n .join(\" \");\r\n contentRes = [...new Set(endIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 3\r\n ) {\r\n if (value.endsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (value && isTarget && isNumberExist(value)) {\r\n const contentRes = [...new Set(value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (mergePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${mergePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tagName}[${mergePattern.join(\" and \")}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and text()]`;\r\n } else {\r\n pattern = `//${tagName}[text()]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAbsoluteXPath = (\r\n domNode: HTMLElement | Element | null,\r\n docmt: Document\r\n): string => {\r\n try {\r\n if (!domNode) {\r\n return \"\";\r\n }\r\n\r\n let xpathe = isSvg(domNode)\r\n ? `/*[local-name()='${domNode.tagName}']`\r\n : `/${domNode.tagName}`;\r\n\r\n // // If this node has siblings of the same tagName, get the index of this node\r\n if (domNode.parentElement) {\r\n // Get the siblings\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.parentElement.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n } else if (domNode instanceof HTMLElement) {\r\n if (domNode.offsetParent) {\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.offsetParent.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n }\r\n }\r\n\r\n // // Make a recursive call to this nodes parents and prepend it to this xpath\r\n return getAbsoluteXPath(domNode?.parentElement, docmt) + xpathe;\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(\"xpath\", error);\r\n\r\n return \"\";\r\n }\r\n};\r\n\r\nexport const getRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean = false,\r\n attributesArray: Attr[]\r\n) => {\r\n try {\r\n // Generate a cache key based on the node's identifier, index, and target flag\r\n // Check if the result for this node is already cached\r\n if (relativeXPathCache.has(domNode)) {\r\n return relativeXPathCache.get(domNode);\r\n }\r\n\r\n // Initialize an array to hold parts of the XPath\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n // Traverse up the DOM tree iteratively instead of using recursion\r\n while (currentNode) {\r\n let xpathe: string | undefined = \"\";\r\n let hasUniqueAttr = false;\r\n let attributes =\r\n domNode === currentNode\r\n ? (attributesArray ?? currentNode.attributes)\r\n : currentNode.attributes;\r\n\r\n // Loop through attributes to check for unique identifiers\r\n for (const attrName of Array.from(attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n // Clean up attribute value\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n\r\n const elementName = attrName.name;\r\n\r\n // Construct an XPath based on attribute\r\n xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr: number = 0;\r\n if (xpathe) {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n if (xpathe) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n // return replaceTempAttributes(xpathe);\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n } else {\r\n let combinePattern: string[] = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g))\r\n ];\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces((contentRes[i] as string).trim())\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i] as string)) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n (contentRes[i] as string).trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If no unique attribute was found, construct XPath by tag name\r\n if (!hasUniqueAttr) {\r\n let tagBasedXPath = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Handle sibling nodes\r\n if (currentNode.parentElement) {\r\n const siblings = Array.from(\r\n currentNode.parentElement.children\r\n ).filter((childNode) => childNode.tagName === currentNode.tagName);\r\n\r\n // Append index to distinguish between siblings\r\n if (siblings.length > 1) {\r\n const index = siblings.indexOf(currentNode);\r\n tagBasedXPath += `[${index + 1}]`;\r\n }\r\n }\r\n\r\n // Add the constructed tag-based XPath to the parts array\r\n xpathParts.unshift(tagBasedXPath);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move up to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXPath = `${xpathParts.join(\"\")}`;\r\n\r\n // Cache the final XPath for this node\r\n relativeXPathCache.set(domNode, finalXPath);\r\n return finalXPath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const getCombinationXpath = (\r\n attribute: Attr,\r\n domNode: HTMLElement | Element\r\n) => {\r\n const combinePattern = [];\r\n let pattern: string = \"\";\r\n\r\n if (\r\n attribute &&\r\n !isNumberExist(attribute.value) &&\r\n typeof attribute.nodeValue !== \"function\" // &&\r\n // !modifiedElementAttributes?.find(\r\n // (x) => x.element === domNode && x.attributeName === attribute.name\r\n // )\r\n ) {\r\n const contentRes = [...new Set(attribute.value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 2\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n contentRes[i].trim()\r\n )})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n pattern = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${combinePattern.join(\" and \")}]`;\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAttributeCombinationXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n uniqueAttributes: Attr[],\r\n isTarget: boolean\r\n): string | undefined => {\r\n try {\r\n const xpathAttributes = [];\r\n\r\n if (uniqueAttributes.length > 1) {\r\n for (const attrName of uniqueAttributes) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n const attrValue = attrName.nodeValue;\r\n\r\n if (!reWhiteSpace.test(attrValue!)) {\r\n xpathAttributes.push(\r\n `normalize-space(@${attrName.nodeName})=\"${attrValue}\"`\r\n );\r\n } else if (attrName.nodeName === \"class\") {\r\n xpathAttributes.push(\r\n `contains(@${attrName.nodeName},\"${attrValue}\")`\r\n );\r\n } else {\r\n xpathAttributes.push(`@${attrName.nodeName}=\"${attrValue}\"`);\r\n }\r\n\r\n const xpathe = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${xpathAttributes.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${xpathAttributes.join(\" and \")}]`;\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, domNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n if (othersWithAttr === 1 && !xpathe.includes(\"and\")) {\r\n return \"\";\r\n }\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr === 1 && xpathe.includes(\"and\")) {\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(`'${JSON.stringify(error, null, 2)}'`);\r\n }\r\n};\r\n\r\nexport const intermediateXpathStep = (\r\n targetElemt: HTMLElement | Element,\r\n attr: { name: string; value: string },\r\n isTarget: boolean\r\n): string => {\r\n let isSvgElement = isSvg(targetElemt);\r\n let expression: string = \"\";\r\n\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n let attrValue = attr.value;\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attr.name;\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n expression = isSvgElement\r\n ? `*[local-name()='${targetElemt.tagName\r\n }' and normalize-space(@${elementName})=${escapeCharacters(\r\n attrValue\r\n )}]`\r\n : `${targetElemt.tagName || \"*\"\r\n }[normalize-space(@${elementName})=${escapeCharacters(attrValue)}]`;\r\n } else {\r\n expression = isSvgElement\r\n ? `*[local-name()='${targetElemt.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${targetElemt.tagName || \"*\"}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return expression;\r\n};\r\n\r\nexport const getFilteredTextXPath = (\r\n node: HTMLElement | Element,\r\n docmt: Document\r\n): string => {\r\n if (!node.textContent) return \"\";\r\n\r\n const filteredText = getFilteredText(node);\r\n\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(filteredText)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and normalize-space(.)=${escapeCharacters(filteredText)}]`\r\n : `//${node.tagName || \"*\"}[normalize-space(.)=${escapeCharacters(\r\n filteredText\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName}' and .=${escapeCharacters(\r\n filteredText\r\n )}]`\r\n : `//${node.tagName || \"*\"}[.=${escapeCharacters(filteredText)}]`;\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const getTextXpathFunction = (\r\n domNode: HTMLElement | Element\r\n): string | undefined => {\r\n const trimmedText = getTextContent(domNode)?.trim();\r\n const filteredText = trimmedText\r\n ? escapeCharacters(deleteGarbageFromInnerText(trimmedText))\r\n : trimmedText;\r\n if (filteredText) {\r\n if (filteredText !== `'${trimmedText}'`) {\r\n return `contains(.,${filteredText})`;\r\n }\r\n return `normalize-space(.)='${trimmedText}'`;\r\n }\r\n};\r\n\r\nexport const getXpathString = (\r\n node: HTMLElement | Element,\r\n attrName: string,\r\n attrValue: string\r\n): string => {\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n let xpathe: string = \"\";\r\n\r\n if (attrValue) {\r\n if (!reWhiteSpace.test(attrValue)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else if (attrName === \"class\") {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName\r\n }' and @${attrName}=${escapeCharacters(attrValue)}]`\r\n : `//${node.tagName || \"*\"}[@${attrName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const replaceActualAttributes = (\r\n str: string,\r\n element: { attributes: any }\r\n): string => {\r\n if (str) {\r\n return str.replace(/\\bdisabled\\b/gi, \"flndisabled\");\r\n }\r\n return str;\r\n};\r\n\r\nconst addAttributeSplitCombineXpaths = (\r\n attributes: NamedNodeMap,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n const attributesArray = Array.prototype.slice.call(attributes);\r\n const xpaths: { key: string; value: string }[] = [];\r\n try {\r\n attributesArray.map((element) => {\r\n if (checkBlockedAttributes(element, targetElemt, isTarget)) {\r\n const xpth = getCombinationXpath(element, targetElemt);\r\n if (xpth) {\r\n xpaths.push({\r\n key: `split xpath by ${element.name}`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n });\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return xpaths;\r\n};\r\n\r\nexport const getReferenceElementsXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n let nodeXpath1;\r\n const xpaths1 = [];\r\n if (\r\n domNode.textContent &&\r\n (!isTarget || (isTarget && !isNumberExist(domNode.textContent)))\r\n ) {\r\n if (!reWhiteSpace.test(domNode.textContent)) {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and ${getTextXpathFunction(\r\n domNode\r\n )})]`\r\n : `${domNode.tagName}[${getTextXpathFunction(domNode)}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and .=${escapeCharacters(\r\n getTextContent(domNode)\r\n )}]`\r\n : `${domNode.tagName}[.=${escapeCharacters(getTextContent(domNode))}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n }\r\n }\r\n\r\n if (domNode.attributes) {\r\n for (const attrName of Array.from(domNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n if (elementName === \"class\") {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName\r\n }' and contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`\r\n : `${domNode.tagName}[contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${domNode.tagName}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n\r\n if (nodeXpath1) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: nodeXpath1\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const attributesArray = Array.prototype.slice.call(domNode.attributes);\r\n if (attributesArray?.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n domNode,\r\n docmt,\r\n Array.prototype.slice.call(domNode.attributes),\r\n isTarget\r\n );\r\n if (combinationXpath) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: combinationXpath\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const combinePattern = [];\r\n let pattern;\r\n const tag = isSvg(domNode);\r\n if (domNode.textContent && isTarget && isNumberExist(domNode.textContent)) {\r\n const contentRes = [...new Set(domNode.textContent.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(contentRes[i]).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (tag) {\r\n pattern = `//*[local-name()='${tag}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tag}[${combinePattern.join(\" and \")}]`;\r\n }\r\n\r\n if (pattern)\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: pattern });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const xpaths = addAttributeSplitCombineXpaths(\r\n domNode.attributes,\r\n domNode,\r\n docmt,\r\n isTarget\r\n );\r\n if (xpaths?.length) {\r\n xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n return xpaths1;\r\n};\r\n\r\nexport const parseXml = (\r\n xmlStr: string,\r\n type: DOMParserSupportedType\r\n): Document | null => {\r\n if (window.DOMParser) {\r\n return new window.DOMParser().parseFromString(xmlStr, type);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const normalizeXPath = (xpath: string): string => {\r\n // Replace text() = \"value\" or text()='value'\r\n xpath = xpath.replace(\r\n /text\\(\\)\\s*=\\s*(['\"])(.*?)\\1/g,\r\n \"normalize-space(.)=$1$2$1\"\r\n );\r\n\r\n // Replace . = \"value\" or .='value'\r\n xpath = xpath.replace(/\\.\\s*=\\s*(['\"])(.*?)\\1/g, \"normalize-space(.)=$1$2$1\");\r\n\r\n return xpath;\r\n};\r\n\r\nexport const findMatchingParenthesis = (\r\n text: string,\r\n openPos: number\r\n): number => {\r\n let closePos = openPos;\r\n let counter = 1;\r\n while (counter > 0) {\r\n const c = text[++closePos];\r\n if (c == \"(\") {\r\n counter++;\r\n } else if (c == \")\") {\r\n counter--;\r\n }\r\n }\r\n return closePos;\r\n};\r\n\r\nexport function canonicalizeXPath(xpath: string): string {\r\n return (\r\n xpath\r\n .toLowerCase()\r\n // replace quoted values\r\n .replace(/'[^']*'/g, \"?\")\r\n .replace(/\"[^\"]*\"/g, \"?\")\r\n // replace numbers in predicates\r\n .replace(/\\[\\d+\\]/g, \"[?]\")\r\n // normalize node names\r\n .replace(/\\/\\/[a-z0-9_-]+/g, \"//node\")\r\n .replace(/\\/[a-z0-9_-]+/g, \"/node\")\r\n );\r\n}\r\n\r\nexport function extractXPathSignatureParts(xpath: string) {\r\n const xp = xpath.toLowerCase();\r\n\r\n const axisMatch = xp.match(\r\n /(ancestor-or-self|ancestor|descendant-or-self|descendant|following-sibling|preceding-sibling|following|preceding|parent|child|self)::/\r\n );\r\n const axis = axisMatch?.[1] ?? \"none\";\r\n\r\n const attrMatch = xp.match(/@([a-z0-9:-]+)/);\r\n const attribute = attrMatch?.[1] ?? \"none\";\r\n\r\n const usesNormalize = xp.includes(\"normalize-space\");\r\n\r\n return { axis, attribute, usesNormalize };\r\n}\r\n\r\nexport function getXPathPattern(xpath: string): string {\r\n const canonical = canonicalizeXPath(xpath);\r\n const parts = extractXPathSignatureParts(xpath);\r\n\r\n return [\r\n \"XPATH\",\r\n `axis:${parts.axis}`,\r\n `attr:${parts.attribute}`,\r\n `normalize:${parts.usesNormalize}`,\r\n `shape:${canonical}`\r\n ].join(\"|\");\r\n}\r\n\r\nexport function escapeAttrValue(value: string): string {\r\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/ /g, \"\\\\ \");\r\n}\r\n\r\nexport function shouldUseSnapshot(xpath: string): boolean {\r\n return /\\[(?:\\s*\\.|\\s*contains\\s*\\(\\s*\\.|\\s*normalize-space\\s*\\(\\s*\\.)/.test(\r\n xpath\r\n );\r\n}\r\n\r\nexport function isUniqueInDOM(\r\n docmt: Document,\r\n name: string,\r\n value: string,\r\n element?: Element | null\r\n): boolean {\r\n const root = (element?.getRootNode?.() as ParentNode | null) ?? docmt;\r\n const queryAll = (selector: string): Element[] => {\r\n try {\r\n return Array.from(root.querySelectorAll(selector));\r\n } catch {\r\n return [];\r\n }\r\n };\r\n\r\n try {\r\n switch (name) {\r\n case \"id\":\r\n return queryAll(`#${escapeAttrValue(value)}`).length === 1;\r\n\r\n case \"name\":\r\n return queryAll(`[name=\"${escapeAttrValue(value)}\"]`).length === 1;\r\n\r\n case \"className\":\r\n return queryAll(`.${value}`).length === 1;\r\n\r\n case \"tagName\":\r\n return queryAll(value).length === 1;\r\n\r\n case \"linkText\":\r\n return (\r\n queryAll(\"a\").filter(\r\n (a) => a.textContent?.trim() === value\r\n ).length === 1\r\n );\r\n case \"partialLinkText\":\r\n return (\r\n queryAll(\"a\").filter((a) =>\r\n a.textContent?.includes(value)\r\n ).length === 1\r\n );\r\n case \"cssSelector\":\r\n return queryAll(value).length === 1;\r\n default:\r\n return false;\r\n }\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport const xpathUtils = {\r\n parseXml,\r\n getReferenceElementsXpath,\r\n getAbsoluteXPath,\r\n getRelativeXPath,\r\n getCombinationXpath,\r\n getAttributeCombinationXpath,\r\n getElementFromXpath,\r\n isSvg,\r\n findXpathWithIndex,\r\n isNumberExist,\r\n getTextContent,\r\n getCountOfXPath,\r\n normalizeXPath,\r\n getShadowRoot,\r\n escapeCharacters,\r\n removeParenthesis,\r\n checkBlockedAttributes,\r\n getRelationship,\r\n findMatchingParenthesis,\r\n deleteGarbageFromInnerText,\r\n replaceTempAttributes,\r\n createObserver,\r\n startObserver,\r\n stopObserver,\r\n modifiedElementAttributes,\r\n cspEnabled,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM\r\n};\r\n","import {\r\n isNumberExist,\r\n getCountOfXPath,\r\n escapeCharacters,\r\n checkBlockedAttributes,\r\n replaceWhiteSpaces,\r\n getTextContent,\r\n getPropertyXPath,\r\n findXpathWithIndex,\r\n getFilteredText,\r\n intermediateXpathStep,\r\n getAttributeCombinationXpath,\r\n getFilteredTextXPath,\r\n isSvg,\r\n getXpathString,\r\n reWhiteSpace,\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathData: { key: string; value: string }[] = [];\r\nlet xpathDataWithIndex: { key: string; value: string; count: number }[] = [];\r\nlet referenceElementMode: boolean = false;\r\nlet xpathCache = new Map();\r\nlet cache = new Map();\r\n\r\nconst parentXpathCache = new Map(); // Cache for parent XPaths\r\n\r\nconst checkRelativeXpathRelation = (\r\n nodeXpath1: string,\r\n nodeXpath2: string,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n relationType: string\r\n) => {\r\n if (nodeXpath1 && !referenceElementMode) {\r\n let xpaths;\r\n\r\n if (relationType === \"parent\") {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/descendant-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/following::${nodeXpath2}`,\r\n ];\r\n } else {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/ancestor-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/preceding::${nodeXpath2}`,\r\n ];\r\n }\r\n\r\n // Iterate through XPath patterns\r\n for (const xpath of xpaths) {\r\n // Check if result is already cached to avoid recomputation\r\n if (!xpathCache?.get(xpath)) {\r\n // Compute and store result in cache\r\n xpathCache.set(xpath, getCountOfXPath(xpath, targetElemt, docmt));\r\n }\r\n\r\n const count = xpathCache?.get(xpath);\r\n\r\n // Short-circuit: Return the first valid XPath result found\r\n if (count === 1) {\r\n return xpath;\r\n }\r\n if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count,\r\n });\r\n }\r\n }\r\n\r\n if (count > 1 && isIndex && !xpathData.length) {\r\n // Try finding XPath with index if count is greater than 1\r\n const indexedXpath = findXpathWithIndex(\r\n xpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n\r\n // Cache the indexed XPath result\r\n if (\r\n indexedXpath &&\r\n getCountOfXPath(indexedXpath, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: indexedXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst getUniqueParentXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean,\r\n nodeXpath: string,\r\n isIndex: boolean\r\n) => {\r\n try {\r\n if (parentXpathCache.has(domNode)) {\r\n return parentXpathCache.get(domNode);\r\n }\r\n\r\n // Direct XPath construction without loops\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n while (currentNode && currentNode.nodeType === 1) {\r\n const hasUniqueAttr = false;\r\n for (const attrName of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent && !currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n } else {\r\n const combinePattern = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g)),\r\n ];\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (contentRes[i] && replaceWhiteSpaces(contentRes[i].trim())) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n const xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Construct the XPath based on the tag name\r\n if (!hasUniqueAttr) {\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Final constructed XPath\r\n const finalXPath = xpathParts.join(\"\") + nodeXpath;\r\n let count = getCountOfXPath(finalXPath, domNode, docmt);\r\n if (count === 1) {\r\n parentXpathCache.set(domNode, finalXPath); // Cache final result\r\n return finalXPath;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getParentRelativeXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean\r\n) => {\r\n const cache = new Map(); // Cache to store computed results\r\n\r\n if (cache.has(domNode)) {\r\n return cache.get(domNode); // Return cached result if available\r\n }\r\n\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath\r\n let currentNode = domNode; // Start with the provided DOM node\r\n\r\n try {\r\n while (currentNode && currentNode.nodeType === 1) {\r\n // BASE CASE #1: If this isn't an element, we're above the root, return empty string\r\n if (!currentNode.tagName) {\r\n return \"\";\r\n }\r\n\r\n // BASE CASE #2: Check for unique attributes\r\n let uniqueAttrFound = false;\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, isTarget)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(xpathe);\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(textXPath, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.unshift(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getChildRelativeXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n node: HTMLElement | Element\r\n) => {\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath.\r\n let currentNode: HTMLElement | Element | null;\r\n\r\n const st = [];\r\n if (\r\n domNode.firstElementChild != null &&\r\n domNode.firstElementChild.classList.contains(\"flntooltip\")\r\n ) {\r\n st.unshift(domNode.firstElementChild);\r\n } else if (domNode.nextElementSibling != null)\r\n st.unshift(domNode.nextElementSibling);\r\n\r\n for (\r\n let m = domNode.parentElement;\r\n m != null && m.nodeType === 1;\r\n m = m.parentElement\r\n ) {\r\n if (m.nextElementSibling) st.unshift(m.nextElementSibling);\r\n }\r\n\r\n try {\r\n do {\r\n let uniqueAttrFound = false;\r\n for (currentNode = st.pop()!; currentNode !== null; ) {\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, true)) {\r\n let attrValue = attr.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(xpathe);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(\r\n textXPath,\r\n currentNode,\r\n docmt\r\n );\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.push(xpathe);\r\n\r\n if (currentNode.firstElementChild != null) {\r\n st.push(currentNode.nextElementSibling);\r\n currentNode = currentNode.firstElementChild;\r\n } else {\r\n currentNode = currentNode.nextElementSibling;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n } while (st.length > 0);\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getSiblingRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n nodeXpath: string\r\n) => {\r\n try {\r\n const markedSpan = document.querySelector(\".flntooltip\");\r\n\r\n for (\r\n let m = domNode.nextElementSibling;\r\n m !== null && m !== markedSpan;\r\n m = m.nextElementSibling\r\n ) {\r\n processSibling(\r\n m,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"preceding-sibling\",\r\n isTarget\r\n );\r\n }\r\n\r\n for (\r\n let n = domNode.previousElementSibling;\r\n n !== null && n !== markedSpan;\r\n n = n.previousElementSibling\r\n ) {\r\n processSibling(\r\n n,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"following-sibling\",\r\n isTarget\r\n );\r\n }\r\n } catch (error) {\r\n console.error(\"sibling error\", error);\r\n return null;\r\n }\r\n};\r\n\r\nconst processSibling = (\r\n sibling: Element,\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n nodeXpath: string,\r\n axis: string,\r\n isTarget: boolean\r\n) => {\r\n try {\r\n if (sibling.hasAttributes()) {\r\n for (const attr of Array.from(sibling.attributes)) {\r\n let xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: attr.name,\r\n value: attr.value,\r\n },\r\n isTarget\r\n );\r\n if (xpathe) {\r\n xpathe += `/${axis}::${nodeXpath}`;\r\n\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!isTarget) {\r\n let xpathe;\r\n xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: \"text\",\r\n value: sibling.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n if (xpathe) {\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe,\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(`${axis} xpath-error`, error);\r\n }\r\n};\r\n\r\nfunction getXPathUsingAttributeAndText(\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n) {\r\n const { tagName } = targetElemt;\r\n const textContent = targetElemt.textContent.trim();\r\n for (const attrName of attributes) {\r\n if (checkBlockedAttributes(attrName, targetElemt, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n\r\n attrValue = attrValue?.replace(\"removePointers\", \"\") ?? \"\";\r\n const elementName = attrName.name;\r\n const xpath = `//${tagName}[@${elementName}='${attrValue}' and text()='${textContent}']`;\r\n if (xpath) {\r\n const count = getCountOfXPath(xpath, targetElemt, docmt);\r\n if (count == 1) {\r\n return xpath;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst addRelativeXpaths = (\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n attribute: Attr[]\r\n) => {\r\n try {\r\n let nodeXpath: string[] = [];\r\n let relativeXpath, relativeChildXpath;\r\n xpathData = [];\r\n\r\n console.log(attribute);\r\n if (attribute) {\r\n for (const attrName of attribute) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: attrName.name,\r\n value: attrName.value,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n }\r\n\r\n if (targetElemt.textContent) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: \"text\",\r\n value: targetElemt.textContent,\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n\r\n nodeXpath.push(targetElemt.tagName);\r\n\r\n if (nodeXpath?.length) {\r\n for (let i = 0; i < nodeXpath.length; i++) {\r\n if (!xpathData.length) {\r\n getSiblingRelativeXPath(targetElemt, docmt, isTarget, nodeXpath[i]);\r\n\r\n if (!xpathData.length) {\r\n if (!relativeXpath) {\r\n relativeXpath = getParentRelativeXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget\r\n );\r\n }\r\n\r\n console.log(relativeXpath);\r\n\r\n if (\r\n relativeXpath &&\r\n (relativeXpath.includes(\"@\") ||\r\n relativeXpath.includes(\"text()\") ||\r\n relativeXpath.includes(\".=\")) &&\r\n relativeXpath.match(/\\//g)?.length - 2 < 5\r\n ) {\r\n const fullRelativeXpath = relativeXpath + `/${nodeXpath[i]}`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative parent\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n if (!relativeChildXpath) {\r\n relativeChildXpath = getChildRelativeXpath(\r\n targetElemt,\r\n docmt,\r\n targetElemt\r\n );\r\n }\r\n\r\n if (\r\n relativeChildXpath &&\r\n (relativeChildXpath.includes(\"@\") ||\r\n relativeChildXpath.includes(\"text()\") ||\r\n relativeChildXpath.includes(\".=\"))\r\n ) {\r\n const fullRelativeXpath = `/${\r\n nodeXpath[i] + relativeChildXpath.substring(1)\r\n }`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative child\",\r\n value: fullRelativeXpath,\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (\r\n xpathData?.length === 1 &&\r\n xpathData?.[0]?.value?.match(/\\[([0-9]+)\\]/gm)?.length! > 3 &&\r\n !referenceElementMode\r\n ) {\r\n if (targetElemt.textContent) {\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, false);\r\n if (txtXpath) {\r\n xpathData.unshift({\r\n key: `xpath by text${isIndex ? \"index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n let tempRelativeXpath = getUniqueParentXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget,\r\n nodeXpath[i],\r\n isIndex\r\n );\r\n\r\n if (tempRelativeXpath) {\r\n xpathData.push({\r\n key: \"xpath by unique parent\",\r\n value: tempRelativeXpath,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return xpathData;\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const attributesBasedXPath = (\r\n attr: Attr,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let attrName;\r\n\r\n attrName = attr.name;\r\n let xpath = getPropertyXPath(\r\n targetElemt,\r\n docmt,\r\n `@${attrName}`,\r\n attr.value,\r\n isIndex,\r\n isTarget\r\n );\r\n\r\n return xpath;\r\n};\r\n\r\nexport const getUniqueClassName = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let value = element.className;\r\n if (typeof value !== \"string\") {\r\n value = \"\";\r\n }\r\n value = value?.replace(\"flndisabled\", \"disabled\");\r\n value = value?.replace(\"removePointers\", \"\");\r\n value = value?.trim();\r\n\r\n if (value) {\r\n return getPropertyXPath(element, docmt, `@class`, value, isIndex, isTarget);\r\n }\r\n};\r\n\r\nexport const getTextXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (element.textContent != \"\") {\r\n const text = getTextContent(element);\r\n\r\n if (text) {\r\n return getPropertyXPath(element, docmt, \".\", text, isIndex, isTarget);\r\n }\r\n }\r\n};\r\n\r\nconst addAllXPathAttributes = (\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n const attributesArray = attributes;\r\n try {\r\n attributesArray.map((attr) => {\r\n if (!(attr.name === \"className\" || attr.name === \"class\")) {\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n const xpth = attributesBasedXPath(\r\n attr,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (xpth) {\r\n xpathData.push({\r\n key: `xpath by ${attr.name}${isIndex ? \" index\" : \"\"}`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n });\r\n\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, isTarget);\r\n if (txtXpath) {\r\n xpathData.push({\r\n key: `xpath by text${isIndex ? \" index\" : \"\"}`,\r\n value: txtXpath,\r\n });\r\n }\r\n\r\n if (\r\n attributesArray.find((element) => element.name === \"className\") &&\r\n checkBlockedAttributes(\r\n attributesArray?.find((element) => element.name === \"className\")!,\r\n targetElemt,\r\n isTarget\r\n )\r\n ) {\r\n let xpath = getUniqueClassName(targetElemt, docmt, isIndex, isTarget);\r\n if (xpath) {\r\n xpathData.push({\r\n key: \"xpath by class\",\r\n value: xpath,\r\n });\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n const textAttribute = getXPathUsingAttributeAndText(\r\n attributes,\r\n targetElemt,\r\n docmt,\r\n isTarget\r\n );\r\n if (textAttribute)\r\n xpathData.push({\r\n key: \"xpath by textAttribute\",\r\n value: textAttribute,\r\n });\r\n }\r\n\r\n if (!xpathData.length && attributesArray.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n targetElemt,\r\n docmt,\r\n attributesArray,\r\n isTarget\r\n );\r\n if (combinationXpath)\r\n xpathData.push({\r\n key: \"xpath by combination\",\r\n value: combinationXpath,\r\n });\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const parseDOM = (\r\n element: HTMLElement | Element,\r\n doc: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n includedAttributes: Attr[] = []\r\n) => {\r\n xpathData = [];\r\n console.log(element);\r\n const targetElemt = element;\r\n const docmt = targetElemt?.ownerDocument || doc;\r\n const tag = targetElemt.tagName;\r\n const { attributes } = targetElemt;\r\n const attributesToUse =\r\n includedAttributes.length > 0 ? includedAttributes : Array.from(attributes);\r\n addAllXPathAttributes(\r\n attributesToUse,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (!referenceElementMode) {\r\n if (xpathData.length) {\r\n const len = xpathData.length;\r\n for (let i = 0; i < len; i++) {\r\n let xpth = xpathData[i].value;\r\n xpth = \"//*\" + xpth.substring(xpth.indexOf(\"//\") + 2 + tag.length);\r\n const count = getCountOfXPath(xpth, element, docmt);\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `${xpathData[i].key} regex`,\r\n value: xpth,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n addRelativeXpaths(\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget,\r\n Array.from(targetElemt.attributes)\r\n );\r\n }\r\n\r\n return xpathData;\r\n};\r\n\r\nconst xpath = {\r\n parseDOM,\r\n getTextXPath,\r\n getUniqueClassName,\r\n attributesBasedXPath,\r\n addAllXPathAttributes,\r\n addRelativeXpaths,\r\n getXPathUsingAttributeAndText,\r\n getSiblingRelativeXPath,\r\n getChildRelativeXpath,\r\n getParentRelativeXpath,\r\n getUniqueParentXpath,\r\n checkRelativeXpathRelation,\r\n};\r\n\r\nexport default xpath;\r\n","import { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n findXpathWithIndex,\r\n getShadowRoot,\r\n getTextContent,\r\n escapeCharacters,\r\n getCountOfXPath,\r\n checkBlockedAttributes,\r\n getAbsoluteXPath,\r\n isSvg,\r\n getCombinationXpath,\r\n getTextXpathFunction,\r\n replaceTempAttributes,\r\n replaceActualAttributes,\r\n getReferenceElementsXpath,\r\n getRelativeXPath,\r\n findMatchingParenthesis,\r\n removeParenthesis\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathDataWithIndex: any[] = [];\r\nlet xpathData: { key: string; value: string }[] = [];\r\nconst reWhiteSpace = /^[\\S]+( [\\S]+)*$/gi;\r\n\r\nexport const findRelativeXpath = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n docmt: Document,\r\n xpaths1: any[],\r\n xpaths2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n // debugger;\r\n const par1 = element1.parentElement;\r\n const par2 = element2.parentElement;\r\n let rel_xpath: any[] = [];\r\n\r\n let tempElement;\r\n let finalXpaths: any[] = [];\r\n\r\n if (isIndex) {\r\n if (xpathDataWithIndex.length) {\r\n const xpathWithIndex = findXpathWithIndex(\r\n xpathDataWithIndex[0].value,\r\n element2,\r\n element2.ownerDocument,\r\n xpathDataWithIndex[0].count\r\n );\r\n if (xpathWithIndex) {\r\n finalXpaths = finalXpaths.concat({\r\n key: `${xpathDataWithIndex[0]?.key\r\n ? xpathDataWithIndex[0]?.key\r\n : \"xpath with \"\r\n } index`,\r\n value: xpathWithIndex,\r\n });\r\n xpathDataWithIndex.pop();\r\n }\r\n }\r\n }\r\n\r\n if (!finalXpaths.length) {\r\n // both are same\r\n if (element1.isSameNode(element2)) {\r\n // rel_xpath = xpath1 + \"/self::\" + element1.tagName;\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // parent\r\n tempElement = element1.parentElement;\r\n\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"parent\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n // ancestor\r\n tempElement = element1.parentElement;\r\n\r\n while (tempElement !== null) {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n }\r\n\r\n // ancestor-or-self\r\n tempElement = element1;\r\n do {\r\n if (tempElement === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"ancestor-or-self\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n\r\n tempElement = tempElement.parentNode;\r\n } while (tempElement !== null);\r\n\r\n // both has same parent\r\n if (par1?.isSameNode(par2)) {\r\n for (\r\n let m = element1.nextElementSibling;\r\n m != null;\r\n m = m.nextElementSibling\r\n ) {\r\n if (m != null && m.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n for (\r\n let n = element1.previousElementSibling;\r\n n != null;\r\n n = n.previousElementSibling\r\n ) {\r\n if (n != null && n.isSameNode(element2)) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding-sibling\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // child\r\n if (element1?.children?.length) {\r\n for (let m = element1.children[0]; m !== null; m = m?.nextElementSibling!) {\r\n if (m === element2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"child\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // following\r\n const relation = element1.compareDocumentPosition(element2);\r\n if (relation === 2) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"preceding\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n\r\n if (relation === 4) {\r\n rel_xpath = getXpathRelationExpression(\r\n element1,\r\n element2,\r\n \"following\",\r\n xpaths1,\r\n xpaths2,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n }\r\n if (rel_xpath) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n\r\n const descendantXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantXpath) finalXpaths = finalXpaths.concat(descendantXpath);\r\n\r\n const descendantSelfXpath = getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n \"descendant-or-self\",\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (descendantSelfXpath) {\r\n finalXpaths = finalXpaths.concat(descendantSelfXpath);\r\n }\r\n }\r\n\r\n if (finalXpaths.length) {\r\n if (finalXpaths.length > 1) {\r\n finalXpaths.sort(function (a, b) {\r\n return a.value.length - b.value.length;\r\n });\r\n }\r\n\r\n if (finalXpaths.filter((x) => !x.key?.includes(\"index\"))?.length) {\r\n return [finalXpaths.filter((x) => !x.key?.includes(\"index\"))[0]];\r\n }\r\n return [finalXpaths[0]];\r\n }\r\n};\r\n\r\nconst descendantExpression = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n xpath2: string,\r\n relation: string,\r\n docmt: Node,\r\n isIndex: any,\r\n expCommonParentXpathElements: string | any[],\r\n step4: string,\r\n refCommonParentXpathElementLength: number = 0,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n let finalExpectedElementXpath: string | undefined = \"\";\r\n\r\n if (\r\n xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g)?.length >=\r\n expCommonParentXpathElements.length\r\n ) {\r\n const xpaths2Els: string[] = [];\r\n const xpath2Elements = xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g);\r\n for (let x = 1; x <= expCommonParentXpathElements.length; x++) {\r\n xpaths2Els.unshift(\r\n x === expCommonParentXpathElements.length\r\n ? expCommonParentXpathElements[\r\n expCommonParentXpathElements.length - x\r\n ]\r\n : xpath2Elements[xpath2Elements.length - x]\r\n );\r\n }\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n xpaths2Els,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n } else {\r\n finalExpectedElementXpath = `//${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n refExpectElement[refExpectElement.length - 1]\r\n )}`;\r\n let rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation} ${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst getDescendantXpath = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Document,\r\n xpaths1: { key: string; value: string }[],\r\n xpaths2: { key: string; value: string }[],\r\n relation: \"descendant\" | \"descendant-or-self\",\r\n isIndex: boolean = false,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n const refElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 2];\r\n const expElement: HTMLElement | Element = refExpectElement[refExpectElement.length - 1];\r\n const expElementDocmnt = getShadowRoot(expElement) ?? expElement.ownerDocument;\r\n\r\n const refAbsoluteXpath =\r\n xpaths1.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(refElement, refElement.ownerDocument);\r\n\r\n const refFullXpathElements: any[] = [];\r\n const refFullXpathElementsWithoutNumber: any[] = [];\r\n refAbsoluteXpath.split(\"/\").map((x) => refFullXpathElements.push(x));\r\n refFullXpathElements.map((x) =>\r\n refFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n const expAbsoluteXpath =\r\n xpaths2.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(expElement, expElement.ownerDocument);\r\n\r\n const expFullXpathElements: any[] = [];\r\n const expFullXpathElementsWithoutNumber: any[] = [];\r\n expAbsoluteXpath.split(\"/\").map((x) => expFullXpathElements.push(x));\r\n expFullXpathElements.map((x) =>\r\n expFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n for (\r\n var parentElementNumber = 0;\r\n parentElementNumber < refFullXpathElements.length;\r\n parentElementNumber++\r\n ) {\r\n if (\r\n refFullXpathElements[parentElementNumber] !=\r\n expFullXpathElements[parentElementNumber]\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n const refCommonParentXpathElements = [];\r\n for (let i = parentElementNumber - 1; i < refFullXpathElements.length; i++) {\r\n if (refFullXpathElements[i]) {\r\n refCommonParentXpathElements.push(refFullXpathElementsWithoutNumber[i]);\r\n }\r\n }\r\n\r\n const expCommonParentXpathElements: string[] = [];\r\n for (\r\n let j =\r\n relation === \"descendant\" ? parentElementNumber : parentElementNumber - 1;\r\n j < expFullXpathElements.length;\r\n j++\r\n ) {\r\n if (expFullXpathElements[j]) {\r\n if (expCommonParentXpathElements.length)\r\n expCommonParentXpathElements.push(expFullXpathElementsWithoutNumber[j]);\r\n else\r\n expCommonParentXpathElements.push(\r\n expFullXpathElementsWithoutNumber[j].replace(/\\[([0-9]+)\\]/gm, \"\")\r\n );\r\n }\r\n }\r\n\r\n xpathData = xpaths2;\r\n\r\n let nodeXpath2;\r\n if (refExpectElement[refExpectElement.length - 2].textContent) {\r\n if (\r\n !reWhiteSpace.test(\r\n refExpectElement[refExpectElement.length - 2].textContent\r\n )\r\n ) {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and ${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )})]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )}]`;\r\n } else {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and .=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[.=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`;\r\n }\r\n\r\n refCommonParentXpathElements[refCommonParentXpathElements.length - 1] =\r\n nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n if (xpath2) {\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (refExpectElement[refExpectElement.length - 2].attributes) {\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const elementName = attrName.name;\r\n\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${refExpectElement[refExpectElement.length - 2].tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${refExpectElement[refExpectElement.length - 2].tagName\r\n }[@${elementName}=${escapeCharacters(attrValue)}]`;\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (const attrName of Array.from(refExpectElement[refExpectElement.length - 2]\r\n .attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, refExpectElement[refExpectElement.length - 2], false)\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = attrValue.replace(\"removePointers\", \"\");\r\n const combinationXpath = getCombinationXpath(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2]\r\n );\r\n if (combinationXpath) {\r\n if (combinationXpath.startsWith(\"//\")) {\r\n nodeXpath2 = combinationXpath.substring(\r\n combinationXpath.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n nodeXpath2 = combinationXpath; // No need to modify the value\r\n }\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n const step4 = refCommonParentXpath;\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n expCommonParentXpathElements,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n};\r\n\r\nconst getXpathRelationExpression = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n relation: string,\r\n xpath1: any[],\r\n xpath2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let xpaths1;\r\n let xpaths2;\r\n console.log('getXpathRelationExpression', relation)\r\n const finalXpaths: { key: string; value: any }[] = [];\r\n\r\n try {\r\n xpaths1 = xpath1.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n xpaths2 = xpath2.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n let rel_xpath: string | undefined = `//${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(xpaths1[i].value.indexOf(\"//\") + 2),\r\n element1\r\n )\r\n }/${relation}::${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths2[j].value, element2)\r\n : replaceActualAttributes(\r\n xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2),\r\n element2\r\n )\r\n }`;\r\n console.log('getXpathRelationExpression', rel_xpath)\r\n const rel_count = getCountOfXPath(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument\r\n );\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n rel_xpath = findXpathWithIndex(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument,\r\n rel_count\r\n );\r\n if (rel_xpath) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n } else if (rel_count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (rel_count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count,\r\n });\r\n }\r\n }\r\n } else if (rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(rel_xpath),\r\n });\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n if (!finalXpaths.length) {\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n const tempPath = `${xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? xpaths2[j].value\r\n : xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2)\r\n }`;\r\n const xpath2Elements: string[] = tempPath.split(\r\n /\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g\r\n );\r\n if (xpath2Elements.length > 1) {\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(\r\n xpaths1[i].value.indexOf(\"//\") + 2\r\n ),\r\n element1\r\n )\r\n }`,\r\n xpath2Elements,\r\n element2,\r\n [element1, element2],\r\n element2.ownerDocument,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n\r\n console.log('getXpathRelationExpression traverseXpath', traverseXpath)\r\n if (traverseXpath) {\r\n finalXpaths.concat(traverseXpath);\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst getReferenceElementXpath = (element: HTMLElement | Element) => {\r\n let xpaths1: {\r\n key: string;\r\n value: string;\r\n }[] = [];\r\n\r\n xpaths1 = parseDOM(element, element.ownerDocument, false, false);\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = parseDOM(element, element.ownerDocument, true, false);\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n } else {\r\n let xpaths = parseDOM(element, element.ownerDocument, true, false);\r\n if (xpaths?.length) {\r\n xpaths = xpaths?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, false, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(element, element.ownerDocument, true, false, Array.from(element.attributes)),\r\n },\r\n ];\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = getReferenceElementsXpath(element, element.ownerDocument, false);\r\n } else {\r\n const xpaths = getReferenceElementsXpath(\r\n element,\r\n element.ownerDocument,\r\n false\r\n );\r\n if (xpaths?.length) {\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n const referenceXpathElement = getAbsoluteXPath(\r\n element,\r\n element.ownerDocument\r\n );\r\n xpaths1 = xpaths1.filter((x) => x.value !== referenceXpathElement);\r\n\r\n xpaths1.push({\r\n key: \"absolute xpath\",\r\n value: referenceXpathElement.slice(1),\r\n });\r\n\r\n return xpaths1;\r\n};\r\n\r\nconst getTraverseXpathExpression = (\r\n xpathe1: string,\r\n absoluteXpathElements: string[],\r\n element2: HTMLElement | Element,\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Node,\r\n relation: string,\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let finalExpectedElementXpath: string | undefined;\r\n if (!multiElementReferenceMode) {\r\n for (let x = 1; x <= absoluteXpathElements.length; x++) {\r\n const xpath2 = absoluteXpathElements\r\n .slice(absoluteXpathElements.length - x, absoluteXpathElements.length)\r\n .join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n const xpath2 = absoluteXpathElements.join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath),\r\n },\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst referenceXpath = {\r\n findRelativeXpath,\r\n getDescendantXpath,\r\n getXpathRelationExpression,\r\n getTraverseXpathExpression,\r\n getReferenceElementXpath,\r\n};\r\n\r\nexport default referenceXpath;\r\n","import { SelectorMode } from \"../types/locator.ts\";\r\nimport { isNumberExist } from \"./xpathHelpers.ts\";\r\n\r\nlet modifiedElementAttributes: [] = [];\r\n\r\nconst escapeCssAttributeValue = (value: string): string => {\r\n return String(value).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\r\n};\r\n\r\nconst isCssSelectorUnique = (\r\n selector: string,\r\n el: Element,\r\n root: Document | ShadowRoot | ParentNode\r\n): boolean => {\r\n try {\r\n const matches = root.querySelectorAll(selector);\r\n return matches.length === 1 && matches[0] === el;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\n\r\nexport const parseCssSelectors = (el: Element, mode: SelectorMode='single') => {\r\n const selectors: { key: string; value: string }[] = [];\r\n const root = el.getRootNode() as Document | ShadowRoot;\r\n\r\n try {\r\n const idPath = getIdCssPath(el);\r\n if (idPath && isCssSelectorUnique(idPath, el, root)) {\r\n selectors.push({ key: 'cssSelector by id', value: idPath });\r\n if (mode === 'single') return selectors;\r\n }\r\n const classPath = getClassCssPath(el);\r\n if (classPath && isCssSelectorUnique(classPath, el, root)) {\r\n selectors.push({ key: 'cssSelector by class', value: classPath });\r\n }\r\n const namePath = getAttributeCssPath(el);\r\n if (namePath) {\r\n selectors.push({ key: 'cssSelector by name', value: namePath });\r\n }\r\n const absPath = getAbsoluteCssPath(el);\r\n if (absPath && isCssSelectorUnique(absPath, el, root)) {\r\n selectors.push({ key: 'Absolute cssSelector', value: absPath });\r\n }\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n return selectors;\r\n};\r\n\r\n\r\nexport const getIdCssPath = (el: HTMLElement | Element,) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n if (el.id && !isNumberExist(el.id)) {\r\n selector += `#${CSS.escape(el.id)}`;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nconst EXCLUDED_ATTRS = new Set([\r\n 'id',\r\n 'class',\r\n 'style'\r\n]);\r\nfunction getAttributeSelectors(el: Element): string[] {\r\n return Array.from(el.attributes)\r\n .filter(attr =>\r\n !EXCLUDED_ATTRS.has(attr?.name?.toLowerCase()) &&\r\n attr.value &&\r\n !isNumberExist(attr.value)\r\n )\r\n .map(attr =>\r\n `[${attr.name}=\"${escapeCssAttributeValue(attr.value)}\"]`\r\n );\r\n}\r\n\r\n\r\nexport const getAttributeCssPath = (\r\n el: Element\r\n): string | undefined => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const root = el.getRootNode() as ParentNode;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === 'style' || tag === 'script') return;\r\n\r\n const attrSelectors = getAttributeSelectors(el);\r\n\r\n for (const attrSelector of attrSelectors) {\r\n const candidate = `${tag}${attrSelector}`;\r\n\r\n if (isCssSelectorUnique(candidate, el, root)) {\r\n return candidate;\r\n }\r\n }\r\n return;\r\n};\r\n\r\n\r\n\r\nexport const getClassCssPath = (el: HTMLElement | Element,) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();;\r\n if (tagName.includes('style') || tagName.includes('script')) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n\r\n if (\r\n typeof el.className === 'string' &&\r\n el.className &&\r\n !isNumberExist(el.className) &&\r\n !modifiedElementAttributes?.find(\r\n (x: { element: HTMLElement | Element; attributeName: string; }) => x.element === el && x.attributeName === 'class'\r\n )\r\n ) {\r\n el.classList.remove('marked-element-temp');\r\n el.classList.remove('removePointers');\r\n if (el.className) {\r\n selector += `.${el.className.trim().replace(/\\s+/g, '.')}`;\r\n path.unshift(selector);\r\n break;\r\n }\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(' > ');\r\n};\r\n\r\nexport const getAbsoluteCssPath = (el: Element) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const path: string[] = [];\r\n\r\n while (el && el.nodeType === Node.ELEMENT_NODE) {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (tagName === 'style' || tagName === 'script') return;\r\n\r\n let selector = tagName;\r\n\r\n const parent = el.parentNode;\r\n\r\n if (parent) {\r\n const siblings = Array.from(parent.children)\r\n .filter(c => c.tagName === el.tagName);\r\n\r\n if (siblings.length > 1) {\r\n selector += `:nth-of-type(${siblings.indexOf(el) + 1})`;\r\n }\r\n }\r\n\r\n path.unshift(selector);\r\n\r\n el = el.parentElement!;\r\n }\r\n\r\n return path.join(' > ');\r\n};\r\n\r\nexport const cssSelectors = {\r\n parseCssSelectors,\r\n getIdCssPath,\r\n getAttributeCssPath,\r\n getClassCssPath,\r\n getAbsoluteCssPath\r\n}","import { ElementRecord, Locator } from \"../types/locator.ts\";\r\nimport { parseDOM } from \"./xpath.ts\";\r\nimport { parseCssSelectors } from \"./cssSelector.ts\";\r\nimport {\r\n isNumberExist,\r\n normalizeXPath,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM,\r\n shouldUseSnapshot\r\n} from \"./xpathHelpers.ts\";\r\n\r\nconst isSameXPathStillValid = (\r\n xpath: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n const normalized = normalizeXPath(xpath);\r\n const found = getElementFromXPath(docmt, normalized);\r\n if (found === target) return true;\r\n\r\n if (shouldUseSnapshot(normalized)) {\r\n const result = docmt.evaluate(\r\n normalized,\r\n docmt,\r\n null,\r\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\r\n null\r\n );\r\n\r\n for (let i = 0; i < result.snapshotLength; i++) {\r\n if (result.snapshotItem(i) === target) return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst getElementFromCssSelector = (\r\n docmt: Document,\r\n selector: string\r\n): Element | null => {\r\n try {\r\n const found = docmt.querySelector(selector);\r\n if (found) return found;\r\n } catch (error) {\r\n console.error(\"Invalid CSS selector:\", selector, error);\r\n return null;\r\n }\r\n\r\n return getElementFromShadowRoot(docmt.body, selector);\r\n};\r\n\r\nconst isSameCssSelectorStillValid = (\r\n selector: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n return getElementFromCssSelector(docmt, selector) === target;\r\n};\r\n\r\nconst resolveIsSelfHealed = (\r\n locName: string,\r\n oldValue: string | null | undefined,\r\n newValue: string | null | undefined\r\n): \"Y\" | null => {\r\n if (!oldValue || !newValue) return \"Y\";\r\n return oldValue === newValue ? null : \"Y\";\r\n};\r\n\r\nconst isCssSelectorLocator = (locator: { name?: string | null }): boolean => {\r\n return locator.name?.toLowerCase().includes(\"cssselector\") ?? false;\r\n};\r\n\r\ntype ElementDetails = {\r\n id?: string | null;\r\n className?: string | null;\r\n xpathByText?: string | null;\r\n xpathById?: string | null;\r\n xpathByClass?: string | null;\r\n xpathAbsolute?: string | null;\r\n xpathByName?: string | null;\r\n xpathByPlaceholder?: string | null;\r\n xpathByType?: string | null;\r\n visibleText?: string | null;\r\n relativeXpath?: string | null;\r\n [key: string]: any;\r\n};\r\n\r\nconst getElementFromShadowRoot = (\r\n el: Element | ShadowRoot,\r\n selector: string\r\n): Element | null => {\r\n // const shadowRoot = (element as HTMLElement).shadowRoot;\r\n // if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n // return shadowRoot.querySelector(selector);\r\n // }\r\n\r\n const elements = Array.from(el.querySelectorAll(\"*\"));\r\n\r\n try {\r\n for (let i = 0; i < elements.length; i++) {\r\n if (elements[i].shadowRoot) {\r\n const { shadowRoot } = elements[i];\r\n if (shadowRoot) {\r\n const nestedElement = getElementFromShadowRoot(shadowRoot, selector);\r\n if (nestedElement) {\r\n return nestedElement;\r\n }\r\n if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n return shadowRoot.querySelector(selector);\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n return null;\r\n};\r\n\r\nconst getId = (element: Element | null): string | null => {\r\n return element?.id || null;\r\n};\r\n\r\nconst getClassName = (element: Element): string | null => {\r\n return (element as HTMLElement).className || null;\r\n};\r\n\r\nconst getVisibleText = (element: Element): string | null => {\r\n return element.textContent?.trim() || null;\r\n};\r\n\r\nconst getName = (element: Element): string | null => {\r\n const elementEl = element as HTMLElement;\r\n\r\n if (elementEl.hasAttribute(\"name\")) {\r\n const attrValue = elementEl.getAttribute(\"name\");\r\n const name = `${attrValue}`;\r\n return name || null;\r\n }\r\n return null;\r\n};\r\n\r\nconst relations: string[] = [\r\n \"/preceding-sibling\",\r\n \"/following-sibling\",\r\n \"/parent\",\r\n \"/descendant\",\r\n \"/ancestor\",\r\n \"/self\",\r\n \"/ancestor-or-self\",\r\n \"/child\",\r\n \"/preceding\",\r\n \"/following\"\r\n];\r\n\r\nfunction getElementFromXPath(docmt: Document, xpath: string): Element | null {\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n return xpathResult.singleNodeValue as Element | null;\r\n}\r\n\r\nfunction checkReferenceElementIsValid(\r\n locator: string,\r\n relation: string,\r\n docmt: Document\r\n): string | null {\r\n if (locator.includes(relation)) {\r\n const locatotSplitArray: string[] = locator.split(relation);\r\n const sourceLoc = locatotSplitArray[0].trim();\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n if (!locator.includes(\"dynamic\")) {\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n sourceLoc,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n const sourceElement = xpathResult.singleNodeValue;\r\n if (sourceElement) {\r\n const xpathResultComplete = xpathEvaluator.evaluate(\r\n locator,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n const completeElement = xpathResultComplete.singleNodeValue;\r\n let relativeXpath: string;\r\n if (completeElement) {\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n } else {\r\n console.error(\"Complete Locator is Invalid:\", locator);\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n }\r\n } else {\r\n console.error(\"Source Locator Not Found:\", sourceLoc);\r\n }\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nconst getElementsFromHTML = (\r\n record: ElementRecord,\r\n docmt: Document\r\n): ElementDetails | null => {\r\n const elementsToRemove = docmt.querySelectorAll(\r\n \"script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg\"\r\n );\r\n\r\n if (elementsToRemove) {\r\n elementsToRemove.forEach((tag) => {\r\n (tag as Element).remove();\r\n });\r\n }\r\n\r\n const finalLocatorsSet: Set<string> = new Set();\r\n let finalLocators: any[] = [];\r\n\r\n function createLocator(base: any, overrides: Partial<any> = {}) {\r\n const oldValue = base?.value;\r\n const newValue = overrides.value ?? base?.value;\r\n const newLocator: any = {\r\n name: overrides.name ?? base?.name,\r\n type: overrides.type ?? base?.type,\r\n value: overrides.value ?? base?.value,\r\n reference: overrides.reference ?? base?.reference,\r\n status: overrides.status ?? base?.status,\r\n isRecorded: overrides.isRecorded ?? base?.isRecorded\r\n };\r\n\r\n const previousSelfHealed = base?.isSelfHealed === \"Y\";\r\n\r\n newLocator.isSelfHealed = previousSelfHealed\r\n ? \"Y\"\r\n : overrides.hasOwnProperty(\"isSelfHealed\")\r\n ? overrides.isSelfHealed\r\n : resolveIsSelfHealed(newLocator.name, oldValue, newValue);\r\n\r\n pushUniqueLocator(newLocator);\r\n }\r\n\r\n function resolveElement(\r\n ctx: Document,\r\n locator: any,\r\n selector: string\r\n ): Element | null {\r\n if (isCssSelectorLocator(locator)) {\r\n return getElementFromCssSelector(ctx, selector);\r\n } else if (locator.name.includes(\"id\") || selector.startsWith(\"#\")) {\r\n return ctx.querySelector(\"#\" + escapeAttrValue(selector));\r\n } else if (locator.name.includes(\"className\") || selector.startsWith(\".\")) {\r\n return ctx.querySelector(\".\" + selector);\r\n } else if (locator.name === \"name\") {\r\n const safeName = escapeAttrValue(selector);\r\n return ctx.querySelector(`[name=\"${safeName}\"]`);\r\n } else if (locator.name === \"tagName\") {\r\n return ctx.querySelector(selector);\r\n } else if (locator.name === \"linkText\") {\r\n return (\r\n Array.from(ctx.querySelectorAll(\"a\")).find(\r\n (a) => a.textContent?.trim() === selector\r\n ) || null\r\n );\r\n } else if (locator.name === \"partialLinkText\") {\r\n return (\r\n Array.from(ctx.querySelectorAll(\"a\")).find((a) =>\r\n a.textContent?.includes(selector)\r\n ) || null\r\n );\r\n } else if (\r\n (locator.name.includes(\"xpath\") || selector.startsWith(\"//\")) &&\r\n !locator.type.match(\"dynamic\")\r\n ) {\r\n const normalizedXPath = normalizeXPath(selector);\r\n const el = getElementFromXPath(ctx, normalizedXPath);\r\n\r\n if (el) {\r\n createLocator(locator, {\r\n value: selector,\r\n isRecorded: String(locator.isRecorded).includes(\"N\") ? \"N\" : \"Y\"\r\n });\r\n }\r\n\r\n return el;\r\n } else {\r\n return ctx.querySelector(selector);\r\n }\r\n }\r\n\r\n function findInIframes(\r\n docmt: Document,\r\n locator: any,\r\n selector: string\r\n ): Element | null {\r\n const iframes = docmt.querySelectorAll(\"iframe\");\r\n\r\n for (const iframe of iframes) {\r\n try {\r\n const iframeDoc =\r\n iframe.contentDocument || iframe.contentWindow?.document;\r\n\r\n if (!iframeDoc) continue;\r\n\r\n const el = resolveElement(iframeDoc, locator, selector);\r\n if (el) return el;\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n function pushUniqueLocator(obj: any) {\r\n const key = `${obj.name}:${obj.value}`;\r\n if (!finalLocatorsSet.has(key)) {\r\n finalLocatorsSet.add(key);\r\n finalLocators.push(obj);\r\n }\r\n }\r\n\r\n /** Locator Value Cleaner (Handles Special Scenarios) **/\r\n const cleanLocatorValue = (\r\n val: string | null | undefined,\r\n type?: string,\r\n isRecorded?: string\r\n ): string | null => {\r\n if (!val) return null;\r\n\r\n let cleaned = val.trim();\r\n\r\n // Return null for empty or literal \"null\"\r\n if (!cleaned || cleaned.toLowerCase() === \"null\") return null;\r\n\r\n // Unescape any escaped quotes\r\n cleaned = cleaned.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\");\r\n\r\n // Remove surrounding single or double quotes\r\n cleaned = cleaned.replace(/^['\"](.+?)['\"]$/, \"$1\");\r\n\r\n // Replace double single quotes with a single quote inside XPath\r\n cleaned = cleaned.replace(/''/g, \"'\");\r\n\r\n // Normalize double quotes in XPath attribute selectors [@id=\"\" -> [@id='']\r\n cleaned = cleaned.replace(\r\n /\\[@(id|name)=['\"]{2}(.+?)['\"]{2}\\]/g,\r\n \"[@$1='$2']\"\r\n );\r\n\r\n // For DOM selectors (id or name), remove ALL quotes\r\n if (type === \"id\" || type === \"name\") {\r\n cleaned = cleaned.replace(/['\"]/g, \"\").trim();\r\n }\r\n\r\n if (type === \"xpath\" && isRecorded === \"Y\" && !val.startsWith(\"//\"))\r\n return null;\r\n\r\n // Final check for empty strings\r\n if (!cleaned || /^['\"]{2}$/.test(cleaned)) return null;\r\n\r\n return cleaned;\r\n };\r\n\r\n locators: for (const locator of record.locators) {\r\n try {\r\n const isRecorded = String(locator.isRecorded || \"\");\r\n const recordedNLocators = record.locators.filter(\r\n (l) => l.isRecorded === \"N\"\r\n );\r\n\r\n if (recordedNLocators.length > 0) {\r\n for (const locator of recordedNLocators) {\r\n createLocator(locator);\r\n }\r\n }\r\n\r\n const isDynamic = String(locator.value || locator.type || \"\");\r\n if (\r\n isDynamic.includes(\"dynamic\") ||\r\n isDynamic.match(\"dynamic\") ||\r\n isDynamic.includes(\"{\") ||\r\n isDynamic.includes(\"}\")\r\n ) {\r\n createLocator(locator);\r\n continue;\r\n }\r\n\r\n if (record.isShared.includes(\"Y\")) {\r\n break locators;\r\n }\r\n\r\n try {\r\n let targetElement: Element | null = null;\r\n const selectors = locator.value.split(\">>>\");\r\n\r\n for (const selector of selectors) {\r\n if (!docmt) {\r\n console.error(\"Element not found at:\", selector);\r\n break;\r\n }\r\n\r\n const trimmedSelector = selector.trim();\r\n\r\n //normal DOM\r\n targetElement = resolveElement(docmt, locator, trimmedSelector);\r\n\r\n //iframe (if not found)\r\n if (!targetElement) {\r\n targetElement = findInIframes(docmt, locator, trimmedSelector);\r\n }\r\n\r\n //shadow DOM (if still not found)\r\n if (!targetElement) {\r\n targetElement = getElementFromShadowRoot(\r\n docmt.body,\r\n trimmedSelector\r\n );\r\n }\r\n\r\n if (!targetElement) {\r\n console.error(\"Element not found at:\", trimmedSelector);\r\n break;\r\n }\r\n }\r\n\r\n const locatorExists = (name: string, value: string): boolean => {\r\n const key = `${name}:${value}`;\r\n return finalLocatorsSet.has(key);\r\n };\r\n\r\n if (targetElement) {\r\n const payloadXPaths = record.locators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n const payloadCssSelectors = record.locators.filter(\r\n (l) => isCssSelectorLocator(l) && l.value\r\n );\r\n\r\n for (const px of payloadXPaths) {\r\n if (isSameXPathStillValid(px.value, docmt, targetElement))\r\n createLocator(px, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n for (const cssLocator of payloadCssSelectors) {\r\n if (\r\n isSameCssSelectorStillValid(\r\n cssLocator.value,\r\n docmt,\r\n targetElement\r\n )\r\n )\r\n createLocator(cssLocator, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n const existingXPaths = finalLocators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n // Track XPath patterns already used\r\n const usedXPathPatterns = new Set<string>(\r\n existingXPaths.map((x) => getXPathPattern(x.value))\r\n );\r\n\r\n const excludedAttributes: string[] = [];\r\n const idValue = getId(targetElement);\r\n if (\r\n idValue &&\r\n !locatorExists(\"id\", idValue) &&\r\n !isNumberExist(idValue)\r\n ) {\r\n const prevId = record.locators.find((l) => l.name === \"id\");\r\n if (isUniqueInDOM(docmt, \"id\", idValue, targetElement)) {\r\n excludedAttributes.push(\"id\");\r\n createLocator(prevId, {\r\n name: \"id\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: idValue\r\n });\r\n }\r\n }\r\n\r\n const tagName = targetElement.tagName;\r\n if (tagName && !locatorExists(\"tagName\", tagName)) {\r\n const prevTag = record.locators.find((l) => l.name === \"tagName\");\r\n if (isUniqueInDOM(docmt, \"tagName\", tagName, targetElement)) {\r\n excludedAttributes.push(\"tagName\");\r\n createLocator(prevTag, {\r\n name: \"tagName\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: tagName\r\n });\r\n }\r\n }\r\n\r\n const textValue = getVisibleText(targetElement);\r\n if (textValue && !isNumberExist(textValue)) {\r\n const prevLinkText = record.locators.find(\r\n (l) => l.name === \"linkText\"\r\n );\r\n if (isUniqueInDOM(docmt, \"linkText\", textValue, targetElement)) {\r\n excludedAttributes.push(\"linkText\");\r\n createLocator(prevLinkText, {\r\n name: \"linkText\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: textValue\r\n });\r\n }\r\n }\r\n\r\n const nameLocator = getName(targetElement);\r\n if (\r\n nameLocator &&\r\n !locatorExists(\"name\", nameLocator) &&\r\n !isNumberExist(nameLocator)\r\n ) {\r\n const prevName = record.locators.find((l) => l.name === \"name\");\r\n if (isUniqueInDOM(docmt, \"name\", nameLocator, targetElement)) {\r\n excludedAttributes.push(\"name\");\r\n createLocator(prevName, {\r\n name: \"name\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: nameLocator\r\n });\r\n }\r\n }\r\n\r\n const classValue = getClassName(targetElement);\r\n if (\r\n classValue &&\r\n classValue.trim() !== \"\" &&\r\n !classValue.includes(\" \") &&\r\n !locatorExists(\"className\", classValue) &&\r\n !isNumberExist(classValue)\r\n ) {\r\n const prevClassLocator = record.locators.find(\r\n (l) => l.name === \"className\"\r\n );\r\n if (isUniqueInDOM(docmt, \"className\", classValue, targetElement)) {\r\n excludedAttributes.push(\"className\");\r\n createLocator(prevClassLocator, {\r\n name: \"className\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: classValue\r\n });\r\n }\r\n }\r\n parseCssSelectors(targetElement, \"single\").forEach(\r\n (cssSelector) => {\r\n if (\r\n cssSelector.value &&\r\n !locatorExists(\"cssSelector\", cssSelector.value)\r\n ) {\r\n createLocator(undefined, {\r\n name: \"cssSelector\",\r\n value: cssSelector.value,\r\n type: \"static\",\r\n isRecorded: \"Y\"\r\n });\r\n }\r\n }\r\n );\r\n const allAttributes = Array.from(targetElement.attributes);\r\n const includedAttributes = allAttributes.filter(\r\n (attr) => !excludedAttributes.includes(attr.name)\r\n );\r\n\r\n //If any direct locator is broken then we consider it as broken xpath\r\n\r\n let xpathResults: any[] = [];\r\n try {\r\n xpathResults =\r\n parseDOM(targetElement, docmt, false, true, includedAttributes) ??\r\n [];\r\n } catch (error) {\r\n console.error(\"Error generating XPath candidates:\", error);\r\n }\r\n\r\n if (xpathResults?.length !== 0) {\r\n const brokenPayloadXPaths = payloadXPaths.filter(\r\n (px) => !isSameXPathStillValid(px.value, docmt, targetElement)\r\n );\r\n\r\n let xpathAdded = 0;\r\n\r\n for (const brokenPx of brokenPayloadXPaths) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n\r\n const originalPattern = getXPathPattern(brokenPx.value);\r\n if (usedXPathPatterns.has(originalPattern)) continue;\r\n\r\n const match = xpathResults.find(\r\n (r) => r.value && getXPathPattern(r.value) === originalPattern\r\n );\r\n\r\n if (match?.value) {\r\n createLocator(brokenPx, {\r\n name: \"xpath\",\r\n value: match.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(originalPattern);\r\n xpathAdded++;\r\n }\r\n }\r\n if (xpathAdded < brokenPayloadXPaths.length) {\r\n for (const result of xpathResults) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n if (!result.value) continue;\r\n\r\n const pattern = getXPathPattern(result.value);\r\n if (usedXPathPatterns.has(pattern)) continue;\r\n\r\n createLocator(result, {\r\n name: \"xpath\",\r\n value: result.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(pattern);\r\n xpathAdded++;\r\n }\r\n }\r\n }\r\n for (const locator of record.locators) {\r\n try {\r\n for (const loc of record.locators) {\r\n if (!loc.value) continue;\r\n\r\n for (const relation of relations) {\r\n if (loc.value.includes(relation)) {\r\n const relativeXpath = checkReferenceElementIsValid(\r\n loc.value,\r\n relation,\r\n docmt\r\n );\r\n if (relativeXpath) {\r\n createLocator(loc, {\r\n name: \"xpath\",\r\n value: relativeXpath,\r\n isRecorded:\r\n locator.isRecorded !== \"\" &&\r\n locator.isRecorded !== null\r\n ? locator.isRecorded\r\n : \"Y\"\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n }\r\n }\r\n if (finalLocators.length < 5) {\r\n const fallbackCandidates = [\r\n { name: \"id\", value: getId(targetElement) },\r\n { name: \"name\", value: getName(targetElement) },\r\n { name: \"className\", value: getClassName(targetElement) },\r\n { name: \"tagName\", value: targetElement.tagName },\r\n { name: \"linkText\", value: getVisibleText(targetElement) }\r\n ];\r\n\r\n for (const candidate of fallbackCandidates) {\r\n if (finalLocators.length > 4) break;\r\n\r\n const { name, value } = candidate;\r\n if (!value) continue;\r\n if (isNumberExist(value)) continue;\r\n if (locatorExists(name, value)) continue;\r\n if (name === \"className\" && value.includes(\" \")) continue;\r\n if (isUniqueInDOM(docmt, name, value, targetElement)) {\r\n createLocator(undefined, {\r\n name,\r\n type: \"static\",\r\n value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n }\r\n\r\n if (finalLocators.length < 5) {\r\n parseCssSelectors(targetElement, \"multiple\").forEach(\r\n (cssSelector) => {\r\n if (finalLocators.length > 4) return;\r\n if (!cssSelector.value) return;\r\n if (locatorExists(\"cssSelector\", cssSelector.value)) return;\r\n if (\r\n !isUniqueInDOM(\r\n docmt,\r\n \"cssSelector\",\r\n cssSelector.value,\r\n targetElement\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n createLocator(undefined, {\r\n name: \"cssSelector\",\r\n type: \"static\",\r\n value: cssSelector.value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n );\r\n }\r\n }\r\n\r\n const finalAutoHealedLocators = finalLocators.map((obj) => ({\r\n ...obj,\r\n value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded)\r\n }));\r\n\r\n const jsonResult = [\r\n {\r\n name: `${record.name}`,\r\n desc: `${record.desc}`,\r\n type: `${record.type}`,\r\n locators: finalAutoHealedLocators.filter(\r\n (locator) => locator?.value != null && locator.value !== \"\"\r\n ),\r\n isShared: `${record.isShared}`,\r\n projectId: `${record.projectId}`,\r\n projectType: `${record.projectType}`,\r\n isRecorded: `${record.isRecorded}`,\r\n folder: `${record.folder}`,\r\n parentId: `${record.parentId}`,\r\n parentName: `${record.parentName}`,\r\n platform: `${record.platform}`,\r\n licenseId: `${record.licenseId}`,\r\n licenseType: `${record.licenseType}`,\r\n userId: `${record.userId}`\r\n }\r\n ];\r\n\r\n return jsonResult;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nexport { getElementsFromHTML };\r\n","import xpath from '../utils/xpath.ts';\r\nimport referenceXpaths from '../utils/referenceXpath.ts';\r\nimport { xpathUtils } from '../utils/xpathHelpers.ts';\r\nimport { getElementsFromHTML } from '../utils/getElementsFromHTML.ts';\r\nimport { cssSelectors } from '../utils/cssSelector.ts';\r\n\r\nexport const createXPathAPI = () => ({\r\n xpath,\r\n referenceXpaths,\r\n xpathUtils,\r\n getElementsFromHTML,\r\n cssSelectors\r\n});\r\n\r\nexport default createXPathAPI;"],"names":["reWhiteSpace","xpathCache","mutationObserver","relativeXPathCache","Map","modifiedElementAttributes","isNumberExist","str","test","getTextContent","targetElement","textContent","getFilteredText","element","childNodes","nodeValue","getCountOfXPath","xpath","docmt","multiElementReferenceMode","count","undefined","nodeType","ownerDocument","evaluate","XPathResult","NUMBER_TYPE","numberValue","Array","isArray","elementsFromXpath","getElementFromXpath","nodex","matchedCount","iterateNext","includes","error","console","escapeCharacters","text","indexOf","removeParenthesis","charArr","split","length","indexArray","push","reverse","finalStr","i","endBracketLength","firstpart","slice","startsWith","endsWith","findXpathWithIndex","val","node","owner","index","nodes","ANY_TYPE","isSameNode","log","deleteGarbageFromInnerText","a","deleteLineGap","reduce","b","c","trim","replaceWhiteSpaces","replace","getShadowRoot","el","getRootNode","root","host","checkBlockedAttributes","attribute","isTarget","value","some","x","name","isModified","find","doc","attributeName","isSvg","SVGElement","replaceTempAttributes","multi","contextNode","Node","DOCUMENT_FRAGMENT_NODE","DOCUMENT_NODE","FIRST_ORDERED_NODE_TYPE","singleNodeValue","getPropertyXPath","prop","isIndex","tagName","combinePattern","mergePattern","pattern","buildPattern","toLowerCase","splitText","contentRes","Set","match","endIndex","startIndexString","join","endIndexString","getAbsoluteXPath","domNode","xpathe","parentElement","prototype","call","children","filter","childNode","HTMLElement","offsetParent","getRelativeXPath","attributesArray","has","get","xpathParts","currentNode","hasUniqueAttr","attributes","attrName","from","attrValue","elementName","getXpathString","othersWithAttr","unshift","RegExp","tagBasedXPath","siblings","finalXPath","set","getCombinationXpath","getAttributeCombinationXpath","uniqueAttributes","xpathAttributes","nodeName","ign","JSON","stringify","intermediateXpathStep","targetElemt","attr","isSvgElement","expression","getFilteredTextXPath","filteredText","getTextXpathFunction","trimmedText","replaceActualAttributes","getReferenceElementsXpath","nodeXpath1","xpaths1","key","combinationXpath","tag","xpaths","map","xpth","addAttributeSplitCombineXpaths","concat","normalizeXPath","findMatchingParenthesis","openPos","closePos","counter","getXPathPattern","canonical","canonicalizeXPath","parts","xp","axisMatch","axis","attrMatch","usesNormalize","extractXPathSignatureParts","escapeAttrValue","isUniqueInDOM","queryAll","selector","querySelectorAll","xpathUtils","parseXml","xmlStr","type","window","DOMParser","parseFromString","getRelationship","pos","compareDocumentPosition","createObserver","addedNodeCallBack","MutationObserver","mutations","forEach","mutation","addedNodes","target","oldValue","classList","url","baseURI","startObserver","options","observe","stopObserver","disconnect","cspEnabled","xpathData","xpathDataWithIndex","cache","parentXpathCache","checkRelativeXpathRelation","nodeXpath2","relationType","pop","indexedXpath","getUniqueParentXpath","nodeXpath","getParentRelativeXpath","uniqueAttrFound","textXPath","finalXpath","getChildRelativeXpath","st","firstElementChild","contains","nextElementSibling","m","getSiblingRelativeXPath","markedSpan","document","querySelector","processSibling","n","previousElementSibling","sibling","hasAttributes","getXPathUsingAttributeAndText","addRelativeXpaths","relativeXpath","relativeChildXpath","fullRelativeXpath","relativeXpathIndex","substring","txtXpath","getTextXPath","tempRelativeXpath","attributesBasedXPath","getUniqueClassName","className","addAllXPathAttributes","textAttribute","parseDOM","includedAttributes","attributesToUse","len","descendantExpression","refExpectElement","xpath2","relation","expCommonParentXpathElements","step4","refCommonParentXpathElementLength","finalExpectedElementXpath","xpaths2Els","xpath2Elements","traverseXpath","getTraverseXpathExpression","repeat","rel_count","getDescendantXpath","xpaths2","refElement","expElement","expElementDocmnt","refAbsoluteXpath","refFullXpathElements","refFullXpathElementsWithoutNumber","expAbsoluteXpath","expFullXpathElements","expFullXpathElementsWithoutNumber","parentElementNumber","refCommonParentXpathElements","j","refCommonParentXpath","getXpathRelationExpression","element1","element2","xpath1","finalXpaths","rel_xpath","xpathe1","absoluteXpathElements","referenceXpath","findRelativeXpath","par1","par2","tempElement","xpathWithIndex","parentNode","descendantXpath","descendantSelfXpath","sort","getReferenceElementXpath","charAt","lastIndexOf","referenceXpathElement","isCssSelectorUnique","matches","parseCssSelectors","mode","selectors","idPath","getIdCssPath","classPath","getClassCssPath","namePath","getAttributeCssPath","absPath","getAbsoluteCssPath","e","view","defaultView","Element","path","ELEMENT_NODE","id","CSS","escape","sib","nth","childElementCount","EXCLUDED_ATTRS","getAttributeSelectors","String","attrSelectors","attrSelector","candidate","remove","parent","cssSelectors","isSameXPathStillValid","normalized","getElementFromXPath","shouldUseSnapshot","result","ORDERED_NODE_SNAPSHOT_TYPE","snapshotLength","snapshotItem","getElementFromCssSelector","found","getElementFromShadowRoot","body","isSameCssSelectorStillValid","isCssSelectorLocator","locator","elements","shadowRoot","nestedElement","getId","getClassName","getVisibleText","getName","elementEl","hasAttribute","getAttribute","relations","XPathEvaluator","checkReferenceElementIsValid","sourceLoc","xpathEvaluator","getElementsFromHTML","record","elementsToRemove","finalLocatorsSet","finalLocators","createLocator","base","overrides","newValue","newLocator","reference","status","isRecorded","previousSelfHealed","isSelfHealed","hasOwnProperty","locName","resolveIsSelfHealed","obj","add","pushUniqueLocator","resolveElement","ctx","safeName","findInIframes","iframes","iframe","iframeDoc","contentDocument","contentWindow","cleanLocatorValue","cleaned","locators","recordedNLocators","l","isDynamic","isShared","trimmedSelector","locatorExists","payloadXPaths","payloadCssSelectors","px","cssLocator","existingXPaths","usedXPathPatterns","excludedAttributes","idValue","prevId","prevTag","textValue","prevLinkText","nameLocator","prevName","classValue","prevClassLocator","cssSelector","xpathResults","brokenPayloadXPaths","xpathAdded","brokenPx","originalPattern","r","loc","fallbackCandidates","finalAutoHealedLocators","jsonResult","desc","projectId","projectType","folder","parentId","parentName","platform","licenseId","licenseType","userId","createXPathAPI","referenceXpaths"],"mappings":"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"}
1
+ {"version":3,"file":"index.browser.js","sources":["../src/utils/xpathHelpers.ts","../src/utils/xpath.ts","../src/utils/referenceXpath.ts","../src/utils/cssSelector.ts","../src/utils/getElementsFromHTML.ts","../src/utils/iosSelector.ts","../src/browser/xpath.ts"],"sourcesContent":["export const reWhiteSpace = /^[\\S]+( [\\S]+)*$/i;\r\nexport let cspEnabled: boolean = false;\r\nconst xpathCache: { [x: string]: number } = {};\r\n\r\nexport const timeLog = (label: string, start: number) => {\r\n const duration = performance.now() - start;\r\n console.log(`⏱️ ${label}: ${duration.toFixed(2)}ms time`);\r\n};\r\n\r\ntype EvalResult = {\r\n first: Node | null;\r\n second: Node | null;\r\n};\r\n\r\n// cache per context node → avoids cross-context pollution\r\nlet xpathEvalCache = new WeakMap<Node, Map<string, EvalResult>>();\r\n\r\nconst getXPathContext = (docmt: Node) => {\r\n const owner: Document =\r\n docmt.nodeType === 9\r\n ? (docmt as Document)\r\n : docmt.ownerDocument || document;\r\n\r\n // valid XPath context nodes: Element(1), Document(9), DocumentFragment/ShadowRoot(11)\r\n const contextNode: Node =\r\n docmt.nodeType === 1 || docmt.nodeType === 9 || docmt.nodeType === 11\r\n ? docmt\r\n : owner;\r\n\r\n return { owner, contextNode };\r\n};\r\n\r\nconst getMutationCacheContexts = (node: Node): Node[] => {\r\n const contexts: Node[] = [];\r\n const addContext = (candidate: Node | null | undefined) => {\r\n if (!candidate || contexts.includes(candidate)) return;\r\n contexts.push(candidate);\r\n };\r\n\r\n addContext(node);\r\n\r\n const rootNode = node.getRootNode?.();\r\n if (rootNode instanceof Document || rootNode instanceof ShadowRoot) {\r\n addContext(rootNode);\r\n }\r\n\r\n const ownerDocument =\r\n node.nodeType === Node.DOCUMENT_NODE\r\n ? (node as Document)\r\n : node.ownerDocument;\r\n addContext(ownerDocument);\r\n\r\n return contexts;\r\n};\r\n\r\nexport const clearXPathEvalCache = (node?: Node | null) => {\r\n if (!node) {\r\n xpathEvalCache = new WeakMap<Node, Map<string, EvalResult>>();\r\n return;\r\n }\r\n\r\n getMutationCacheContexts(node).forEach((contextNode) => {\r\n xpathEvalCache.delete(contextNode);\r\n });\r\n};\r\n\r\nexport const evaluateXPathOnce = (xpath: string, docmt: Node): EvalResult => {\r\n const { owner, contextNode } = getXPathContext(docmt);\r\n\r\n // get or create cache for this context node\r\n let nodeCache = xpathEvalCache.get(contextNode);\r\n if (!nodeCache) {\r\n nodeCache = new Map<string, EvalResult>();\r\n xpathEvalCache.set(contextNode, nodeCache);\r\n }\r\n\r\n // cache hit\r\n const cached = nodeCache.get(xpath);\r\n if (cached) return cached;\r\n\r\n // evaluate once, stop after 2 nodes\r\n const result = owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.ORDERED_NODE_ITERATOR_TYPE,\r\n null\r\n );\r\n\r\n const first = result.iterateNext();\r\n const second = result.iterateNext();\r\n\r\n const evalResult: EvalResult = { first, second };\r\n nodeCache.set(xpath, evalResult);\r\n\r\n return evalResult;\r\n};\r\nlet relativeXPathCache = new Map();\r\nexport let modifiedElementAttributes: {\r\n url: string | null;\r\n attributeName: string | null;\r\n element: HTMLElement | Element;\r\n doc: Document;\r\n}[] = [];\r\nlet mutationObserver: MutationObserver;\r\nconst INTERNAL_CLASS_TOKENS = new Set([\r\n \"marked-element-temp\",\r\n \"removePointers\"\r\n]);\r\n\r\nconst normalizeClassTokens = (\r\n classValue: string | null | undefined\r\n): string[] =>\r\n (classValue || \"\")\r\n .split(/\\s+/)\r\n .map((token) => token.trim())\r\n .filter((token) => token && !INTERNAL_CLASS_TOKENS.has(token))\r\n .sort();\r\n\r\nexport const sanitizeAttributeValue = (\r\n attributeName: string,\r\n attributeValue: string | null | undefined\r\n): string => {\r\n if (!attributeValue) {\r\n return \"\";\r\n }\r\n\r\n if (attributeName === \"class\" || attributeName === \"className\") {\r\n return normalizeClassTokens(attributeValue).join(\" \");\r\n }\r\n\r\n return attributeValue.replace(\"removePointers\", \"\").trim();\r\n};\r\n\r\nconst isInternalClassOnlyMutation = (mutation: MutationRecord): boolean => {\r\n if (\r\n mutation.type !== \"attributes\" ||\r\n mutation.attributeName !== \"class\" ||\r\n !(mutation.target instanceof Element)\r\n ) {\r\n return false;\r\n }\r\n\r\n if (\r\n isSvg(mutation.target) &&\r\n mutation.oldValue?.trim() === mutation.target.classList.value?.trim()\r\n ) {\r\n return true;\r\n }\r\n\r\n const previousTokens = normalizeClassTokens(mutation.oldValue);\r\n const currentTokens = normalizeClassTokens(\r\n mutation.target.getAttribute(\"class\")\r\n );\r\n\r\n return previousTokens.join(\" \") === currentTokens.join(\" \");\r\n};\r\n\r\nexport const createObserver = (addedNodeCallBack: Function) => {\r\n mutationObserver = new MutationObserver((mutations) => {\r\n mutations.forEach((mutation) => {\r\n const shouldInvalidateXPathCache =\r\n mutation.type === \"childList\" ||\r\n mutation.type === \"characterData\" ||\r\n (mutation.type === \"attributes\" &&\r\n mutation.attributeName !== \"flndisabled\" &&\r\n !isInternalClassOnlyMutation(mutation));\r\n\r\n if (shouldInvalidateXPathCache) {\r\n clearXPathEvalCache(mutation.target);\r\n }\r\n\r\n if (mutation?.addedNodes?.length) {\r\n addedNodeCallBack(mutation?.addedNodes);\r\n }\r\n\r\n if (mutation.target instanceof HTMLElement) {\r\n if (isInternalClassOnlyMutation(mutation)) {\r\n } else if (\r\n mutation?.type === \"attributes\" &&\r\n ![\"flndisabled\"].includes(mutation.attributeName!)\r\n ) {\r\n modifiedElementAttributes.push({\r\n url: mutation.target.baseURI,\r\n attributeName: mutation.attributeName,\r\n element: mutation.target,\r\n doc: mutation.target.ownerDocument\r\n });\r\n }\r\n }\r\n });\r\n });\r\n};\r\nexport const startObserver = (\r\n target: Node,\r\n options: MutationObserverInit | undefined\r\n) => {\r\n mutationObserver?.observe(target, options);\r\n};\r\n\r\nexport const stopObserver = () => {\r\n mutationObserver?.disconnect();\r\n};\r\n\r\nexport const isNumberExist = (str: string): boolean => {\r\n const hasNumber = /\\d/;\r\n return hasNumber.test(str);\r\n};\r\n\r\nexport const buildPattern = (\r\n pattern: string,\r\n isSvg: boolean,\r\n tagName: string\r\n): string => {\r\n return isSvg\r\n ? `//*[local-name()='${tagName}' and ${pattern}]`\r\n : `//${tagName}[${pattern}]`;\r\n};\r\n\r\nexport const getTextContent = (\r\n targetElement: HTMLElement | Element\r\n): string => {\r\n const textContent = targetElement?.textContent;\r\n if (cspEnabled) {\r\n if (textContent) {\r\n const tooltip = document.querySelector(\".flntooltip\") as HTMLElement;\r\n if (tooltip) {\r\n const lastIndex = textContent.lastIndexOf(tooltip.innerText);\r\n if (\r\n lastIndex &&\r\n textContent.length === lastIndex + tooltip.innerText.length\r\n ) {\r\n return textContent.substring(0, lastIndex);\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n }\r\n } else {\r\n return textContent;\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nexport const getFilteredText = (element: Node): string => {\r\n return element?.childNodes[0]?.nodeValue || \"\";\r\n};\r\n\r\nexport const getCountOfXPath = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Node,\r\n multiElementReferenceMode: boolean = false\r\n): number => {\r\n try {\r\n const { first, second } = evaluateXPathOnce(xpath, docmt);\r\n\r\n if (!first) return 0;\r\n\r\n // exactly one match\r\n if (!second) {\r\n return first === element ? 1 : 0;\r\n }\r\n\r\n // multiple matches\r\n if (multiElementReferenceMode && Array.isArray(element)) {\r\n let matchCount = 0;\r\n\r\n if (element.includes(first)) matchCount++;\r\n if (element.includes(second)) matchCount++;\r\n\r\n if (matchCount === 2) return 2;\r\n const owner =\r\n docmt.nodeType === 9 ? (docmt as Document) : docmt.ownerDocument!;\r\n\r\n const result = owner.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n XPathResult.ORDERED_NODE_ITERATOR_TYPE,\r\n null\r\n );\r\n\r\n let node: Node | null;\r\n while ((node = result.iterateNext())) {\r\n if (element.includes(node)) {\r\n matchCount++;\r\n if (matchCount === 2) return 2;\r\n }\r\n }\r\n\r\n return 0;\r\n }\r\n\r\n return 2;\r\n } catch (error) {\r\n console.error(`Error evaluating XPath: ${xpath}`, error);\r\n return 0;\r\n }\r\n};\r\n\r\nexport const escapeCharacters = (text: string): string => {\r\n if (text) {\r\n if (!(text.indexOf('\"') === -1)) {\r\n return `'${text}'`;\r\n }\r\n if (!(text.indexOf(\"'\") === -1)) {\r\n return `\"${text}\"`;\r\n }\r\n }\r\n return `'${text}'`;\r\n};\r\n\r\nexport const removeParenthesis = (xpath: string): string => {\r\n const charArr = xpath.split(\"\");\r\n\r\n let count = charArr.length;\r\n const indexArray = [];\r\n\r\n while (charArr[count - 2] !== \"[\") {\r\n indexArray.push(charArr[count - 2]);\r\n count--;\r\n }\r\n\r\n indexArray.reverse();\r\n let finalStr = \"\";\r\n for (let i = 0; i < indexArray.length; i++) {\r\n finalStr += indexArray[i];\r\n }\r\n\r\n const endBracketLength = finalStr.length + 2;\r\n let firstpart = xpath.slice(0, xpath.length - endBracketLength);\r\n\r\n if (firstpart.startsWith(\"(\") && firstpart.endsWith(\")\")) {\r\n firstpart = firstpart.slice(1, -1);\r\n } else {\r\n firstpart = xpath;\r\n }\r\n\r\n return firstpart;\r\n};\r\n\r\nexport const findXpathWithIndex = (\r\n val: string,\r\n node: HTMLElement | Element,\r\n docmt: Node,\r\n count: number\r\n) => {\r\n try {\r\n const owner =\r\n docmt.nodeType === 9 // DOCUMENT_NODE\r\n ? (docmt as Document)\r\n : docmt.ownerDocument!;\r\n\r\n let index = 0;\r\n if (count) {\r\n if (getCountOfXPath(`${val}[${count}]`, node, docmt) === 1) {\r\n return `${val}[${count}]`;\r\n }\r\n\r\n if (getCountOfXPath(`(${val})[${count}]`, node, docmt) === 1) {\r\n return `(${val})[${count}]`;\r\n }\r\n }\r\n\r\n const nodes = owner.evaluate(val, docmt, null, XPathResult.ANY_TYPE, null);\r\n let nodex: Node | null = null;\r\n while ((nodex = nodes.iterateNext())) {\r\n index++;\r\n if (nodex.isSameNode(node)) {\r\n if (getCountOfXPath(`${val}[${index}]`, node, docmt) === 1) {\r\n return `${val}[${index}]`;\r\n }\r\n if (getCountOfXPath(`(${val})[${index}]`, node, docmt) === 1) {\r\n return `(${val})[${index}]`;\r\n }\r\n return;\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nconst deleteLineGap = (a: string): string => {\r\n a &&= a.split(\"\\n\")[0].length > 0 ? a.split(\"\\n\")[0] : a.split(\"\\n\")[1];\r\n return a;\r\n};\r\n\r\nconst deleteGarbageFromInnerText = (a: string): string => {\r\n a = deleteLineGap(a);\r\n a = a\r\n .split(/[^\\u0000-\\u00ff]/)\r\n .reduce((b, c) => {\r\n return b.length > c.length ? b : c;\r\n }, \"\")\r\n .trim();\r\n return (a = a.split(\"/\")[0].trim());\r\n};\r\n\r\nexport const replaceWhiteSpaces = (str: string): string => {\r\n if (str) {\r\n return str.replace(/\\s\\s+/g, \" \").trim();\r\n }\r\n\r\n return str;\r\n};\r\n\r\nexport const getShadowRoot = (el: HTMLElement | Element): Element | null => {\r\n if (!el || !el?.getRootNode) return null;\r\n\r\n const root = el.getRootNode() as ShadowRoot;\r\n return root && root?.host ? (root as unknown as Element) : null;\r\n};\r\n\r\nconst isShadowRootNode = (node: Node): node is ShadowRoot => {\r\n return node?.nodeType === Node.DOCUMENT_FRAGMENT_NODE && \"host\" in node;\r\n};\r\n\r\nconst getElementPathFromRoot = (\r\n root: ShadowRoot,\r\n element: Element\r\n): number[] | null => {\r\n const path: number[] = [];\r\n let current: Element | null = element;\r\n\r\n while (current && current.parentElement) {\r\n const parent: Element = current.parentElement as Element;\r\n path.unshift(Array.from(parent.children).indexOf(current));\r\n current = parent;\r\n }\r\n\r\n if (!current || current.parentNode !== root) {\r\n return null;\r\n }\r\n\r\n path.unshift(Array.from(root.children).indexOf(current));\r\n return path;\r\n};\r\n\r\nconst getElementAtPath = (\r\n container: ParentNode & { children: HTMLCollection },\r\n path: number[]\r\n): Element | null => {\r\n let current: (ParentNode & { children: HTMLCollection }) | Element =\r\n container;\r\n\r\n for (const index of path) {\r\n const next: Element | null = current.children.item(index) as Element | null;\r\n if (!next) {\r\n return null;\r\n }\r\n\r\n current = next;\r\n }\r\n\r\n return current as Element | null;\r\n};\r\n\r\nexport const createShadowEvaluationContext = (\r\n root: ShadowRoot,\r\n element?: HTMLElement | Element | (HTMLElement | Element)[]\r\n) => {\r\n const tempDoc =\r\n root.ownerDocument.implementation.createHTMLDocument(\"shadow-xpath\");\r\n const wrapper = tempDoc.createElement(\"div\");\r\n wrapper.innerHTML = root.innerHTML;\r\n tempDoc.body.appendChild(wrapper);\r\n\r\n const cloneForElement = (candidate?: HTMLElement | Element | null) => {\r\n if (\r\n !candidate ||\r\n !(candidate instanceof root.ownerDocument.defaultView!.Element)\r\n ) {\r\n return null;\r\n }\r\n\r\n const path = getElementPathFromRoot(root, candidate);\r\n return path ? getElementAtPath(wrapper, path) : null;\r\n };\r\n\r\n const cloneElements = Array.isArray(element)\r\n ? element.map((candidate) => cloneForElement(candidate)).filter(Boolean)\r\n : [];\r\n\r\n const cloneElement = Array.isArray(element)\r\n ? null\r\n : cloneForElement(element ?? null);\r\n\r\n return {\r\n owner: tempDoc,\r\n contextNode: wrapper,\r\n cloneElement,\r\n cloneElements\r\n };\r\n};\r\n\r\nexport const checkBlockedAttributes = (\r\n attribute: {\r\n name: string;\r\n value: string;\r\n },\r\n targetElement: HTMLElement | Element,\r\n isTarget: boolean\r\n): boolean => {\r\n const sanitizedValue = sanitizeAttributeValue(\r\n attribute.name,\r\n attribute.value\r\n );\r\n\r\n if (!sanitizedValue || typeof attribute?.value === \"boolean\") {\r\n return false;\r\n }\r\n const blockedValues = [\r\n \"true\",\r\n \"false\",\r\n \"on\",\r\n \"off\",\r\n \"flntooltip\",\r\n \"flutter-highlight-overlay\"\r\n ];\r\n if (blockedValues.some((x) => x === sanitizedValue)) {\r\n return false;\r\n }\r\n const blockedNames = [\"style\", \"locator-data-tooltip\", \"value\"];\r\n if (blockedNames.some((x) => x === attribute.name)) {\r\n return false;\r\n }\r\n\r\n const isModified = modifiedElementAttributes?.find(\r\n (x) =>\r\n x.doc === targetElement.ownerDocument &&\r\n x.element === targetElement &&\r\n x.attributeName === attribute.name\r\n );\r\n if (isModified) {\r\n return false;\r\n }\r\n\r\n if (attribute?.name?.indexOf(\"on\") === 0 && attribute?.name?.length > 3) {\r\n return false;\r\n }\r\n\r\n if (typeof attribute.value === \"function\") {\r\n return false;\r\n }\r\n\r\n if (isTarget && isNumberExist(sanitizedValue)) {\r\n return false;\r\n }\r\n\r\n return true;\r\n};\r\n\r\nexport const getRelationship = (a: HTMLElement, b: HTMLElement): string => {\r\n let pos = a.compareDocumentPosition(b);\r\n return pos === 2\r\n ? \"preceding\"\r\n : pos === 4\r\n ? \"following\"\r\n : pos === 8\r\n ? \"ancestor\"\r\n : pos === 16\r\n ? \"descendant\"\r\n : pos === 32\r\n ? \"self\"\r\n : \"\";\r\n};\r\n\r\nexport const isSvg = (element: HTMLElement | Element) => {\r\n return element instanceof SVGElement;\r\n};\r\n\r\nexport const replaceTempAttributes = (str: string): string => {\r\n if (!str) return str;\r\n\r\n return str.replace(/\\b[a-zA-Z_]*disabled\\b/gi, \"disabled\");\r\n};\r\n\r\nconst getElementFromXpath = (xpath: string, docmt: Node, multi = false) => {\r\n let contextNode: Node = docmt;\r\n\r\n // XPath does NOT support DocumentFragment / ShadowRoot\r\n if (docmt.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\r\n contextNode = (docmt as ShadowRoot).host ?? docmt;\r\n }\r\n\r\n const owner =\r\n contextNode.nodeType === Node.DOCUMENT_NODE\r\n ? (contextNode as Document)\r\n : contextNode.ownerDocument!;\r\n\r\n if (multi) {\r\n return owner.evaluate(xpath, contextNode, null, XPathResult.ANY_TYPE, null);\r\n }\r\n\r\n return owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n ).singleNodeValue;\r\n};\r\n\r\nexport const getPropertyXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n prop: string,\r\n value: string,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if (value) {\r\n const { tagName } = element;\r\n let count;\r\n let combinePattern = \"\";\r\n const mergePattern = [];\r\n let pattern;\r\n\r\n if (value && (!isTarget || !isNumberExist(value))) {\r\n if (!reWhiteSpace.test(value)) {\r\n pattern = buildPattern(\r\n `normalize-space(${prop})=${escapeCharacters(\r\n replaceWhiteSpaces(value)\r\n ).trim()}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n } else {\r\n pattern = `//${tagName}[${prop}=${escapeCharacters(value)}]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n if (value && isTarget) {\r\n const splitText = value.split(\" \");\r\n if (splitText?.length) {\r\n if (splitText.length === 1) {\r\n const contentRes = [...new Set(splitText[0].match(/([^0-9]+)/g))];\r\n if (contentRes?.length >= 1) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 1\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (contentRes?.length > 1) {\r\n if (\r\n contentRes[contentRes.length - 1] &&\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1].trim())\r\n ?.length > 1\r\n ) {\r\n if (value.endsWith(contentRes[contentRes.length - 1])) {\r\n if (!reWhiteSpace.test(contentRes[contentRes.length - 1])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[contentRes.length - 1])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[contentRes.length - 1]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n } else {\r\n const endIndex =\r\n splitText.length % 2 === 0\r\n ? splitText.length / 2\r\n : splitText.length % 2;\r\n const startIndexString = splitText.slice(0, endIndex).join(\" \");\r\n let contentRes = [...new Set(startIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length\r\n ) {\r\n if (value.startsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `starts-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n\r\n const endIndexString = splitText\r\n .slice(endIndex, splitText.length - 1)\r\n .join(\" \");\r\n contentRes = [...new Set(endIndexString.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n if (\r\n contentRes[0] &&\r\n replaceWhiteSpaces(contentRes[0].trim())?.length > 3\r\n ) {\r\n if (value.endsWith(contentRes[0])) {\r\n if (!reWhiteSpace.test(contentRes[0])) {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[0])\r\n ).trim()})`;\r\n } else {\r\n combinePattern = `ends-with(${prop},${escapeCharacters(\r\n contentRes[0]\r\n ).trim()})`;\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${combinePattern}]`;\r\n } else {\r\n pattern = `//${tagName}[${combinePattern}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (value && isTarget && isNumberExist(value)) {\r\n const contentRes = [...new Set(value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n mergePattern.push(\r\n `contains(${prop},${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (mergePattern?.length) {\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and ${mergePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tagName}[${mergePattern.join(\" and \")}]`;\r\n }\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n }\r\n\r\n if (isSvg(element)) {\r\n pattern = `//*[local-name()='${tagName}' and text()]`;\r\n } else {\r\n pattern = `//${tagName}[text()]`;\r\n }\r\n\r\n count = getCountOfXPath(pattern, element, docmt);\r\n if (count === 1 && !isIndex) {\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAbsoluteXPath = (\r\n domNode: HTMLElement | Element | null,\r\n docmt: Document\r\n): string => {\r\n try {\r\n if (!domNode) {\r\n return \"\";\r\n }\r\n\r\n let xpathe = isSvg(domNode)\r\n ? `/*[local-name()='${domNode.tagName}']`\r\n : `/${domNode.tagName}`;\r\n\r\n // // If this node has siblings of the same tagName, get the index of this node\r\n if (domNode.parentElement) {\r\n // Get the siblings\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.parentElement.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n } else if (domNode instanceof HTMLElement) {\r\n if (domNode.offsetParent) {\r\n const childNodes = Array.prototype.slice\r\n .call(domNode.offsetParent.children, 0)\r\n .filter(\r\n (childNode: HTMLElement) => childNode.tagName === domNode.tagName\r\n );\r\n\r\n // // If there's more than one sibling, append the index\r\n if (childNodes.length > 1) {\r\n const index = childNodes.indexOf(domNode);\r\n xpathe += `[${index + 1}]`;\r\n }\r\n }\r\n }\r\n\r\n // // Make a recursive call to this nodes parents and prepend it to this xpath\r\n return getAbsoluteXPath(domNode?.parentElement, docmt) + xpathe;\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(\"xpath\", error);\r\n\r\n return \"\";\r\n }\r\n};\r\n\r\nexport const getRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean = false,\r\n attributesArray: Attr[]\r\n) => {\r\n try {\r\n // Generate a cache key based on the node's identifier, index, and target flag\r\n // Check if the result for this node is already cached\r\n if (relativeXPathCache.has(domNode)) {\r\n return relativeXPathCache.get(domNode);\r\n }\r\n\r\n // Initialize an array to hold parts of the XPath\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n // Traverse up the DOM tree iteratively instead of using recursion\r\n while (currentNode) {\r\n let xpathe: string | undefined = \"\";\r\n let hasUniqueAttr = false;\r\n let attributes =\r\n domNode === currentNode\r\n ? (attributesArray ?? currentNode.attributes)\r\n : currentNode.attributes;\r\n\r\n // Loop through attributes to check for unique identifiers\r\n for (const attrName of Array.from(attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n const attrValue = sanitizeAttributeValue(\r\n attrName.name,\r\n attrName.nodeValue\r\n );\r\n\r\n const elementName = attrName.name;\r\n\r\n // Construct an XPath based on attribute\r\n xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr: number = 0;\r\n if (xpathe) {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n if (xpathe) {\r\n xpathParts.unshift(replaceTempAttributes(xpathe));\r\n hasUniqueAttr = true;\r\n break;\r\n }\r\n // return replaceTempAttributes(xpathe);\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n } else {\r\n let combinePattern: string[] = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g))\r\n ];\r\n let reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces((contentRes[i] as string).trim())\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i] as string)) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n (contentRes[i] as string).trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n let othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n return xpathe;\r\n }\r\n\r\n if (othersWithAttr > 1 && isIndex) {\r\n xpathe = findXpathWithIndex(\r\n xpathe,\r\n currentNode,\r\n docmt,\r\n othersWithAttr\r\n );\r\n return xpathe;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // If no unique attribute was found, construct XPath by tag name\r\n if (!hasUniqueAttr) {\r\n let tagBasedXPath = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Handle sibling nodes\r\n if (currentNode.parentElement) {\r\n const siblings = Array.from(\r\n currentNode.parentElement.children\r\n ).filter((childNode) => childNode.tagName === currentNode.tagName);\r\n\r\n // Append index to distinguish between siblings\r\n if (siblings.length > 1) {\r\n const index = siblings.indexOf(currentNode);\r\n tagBasedXPath += `[${index + 1}]`;\r\n }\r\n }\r\n\r\n // Add the constructed tag-based XPath to the parts array\r\n xpathParts.unshift(tagBasedXPath);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move up to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXPath = `${xpathParts.join(\"\")}`;\r\n\r\n // Cache the final XPath for this node\r\n relativeXPathCache.set(domNode, finalXPath);\r\n return finalXPath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nexport const getCombinationXpath = (\r\n attribute: Attr,\r\n domNode: HTMLElement | Element\r\n) => {\r\n const combinePattern = [];\r\n let pattern: string = \"\";\r\n\r\n if (\r\n attribute &&\r\n !isNumberExist(attribute.value) &&\r\n typeof attribute.nodeValue !== \"function\" // &&\r\n // !modifiedElementAttributes?.find(\r\n // (x) => x.element === domNode && x.attributeName === attribute.name\r\n // )\r\n ) {\r\n const contentRes = [...new Set(attribute.value.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 2\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(@${attribute.name},${escapeCharacters(\r\n contentRes[i].trim()\r\n )})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n pattern = isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`\r\n : `//${domNode.tagName}[${combinePattern.join(\" and \")}]`;\r\n return pattern;\r\n }\r\n }\r\n};\r\n\r\nexport const getAttributeCombinationXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document | ShadowRoot,\r\n uniqueAttributes: Attr[],\r\n isTarget: boolean\r\n): string | undefined => {\r\n try {\r\n const candidateAttributes = uniqueAttributes.filter((attr) =>\r\n checkBlockedAttributes(attr, domNode, isTarget)\r\n );\r\n\r\n const buildAttributeConditions = (attribute: Attr): string[] => {\r\n const attrValue = sanitizeAttributeValue(\r\n attribute.name,\r\n attribute.nodeValue\r\n );\r\n\r\n if (!attrValue) return [];\r\n\r\n if (attribute.name === \"class\") {\r\n const classTokens = attrValue\r\n .split(/\\s+/)\r\n .map((token) => token.trim())\r\n .filter(Boolean);\r\n\r\n if (!classTokens.length) return [];\r\n\r\n const rankedTokens = classTokens\r\n .map((token) => {\r\n const xpath = buildPattern(\r\n `contains(@class,${escapeCharacters(token)})`,\r\n isSvg(domNode),\r\n domNode.tagName.toLowerCase()\r\n );\r\n\r\n return {\r\n token,\r\n count: getTagOnlyXpathCandidateCount(xpath, domNode, docmt)\r\n };\r\n })\r\n .sort((left, right) => {\r\n if (left.count !== right.count) {\r\n return left.count - right.count;\r\n }\r\n\r\n return right.token.length - left.token.length;\r\n });\r\n\r\n return rankedTokens[0]?.token\r\n ? [`contains(@class,${escapeCharacters(rankedTokens[0].token)})`]\r\n : [];\r\n }\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n return [`normalize-space(@${attribute.name})=\"${attrValue}\"`];\r\n }\r\n\r\n return [`@${attribute.name}=\"${attrValue}\"`];\r\n };\r\n\r\n const getTextConditions = (): string[] => {\r\n const rawText = replaceWhiteSpaces(getTextContent(domNode)?.trim() || \"\");\r\n\r\n if (!rawText || rawText.length > 80 || /^\\d+$/.test(rawText)) {\r\n return [];\r\n }\r\n\r\n const conditions = new Set<string>();\r\n\r\n if (reWhiteSpace.test(rawText) && rawText.length <= 40) {\r\n conditions.add(`text()=${escapeCharacters(rawText)}`);\r\n }\r\n\r\n if (rawText.includes(\" \")) {\r\n conditions.add(\r\n `normalize-space(text())=${escapeCharacters(replaceWhiteSpaces(rawText))}`\r\n );\r\n }\r\n\r\n conditions.add(`contains(text(),${escapeCharacters(rawText)})`);\r\n\r\n return Array.from(conditions);\r\n };\r\n\r\n const generateAttributeCombinations = (\r\n attributes: Attr[],\r\n combinationSize: number\r\n ): Attr[][] => {\r\n const results: Attr[][] = [];\r\n\r\n const build = (startIndex: number, currentGroup: Attr[]) => {\r\n if (currentGroup.length === combinationSize) {\r\n results.push([...currentGroup]);\r\n return;\r\n }\r\n\r\n for (let i = startIndex; i < attributes.length; i++) {\r\n currentGroup.push(attributes[i]);\r\n build(i + 1, currentGroup);\r\n currentGroup.pop();\r\n }\r\n };\r\n\r\n build(0, []);\r\n return results;\r\n };\r\n\r\n const buildXPath = (conditions: string[]) =>\r\n isSvg(domNode)\r\n ? `//*[local-name()='${domNode.tagName}' and ${conditions.join(\" and \")}]`\r\n : `//${domNode.tagName}[${conditions.join(\" and \")}]`;\r\n\r\n const tryAttributeOnlyCombinations = () => {\r\n if (candidateAttributes.length < 2) {\r\n return undefined;\r\n }\r\n\r\n for (\r\n let combinationSize = 2;\r\n combinationSize <= candidateAttributes.length;\r\n combinationSize++\r\n ) {\r\n const attributeGroups = generateAttributeCombinations(\r\n candidateAttributes,\r\n combinationSize\r\n );\r\n\r\n for (const attributeGroup of attributeGroups) {\r\n let xpathConditions: string[] = [];\r\n\r\n for (const attribute of attributeGroup) {\r\n const attributeConditions = buildAttributeConditions(attribute);\r\n\r\n if (!attributeConditions.length) continue;\r\n\r\n xpathConditions.push(...attributeConditions);\r\n }\r\n\r\n if (xpathConditions.length < 2) continue;\r\n\r\n const xpath = buildXPath(xpathConditions);\r\n\r\n let matchCount: number;\r\n\r\n try {\r\n matchCount = getCountOfXPath(xpath, domNode, docmt);\r\n } catch {\r\n continue;\r\n }\r\n\r\n if (matchCount === 1) {\r\n return xpath;\r\n }\r\n }\r\n }\r\n\r\n return undefined;\r\n };\r\n\r\n const attributeOnlyXpath = tryAttributeOnlyCombinations();\r\n if (attributeOnlyXpath) {\r\n return attributeOnlyXpath;\r\n }\r\n\r\n const textConditions = getTextConditions();\r\n if (!textConditions.length || !candidateAttributes.length) {\r\n return;\r\n }\r\n\r\n for (\r\n let combinationSize = 1;\r\n combinationSize <= candidateAttributes.length;\r\n combinationSize++\r\n ) {\r\n const attributeGroups = generateAttributeCombinations(\r\n candidateAttributes,\r\n combinationSize\r\n );\r\n\r\n for (const attributeGroup of attributeGroups) {\r\n let attributeConditions: string[] = [];\r\n\r\n for (const attribute of attributeGroup) {\r\n attributeConditions.push(...buildAttributeConditions(attribute));\r\n }\r\n\r\n if (!attributeConditions.length) {\r\n continue;\r\n }\r\n\r\n for (const textCondition of textConditions) {\r\n const xpathConditions = [...attributeConditions, textCondition];\r\n const xpath = buildXPath(xpathConditions);\r\n\r\n try {\r\n if (getCountOfXPath(xpath, domNode, docmt) === 1) {\r\n return xpath;\r\n }\r\n } catch {\r\n continue;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(`XPath generation error: ${JSON.stringify(error, null, 2)}`);\r\n }\r\n};\r\n\r\nexport const intermediateXpathStep = (\r\n targetElemt: HTMLElement | Element,\r\n attr: { name: string; value: string },\r\n isTarget: boolean\r\n): string => {\r\n let isSvgElement = isSvg(targetElemt);\r\n let expression: string = \"\";\r\n\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n let attrValue = sanitizeAttributeValue(attr.name, attr.value);\r\n const elementName = attr.name;\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n expression = isSvgElement\r\n ? `*[local-name()='${\r\n targetElemt.tagName\r\n }' and normalize-space(@${elementName})=${escapeCharacters(\r\n attrValue\r\n )}]`\r\n : `${\r\n targetElemt.tagName || \"*\"\r\n }[normalize-space(@${elementName})=${escapeCharacters(attrValue)}]`;\r\n } else {\r\n expression = isSvgElement\r\n ? `*[local-name()='${\r\n targetElemt.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${targetElemt.tagName || \"*\"}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return expression;\r\n};\r\n\r\nexport const getFilteredTextXPath = (\r\n node: HTMLElement | Element,\r\n docmt: Document | ShadowRoot\r\n): string => {\r\n if (!node.textContent) return \"\";\r\n\r\n const filteredText = getFilteredText(node);\r\n\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(filteredText)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and normalize-space(.)=${escapeCharacters(filteredText)}]`\r\n : `//${node.tagName || \"*\"}[normalize-space(.)=${escapeCharacters(\r\n filteredText\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${node.tagName}' and .=${escapeCharacters(\r\n filteredText\r\n )}]`\r\n : `//${node.tagName || \"*\"}[.=${escapeCharacters(filteredText)}]`;\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const getNormalizedPropertyXPath = (\r\n element: HTMLElement | Element,\r\n prop: string,\r\n value: string\r\n): string => {\r\n return buildPattern(\r\n `normalize-space(${prop})=${escapeCharacters(replaceWhiteSpaces(value)).trim()}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n};\r\n\r\nexport const getStartsWithPropertyXPath = (\r\n element: HTMLElement | Element,\r\n prop: string,\r\n value: string\r\n): string => {\r\n return buildPattern(\r\n `starts-with(${prop},${escapeCharacters(replaceWhiteSpaces(value)).trim()})`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n};\r\n\r\nexport const getContainsPropertyXPath = (\r\n element: HTMLElement | Element,\r\n prop: string,\r\n value: string\r\n): string => {\r\n return buildPattern(\r\n `contains(${prop},${escapeCharacters(replaceWhiteSpaces(value)).trim()})`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n};\r\n\r\nexport const getOrAttributesXPath = (\r\n element: HTMLElement | Element,\r\n attributes: Attr[]\r\n): string => {\r\n const buildAttributeCondition = (attribute: Attr): string | null => {\r\n const attrValue = sanitizeAttributeValue(attribute.name, attribute.value);\r\n\r\n if (!attrValue) {\r\n return null;\r\n }\r\n\r\n if (attribute.name === \"class\") {\r\n const classTokens = attrValue\r\n .split(/\\s+/)\r\n .map((token) => token.trim())\r\n .filter(Boolean);\r\n\r\n const docmt =\r\n (element.getRootNode?.() as Document | ShadowRoot | null) ??\r\n element.ownerDocument;\r\n\r\n const rankedToken = classTokens\r\n .map((token) => {\r\n const xpath = buildPattern(\r\n `contains(@class,${escapeCharacters(token)})`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n\r\n return {\r\n token,\r\n count: getTagOnlyXpathCandidateCount(xpath, element, docmt)\r\n };\r\n })\r\n .sort((left, right) => {\r\n if (left.count !== right.count) {\r\n return left.count - right.count;\r\n }\r\n\r\n return right.token.length - left.token.length;\r\n })[0]?.token;\r\n\r\n return rankedToken\r\n ? `contains(@class,${escapeCharacters(rankedToken)})`\r\n : null;\r\n }\r\n\r\n if (!reWhiteSpace.test(attrValue)) {\r\n return `normalize-space(@${attribute.name})=${escapeCharacters(attrValue)}`;\r\n }\r\n\r\n return `@${attribute.name}=${escapeCharacters(attrValue)}`;\r\n };\r\n\r\n const buildTextCondition = (): string | null => {\r\n const rawText = replaceWhiteSpaces(getTextContent(element)?.trim() || \"\");\r\n\r\n if (!rawText || rawText.length > 80 || /^\\d+$/.test(rawText)) {\r\n return null;\r\n }\r\n\r\n if (reWhiteSpace.test(rawText) && rawText.length <= 40) {\r\n return `text()=${escapeCharacters(rawText)}`;\r\n }\r\n\r\n if (rawText.includes(\" \")) {\r\n return `normalize-space(text())=${escapeCharacters(rawText)}`;\r\n }\r\n\r\n return `contains(text(),${escapeCharacters(rawText)})`;\r\n };\r\n\r\n const attributeConditions = attributes\r\n .map((attribute) => buildAttributeCondition(attribute))\r\n .filter(Boolean) as string[];\r\n\r\n if (attributeConditions.length >= 2) {\r\n return buildPattern(\r\n `${attributeConditions[0]} or ${attributeConditions[1]}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n }\r\n\r\n const textCondition = buildTextCondition();\r\n if (attributeConditions.length === 1 && textCondition) {\r\n return buildPattern(\r\n `${attributeConditions[0]} or ${textCondition}`,\r\n isSvg(element),\r\n element.tagName.toLowerCase()\r\n );\r\n }\r\n\r\n return \"\";\r\n};\r\n\r\nconst getTagOnlyXpathCandidateCount = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Document | ShadowRoot\r\n) => {\r\n try {\r\n return getCountOfXPath(xpath, element, docmt);\r\n } catch (_error) {\r\n return 0;\r\n }\r\n};\r\n\r\nconst getAncestorAnchorCandidates = (\r\n node: HTMLElement | Element,\r\n docmt: Document | ShadowRoot\r\n): string[] => {\r\n const anchors: string[] = [];\r\n const seen = new Set<string>();\r\n const attributes = Array.from(node.attributes || []);\r\n const priorityAttrs = [\r\n \"id\",\r\n \"data-testid\",\r\n \"data-test\",\r\n \"data-qa\",\r\n \"name\",\r\n \"aria-label\",\r\n \"role\"\r\n ];\r\n const orderedAttributes = [\r\n ...priorityAttrs\r\n .map((attrName) => attributes.find((attr) => attr.name === attrName))\r\n .filter(Boolean),\r\n ...attributes.filter((attr) => !priorityAttrs.includes(attr.name))\r\n ] as Attr[];\r\n\r\n const pushAnchor = (xpath: string) => {\r\n if (!xpath || seen.has(xpath)) return;\r\n if (isExactUniqueXpath(xpath, node, docmt)) {\r\n seen.add(xpath);\r\n anchors.push(xpath);\r\n }\r\n };\r\n\r\n orderedAttributes.forEach((attr) => {\r\n if (!checkBlockedAttributes(attr, node, false)) return;\r\n\r\n const xpath =\r\n attr.name === \"id\"\r\n ? `//*[@id=${escapeCharacters(sanitizeAttributeValue(attr.name, attr.value))}]`\r\n : getXpathString(node, attr.name, attr.value);\r\n\r\n if (xpath) {\r\n pushAnchor(xpath);\r\n }\r\n });\r\n\r\n const text = node.textContent?.trim();\r\n if (text && text.length < 40 && node.children.length === 0) {\r\n const textXpath = getFilteredTextXPath(node, docmt);\r\n if (textXpath) {\r\n pushAnchor(textXpath);\r\n }\r\n }\r\n\r\n if (attributes.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n node,\r\n docmt,\r\n attributes,\r\n false\r\n );\r\n if (combinationXpath) {\r\n pushAnchor(combinationXpath);\r\n }\r\n }\r\n\r\n return anchors;\r\n};\r\n\r\nconst getStructuralPathFromAncestor = (\r\n ancestor: HTMLElement | Element,\r\n element: HTMLElement | Element\r\n): string => {\r\n const steps: string[] = [];\r\n let current: Element | null = element;\r\n\r\n while (current && current !== ancestor) {\r\n steps.unshift(getAxisNodeTest(current));\r\n current = current.parentElement;\r\n }\r\n\r\n return current === ancestor ? steps.join(\"/\") : \"\";\r\n};\r\n\r\nexport const getTagOnlyXPath = (\r\n element: HTMLElement | Element,\r\n docmt?: Document | ShadowRoot\r\n): string => {\r\n const root =\r\n docmt ??\r\n ((element.getRootNode?.() as Document | ShadowRoot) ||\r\n element.ownerDocument);\r\n const tagName = getAxisNodeTest(element);\r\n const fallbackXpath = isSvg(element)\r\n ? `//*[local-name()='${element.tagName.toLowerCase()}']`\r\n : `//${element.tagName.toLowerCase()}`;\r\n\r\n for (\r\n let ancestor = element.parentElement;\r\n ancestor;\r\n ancestor = ancestor.parentElement\r\n ) {\r\n const ancestorAnchors = getAncestorAnchorCandidates(ancestor, root);\r\n\r\n for (const ancestorXpath of ancestorAnchors) {\r\n console.log(`Trying ancestor XPath: ${ancestorXpath}`);\r\n\r\n const descendantXpath = `${ancestorXpath}/descendant::${tagName}`;\r\n console.log(`Trying descendant XPath: ${descendantXpath}`);\r\n\r\n const count = getTagOnlyXpathCandidateCount(\r\n descendantXpath,\r\n element,\r\n root\r\n );\r\n console.log(`Match count: ${count}`);\r\n\r\n if (\r\n count === 1 &&\r\n getFirstMatchedNode(descendantXpath, root) === element\r\n ) {\r\n console.log(`Selected XPath: ${descendantXpath}`);\r\n return descendantXpath;\r\n }\r\n\r\n const structuralPath = getStructuralPathFromAncestor(ancestor, element);\r\n if (structuralPath) {\r\n const parentChainXpath = `${ancestorXpath}/${structuralPath}`;\r\n console.log(`Trying descendant XPath: ${parentChainXpath}`);\r\n\r\n const parentChainCount = getTagOnlyXpathCandidateCount(\r\n parentChainXpath,\r\n element,\r\n root\r\n );\r\n console.log(`Match count: ${parentChainCount}`);\r\n\r\n if (\r\n parentChainCount === 1 &&\r\n getFirstMatchedNode(parentChainXpath, root) === element\r\n ) {\r\n console.log(`Selected XPath: ${parentChainXpath}`);\r\n return parentChainXpath;\r\n }\r\n }\r\n }\r\n }\r\n\r\n console.log(`Trying descendant XPath: ${fallbackXpath}`);\r\n const fallbackCount = getTagOnlyXpathCandidateCount(\r\n fallbackXpath,\r\n element,\r\n root\r\n );\r\n console.log(`Match count: ${fallbackCount}`);\r\n\r\n if (\r\n fallbackCount === 1 &&\r\n getFirstMatchedNode(fallbackXpath, root) === element\r\n ) {\r\n console.log(`Selected XPath: ${fallbackXpath}`);\r\n return fallbackXpath;\r\n }\r\n\r\n console.log(\"Selected XPath: \");\r\n return \"\";\r\n};\r\n\r\nexport const getFirstMatchedNode = (\r\n xpath: string,\r\n docmt: Document | ShadowRoot\r\n): HTMLElement | Element | null => {\r\n try {\r\n if (isShadowRootNode(docmt)) {\r\n const { owner, contextNode, cloneElement } =\r\n createShadowEvaluationContext(docmt);\r\n const result = owner.evaluate(\r\n xpath,\r\n contextNode,\r\n null,\r\n XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n return (result.singleNodeValue || cloneElement) as\r\n | HTMLElement\r\n | Element\r\n | null;\r\n }\r\n\r\n const result = docmt.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n docmt.defaultView!.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n return result.singleNodeValue as HTMLElement | Element | null;\r\n } catch (_error) {\r\n return null;\r\n }\r\n};\r\n\r\nexport const isExactUniqueXpath = (\r\n xpath: string,\r\n element: HTMLElement | Element,\r\n docmt: Document | ShadowRoot\r\n): boolean => {\r\n try {\r\n const { first, second } = evaluateXPathOnce(xpath, docmt);\r\n\r\n return !!first && !second && first === element;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const getAxisNodeTest = (element: HTMLElement | Element): string => {\r\n return isSvg(element)\r\n ? `*[local-name()='${element.tagName.toLowerCase()}']`\r\n : element.tagName.toLowerCase();\r\n};\r\n\r\nconst hasAnyNumber = (value: string) => /\\d/.test(value);\r\n\r\nexport const getUniqueNodeAnchorXpaths = (\r\n node: HTMLElement | Element,\r\n docmt: Document | ShadowRoot,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n if (!(node instanceof Element)) return [];\r\n const seen = new Set<string>();\r\n const anchors: { key: string; value: string }[] = [];\r\n\r\n const attributes = Array.from(node.attributes || []).filter(\r\n (attribute) =>\r\n attribute?.value &&\r\n !hasAnyNumber(attribute.value) &&\r\n checkBlockedAttributes(attribute, node, isTarget)\r\n );\r\n\r\n const pushAnchor = (key: string, value: string) => {\r\n if (!value || seen.has(value)) return;\r\n seen.add(value);\r\n anchors.push({ key, value });\r\n };\r\n\r\n // Priority attributes\r\n const priorityAttrs = [\r\n \"id\",\r\n \"data-testid\",\r\n \"data-test\",\r\n \"data-qa\",\r\n \"name\",\r\n \"aria-label\",\r\n \"role\"\r\n ];\r\n\r\n priorityAttrs.forEach((attrName) => {\r\n const attr = attributes.find((a) => a.name === attrName);\r\n if (!attr) return;\r\n\r\n const xpath =\r\n attrName === \"id\"\r\n ? `//*[@id='${attr.value}']`\r\n : getXpathString(node, attr.name, attr.value);\r\n\r\n if (xpath && isExactUniqueXpath(xpath, node, docmt)) {\r\n pushAnchor(`anchor by ${attr.name}`, xpath);\r\n }\r\n });\r\n\r\n // Other attributes\r\n attributes.forEach((attribute) => {\r\n if (priorityAttrs.includes(attribute.name)) return;\r\n\r\n const xpath = getXpathString(node, attribute.name, attribute.value);\r\n if (xpath && isExactUniqueXpath(xpath, node, docmt)) {\r\n pushAnchor(`anchor by ${attribute.name}`, xpath);\r\n }\r\n });\r\n\r\n // Text (controlled)\r\n const text = node.textContent?.trim();\r\n if (text && text.length < 40 && node.children.length === 0) {\r\n const textXpath = getFilteredTextXPath(node, docmt);\r\n if (textXpath && isExactUniqueXpath(textXpath, node, docmt)) {\r\n pushAnchor(\"anchor by text\", textXpath);\r\n }\r\n }\r\n\r\n // Combination\r\n if (attributes.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n node,\r\n docmt,\r\n attributes,\r\n isTarget\r\n );\r\n\r\n if (combinationXpath && isExactUniqueXpath(combinationXpath, node, docmt)) {\r\n pushAnchor(\"anchor by combination\", combinationXpath);\r\n }\r\n }\r\n\r\n // Tag (last fallback)\r\n const tagXpath = getTagOnlyXPath(node, docmt);\r\n if (tagXpath && isExactUniqueXpath(tagXpath, node, docmt)) {\r\n pushAnchor(\"anchor by tag\", tagXpath);\r\n }\r\n\r\n return anchors;\r\n};\r\n\r\nexport const getTextXpathFunction = (\r\n domNode: HTMLElement | Element\r\n): string | undefined => {\r\n const trimmedText = getTextContent(domNode)?.trim();\r\n const filteredText = trimmedText\r\n ? escapeCharacters(deleteGarbageFromInnerText(trimmedText))\r\n : trimmedText;\r\n if (filteredText) {\r\n if (filteredText !== `'${trimmedText}'`) {\r\n return `contains(.,${filteredText})`;\r\n }\r\n return `normalize-space(.)='${trimmedText}'`;\r\n }\r\n};\r\n\r\nexport const getXpathString = (\r\n node: HTMLElement | Element,\r\n attrName: string,\r\n attrValue: string\r\n): string => {\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n let xpathe: string = \"\";\r\n attrValue = sanitizeAttributeValue(attrName, attrValue);\r\n\r\n if (attrValue) {\r\n if (!reWhiteSpace.test(attrValue)) {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else if (attrName === \"class\") {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and contains(@${attrName},${escapeCharacters(attrValue)})]`\r\n : `//${node.tagName || \"*\"}[contains(@${attrName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n xpathe = isSvg(node)\r\n ? `//*[local-name()='${\r\n node.tagName\r\n }' and @${attrName}=${escapeCharacters(attrValue)}]`\r\n : `//${node.tagName || \"*\"}[@${attrName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n }\r\n\r\n return xpathe;\r\n};\r\n\r\nexport const replaceActualAttributes = (\r\n str: string,\r\n element: { attributes: any }\r\n): string => {\r\n if (str) {\r\n return str.replace(/\\bdisabled\\b/gi, \"flndisabled\");\r\n }\r\n return str;\r\n};\r\n\r\nconst addAttributeSplitCombineXpaths = (\r\n attributes: NamedNodeMap,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n const attributesArray = Array.prototype.slice.call(attributes);\r\n const xpaths: { key: string; value: string }[] = [];\r\n try {\r\n attributesArray.map((element) => {\r\n if (checkBlockedAttributes(element, targetElemt, isTarget)) {\r\n const xpth = getCombinationXpath(element, targetElemt);\r\n if (xpth) {\r\n xpaths.push({\r\n key: `split xpath by ${element.name}`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n });\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return xpaths;\r\n};\r\n\r\nexport const getReferenceElementsXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n): { key: string; value: string }[] => {\r\n let nodeXpath1;\r\n const xpaths1 = [];\r\n if (\r\n domNode.textContent &&\r\n (!isTarget || (isTarget && !isNumberExist(domNode.textContent)))\r\n ) {\r\n if (!reWhiteSpace.test(domNode.textContent)) {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and ${getTextXpathFunction(\r\n domNode\r\n )})]`\r\n : `${domNode.tagName}[${getTextXpathFunction(domNode)}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${domNode.tagName}' and .=${escapeCharacters(\r\n getTextContent(domNode)\r\n )}]`\r\n : `${domNode.tagName}[.=${escapeCharacters(getTextContent(domNode))}]`;\r\n if (nodeXpath1) {\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: nodeXpath1 });\r\n }\r\n }\r\n }\r\n\r\n if (domNode.attributes) {\r\n for (const attrName of Array.from(domNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, domNode, isTarget)) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = sanitizeAttributeValue(attrName.name, attrValue);\r\n const elementName = attrName.name;\r\n\r\n if (elementName === \"class\") {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${\r\n domNode.tagName\r\n }' and contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`\r\n : `${domNode.tagName}[contains(@${elementName},${escapeCharacters(\r\n attrValue\r\n )})]`;\r\n } else {\r\n nodeXpath1 = isSvg(domNode)\r\n ? `*[local-name()='${\r\n domNode.tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${domNode.tagName}[@${elementName}=${escapeCharacters(\r\n attrValue\r\n )}]`;\r\n }\r\n\r\n if (nodeXpath1) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: nodeXpath1\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const attributesArray = Array.prototype.slice.call(domNode.attributes);\r\n if (attributesArray?.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n domNode,\r\n docmt,\r\n Array.prototype.slice.call(domNode.attributes),\r\n isTarget\r\n );\r\n if (combinationXpath) {\r\n xpaths1.push({\r\n key: \"getReferenceElementsXpath\",\r\n value: combinationXpath\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const combinePattern = [];\r\n let pattern;\r\n const tag = isSvg(domNode);\r\n if (domNode.textContent && isTarget && isNumberExist(domNode.textContent)) {\r\n const contentRes = [...new Set(domNode.textContent.match(/([^0-9]+)/g))];\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (\r\n contentRes[i] &&\r\n replaceWhiteSpaces(contentRes[i].trim())?.length > 1\r\n ) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(contentRes[i]).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n if (tag) {\r\n pattern = `//*[local-name()='${tag}' and ${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n } else {\r\n pattern = `//${tag}[${combinePattern.join(\" and \")}]`;\r\n }\r\n\r\n if (pattern)\r\n xpaths1.push({ key: \"getReferenceElementsXpath\", value: pattern });\r\n }\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n const xpaths = addAttributeSplitCombineXpaths(\r\n domNode.attributes,\r\n domNode,\r\n docmt,\r\n isTarget\r\n );\r\n if (xpaths?.length) {\r\n xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n return xpaths1;\r\n};\r\n\r\nexport const parseXml = (\r\n xmlStr: string,\r\n type: DOMParserSupportedType\r\n): Document | null => {\r\n if (window.DOMParser) {\r\n return new window.DOMParser().parseFromString(xmlStr, type);\r\n }\r\n\r\n return null;\r\n};\r\n\r\nexport const normalizeXPath = (xpath: string): string => {\r\n // Replace text() = \"value\" or text()='value'\r\n xpath = xpath.replace(\r\n /text\\(\\)\\s*=\\s*(['\"])(.*?)\\1/g,\r\n \"normalize-space(.)=$1$2$1\"\r\n );\r\n\r\n // Replace . = \"value\" or .='value'\r\n xpath = xpath.replace(/\\.\\s*=\\s*(['\"])(.*?)\\1/g, \"normalize-space(.)=$1$2$1\");\r\n\r\n return xpath;\r\n};\r\n\r\nexport const findMatchingParenthesis = (\r\n text: string,\r\n openPos: number\r\n): number => {\r\n let closePos = openPos;\r\n let counter = 1;\r\n while (counter > 0) {\r\n const c = text[++closePos];\r\n if (c == \"(\") {\r\n counter++;\r\n } else if (c == \")\") {\r\n counter--;\r\n }\r\n }\r\n return closePos;\r\n};\r\n\r\nexport function canonicalizeXPath(xpath: string): string {\r\n return (\r\n xpath\r\n .toLowerCase()\r\n // replace quoted values\r\n .replace(/'[^']*'/g, \"?\")\r\n .replace(/\"[^\"]*\"/g, \"?\")\r\n // replace numbers in predicates\r\n .replace(/\\[\\d+\\]/g, \"[?]\")\r\n // normalize node names\r\n .replace(/\\/\\/[a-z0-9_-]+/g, \"//node\")\r\n .replace(/\\/[a-z0-9_-]+/g, \"/node\")\r\n );\r\n}\r\n\r\nexport function extractXPathSignatureParts(xpath: string) {\r\n const xp = xpath.toLowerCase();\r\n\r\n const axisMatch = xp.match(\r\n /(ancestor-or-self|ancestor|descendant-or-self|descendant|following-sibling|preceding-sibling|following|preceding|parent|child|self)::/\r\n );\r\n const axis = axisMatch?.[1] ?? \"none\";\r\n\r\n const attrMatch = xp.match(/@([a-z0-9:-]+)/);\r\n const attribute = attrMatch?.[1] ?? \"none\";\r\n\r\n const usesNormalize = xp.includes(\"normalize-space\");\r\n\r\n return { axis, attribute, usesNormalize };\r\n}\r\n\r\nexport function getXPathPattern(xpath: string): string {\r\n const canonical = canonicalizeXPath(xpath);\r\n const parts = extractXPathSignatureParts(xpath);\r\n\r\n return [\r\n \"XPATH\",\r\n `axis:${parts.axis}`,\r\n `attr:${parts.attribute}`,\r\n `normalize:${parts.usesNormalize}`,\r\n `shape:${canonical}`\r\n ].join(\"|\");\r\n}\r\n\r\nexport function escapeAttrValue(value: string): string {\r\n return value.replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"').replace(/ /g, \"\\\\ \");\r\n}\r\n\r\nexport function shouldUseSnapshot(xpath: string): boolean {\r\n return /\\[(?:\\s*\\.|\\s*contains\\s*\\(\\s*\\.|\\s*normalize-space\\s*\\(\\s*\\.)/.test(\r\n xpath\r\n );\r\n}\r\n\r\nexport function isUniqueInDOM(\r\n docmt: Document,\r\n name: string,\r\n value: string,\r\n element?: Element | null\r\n): boolean {\r\n const root = (element?.getRootNode?.() as ParentNode | null) ?? docmt;\r\n const queryAll = (selector: string): Element[] => {\r\n try {\r\n return Array.from(root.querySelectorAll(selector));\r\n } catch {\r\n return [];\r\n }\r\n };\r\n\r\n try {\r\n switch (name) {\r\n case \"id\":\r\n return queryAll(`#${escapeAttrValue(value)}`).length === 1;\r\n\r\n case \"name\":\r\n return queryAll(`[name=\"${escapeAttrValue(value)}\"]`).length === 1;\r\n\r\n case \"className\":\r\n return queryAll(`.${value}`).length === 1;\r\n\r\n case \"tagName\":\r\n return queryAll(value).length === 1;\r\n\r\n case \"linkText\":\r\n return (\r\n queryAll(\"a\").filter((a) => a.textContent?.trim() === value)\r\n .length === 1\r\n );\r\n case \"partialLinkText\":\r\n return (\r\n queryAll(\"a\").filter((a) => a.textContent?.includes(value)).length ===\r\n 1\r\n );\r\n case \"cssSelector\":\r\n return queryAll(value).length === 1;\r\n default:\r\n return false;\r\n }\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\nexport const xpathUtils = {\r\n parseXml,\r\n getReferenceElementsXpath,\r\n getAbsoluteXPath,\r\n getRelativeXPath,\r\n getCombinationXpath,\r\n getAttributeCombinationXpath,\r\n getElementFromXpath,\r\n isSvg,\r\n findXpathWithIndex,\r\n isNumberExist,\r\n getTextContent,\r\n getCountOfXPath,\r\n normalizeXPath,\r\n getShadowRoot,\r\n escapeCharacters,\r\n removeParenthesis,\r\n checkBlockedAttributes,\r\n getRelationship,\r\n findMatchingParenthesis,\r\n deleteGarbageFromInnerText,\r\n replaceTempAttributes,\r\n createObserver,\r\n startObserver,\r\n stopObserver,\r\n modifiedElementAttributes,\r\n cspEnabled,\r\n getXPathPattern,\r\n getNormalizedPropertyXPath,\r\n getStartsWithPropertyXPath,\r\n getContainsPropertyXPath,\r\n getOrAttributesXPath,\r\n getTagOnlyXPath,\r\n getFirstMatchedNode,\r\n isExactUniqueXpath,\r\n getAxisNodeTest,\r\n getUniqueNodeAnchorXpaths,\r\n escapeAttrValue,\r\n isUniqueInDOM,\r\n sanitizeAttributeValue\r\n};\r\n","import {\r\n isNumberExist,\r\n getCountOfXPath,\r\n escapeCharacters,\r\n checkBlockedAttributes,\r\n replaceWhiteSpaces,\r\n getTextContent,\r\n getPropertyXPath,\r\n findXpathWithIndex,\r\n getFilteredText,\r\n intermediateXpathStep,\r\n getAttributeCombinationXpath,\r\n getFilteredTextXPath,\r\n getNormalizedPropertyXPath,\r\n getStartsWithPropertyXPath,\r\n getContainsPropertyXPath,\r\n getOrAttributesXPath,\r\n getTagOnlyXPath,\r\n isExactUniqueXpath,\r\n getAxisNodeTest,\r\n getUniqueNodeAnchorXpaths,\r\n isSvg,\r\n getXpathString,\r\n reWhiteSpace,\r\n sanitizeAttributeValue\r\n // timeLog\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathData: { key: string; value: string }[] = [];\r\nlet xpathDataWithIndex: { key: string; value: string; count: number }[] = [];\r\nlet referenceElementMode: boolean = false;\r\nlet xpathCache = new Map();\r\nlet cache = new Map();\r\n\r\nconst parentXpathCache = new Map(); // Cache for parent XPaths\r\n\r\nconst STRATEGY_MAP = {\r\n andConditions: \"and\",\r\n orConditions: \"or\",\r\n contains: \"contains\",\r\n startsWith: \"startsWith\",\r\n normalizeSpace: \"normalizeSpace\",\r\n axes: \"axes\",\r\n index: \"index\",\r\n hardCodedText: \"text\",\r\n tillTag: \"tag\"\r\n} as const;\r\n\r\nconst getStrategyName = (strategy: string) => {\r\n return STRATEGY_MAP[strategy as keyof typeof STRATEGY_MAP] || strategy;\r\n};\r\n\r\nconst withStrategyKey = (\r\n strategy: string,\r\n entries: { key: string; value: string }[]\r\n) => {\r\n return entries.map((entry) => ({\r\n ...entry,\r\n key: entry?.key?.includes(strategy)\r\n ? entry.key\r\n : `${strategy} ${entry.key}`.trim()\r\n }));\r\n};\r\n\r\nconst getUniqueXpathEntries = (entries: { key: string; value: string }[]) => {\r\n const seen = new Set<string>();\r\n\r\n return entries.filter((entry) => {\r\n if (!entry?.value || seen.has(entry.value)) {\r\n return false;\r\n }\r\n\r\n seen.add(entry.value);\r\n return true;\r\n });\r\n};\r\n\r\nconst getNormalizedText = (element: HTMLElement | Element) => {\r\n return element?.textContent?.replace(/\\s+/g, \" \")?.trim() || \"\";\r\n};\r\n\r\nconst buildTextStrategyXpaths = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n strategy: string\r\n) => {\r\n const text = getNormalizedText(element);\r\n\r\n if (!text) {\r\n return [];\r\n }\r\n\r\n if (strategy === \"text\") {\r\n const textXpath =\r\n getFilteredTextXPath(element, docmt) ||\r\n getTextXPath(element, docmt, false, false);\r\n\r\n return textXpath ? [{ key: \"xpath by text\", value: textXpath }] : [];\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst buildPropertyStrategyXpaths = (\r\n element: HTMLElement | Element,\r\n isTarget: boolean,\r\n strategy: string\r\n) => {\r\n const xpaths: { key: string; value: string }[] = [];\r\n const attributes = Array.from(element.attributes || []).filter(\r\n (attribute) =>\r\n attribute?.value && checkBlockedAttributes(attribute, element, isTarget)\r\n );\r\n const text = getNormalizedText(element);\r\n const getStrategyXPath =\r\n strategy === \"contains\"\r\n ? getContainsPropertyXPath\r\n : strategy === \"startsWith\"\r\n ? getStartsWithPropertyXPath\r\n : strategy === \"normalizeSpace\"\r\n ? getNormalizedPropertyXPath\r\n : null;\r\n\r\n if (!getStrategyXPath) {\r\n return xpaths;\r\n }\r\n\r\n attributes.forEach((attribute) => {\r\n const xpath = getStrategyXPath(\r\n element,\r\n `@${attribute.name}`,\r\n attribute.value\r\n );\r\n\r\n if (xpath) {\r\n xpaths.push({\r\n key: `xpath by ${strategy} ${attribute.name}`,\r\n value: xpath\r\n });\r\n }\r\n });\r\n\r\n if (text) {\r\n const xpath = getStrategyXPath(element, \".\", text);\r\n\r\n if (xpath) {\r\n xpaths.push({\r\n key: `xpath by ${strategy} text`,\r\n value: xpath\r\n });\r\n }\r\n }\r\n\r\n return xpaths;\r\n};\r\n\r\nconst buildConditionStrategyXpaths = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n strategy: string\r\n) => {\r\n const attributes = Array.from(element.attributes || []).filter(\r\n (attribute) =>\r\n attribute?.value && checkBlockedAttributes(attribute, element, isTarget)\r\n );\r\n\r\n if (strategy === \"and\") {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n element,\r\n docmt,\r\n attributes,\r\n isTarget\r\n );\r\n\r\n return combinationXpath\r\n ? [{ key: \"xpath by combination\", value: combinationXpath }]\r\n : [];\r\n }\r\n\r\n if (strategy === \"or\" && attributes.length >= 1) {\r\n const xpath = getOrAttributesXPath(element, attributes);\r\n return xpath ? [{ key: \"xpath by or\", value: xpath }] : [];\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst collectSubtreeElements = (root: HTMLElement | Element) => {\r\n if (!root || !(root instanceof Element)) return [];\r\n\r\n const nodes: (HTMLElement | Element)[] = [];\r\n const queue = Array.from(root.children || []);\r\n\r\n while (queue.length) {\r\n const currentNode = queue.shift()!;\r\n\r\n if (currentNode.classList?.contains(\"flntooltip\")) {\r\n continue;\r\n }\r\n\r\n nodes.push(currentNode);\r\n queue.push(...Array.from(currentNode.children || []));\r\n }\r\n\r\n return nodes;\r\n};\r\n\r\nconst getSiblingNodes = (\r\n element: HTMLElement | Element,\r\n direction: \"previous\" | \"next\"\r\n) => {\r\n const nodes: (HTMLElement | Element)[] = [];\r\n let currentNode =\r\n direction === \"previous\"\r\n ? element.previousElementSibling\r\n : element.nextElementSibling;\r\n\r\n while (currentNode) {\r\n if (!currentNode.classList?.contains(\"flntooltip\")) {\r\n nodes.push(currentNode);\r\n }\r\n\r\n currentNode =\r\n direction === \"previous\"\r\n ? currentNode.previousElementSibling\r\n : currentNode.nextElementSibling;\r\n }\r\n\r\n return nodes;\r\n};\r\n\r\ntype AxisSeedNode =\r\n | Element\r\n | {\r\n node: Element;\r\n expand: () => Element[];\r\n };\r\n\r\nconst getDirectionalAxisSeedNodes = (\r\n element: HTMLElement | Element,\r\n direction: \"previous\" | \"next\"\r\n): AxisSeedNode[] => {\r\n const nodes: AxisSeedNode[] = [];\r\n\r\n for (\r\n let currentNode: HTMLElement | Element | null = element;\r\n currentNode?.parentElement;\r\n currentNode = currentNode.parentElement\r\n ) {\r\n let sibling =\r\n direction === \"previous\"\r\n ? currentNode.previousElementSibling\r\n : currentNode.nextElementSibling;\r\n\r\n while (sibling) {\r\n if (!sibling.classList?.contains(\"flntooltip\")) {\r\n nodes.push(sibling);\r\n\r\n nodes.push({\r\n node: sibling,\r\n expand: () => collectSubtreeElements(sibling as HTMLElement)\r\n });\r\n }\r\n\r\n sibling =\r\n direction === \"previous\"\r\n ? sibling.previousElementSibling\r\n : sibling.nextElementSibling;\r\n }\r\n }\r\n\r\n return nodes;\r\n};\r\n\r\nconst isLowQualityNode = (node: Element) => {\r\n if (!(node instanceof Element)) return true;\r\n const text = node.textContent?.trim();\r\n\r\n return (\r\n !node.id &&\r\n !node.className &&\r\n node.attributes.length === 0 &&\r\n (!text || text.length > 60) &&\r\n node.children.length > 2\r\n );\r\n};\r\n\r\nconst buildAxisXpathsForNodes = (\r\n nodes: any[],\r\n axis: string,\r\n targetElement: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n key: string,\r\n isIndex: boolean\r\n) => {\r\n const targetNodeTest = getAxisNodeTest(targetElement);\r\n const MAX_INDEX_TRY = 3;\r\n const MAX_CANDIDATES = 5;\r\n\r\n const candidates: { key: string; value: string }[] = [];\r\n\r\n let processed = 0;\r\n const MAX_PROCESS = axis.includes(\"descendant\") ? 10 : 20;\r\n\r\n for (const nodeItem of nodes) {\r\n if (processed++ > MAX_PROCESS) break;\r\n if (candidates.length >= MAX_CANDIDATES) break;\r\n\r\n const node = \"node\" in nodeItem ? nodeItem.node : nodeItem;\r\n\r\n if (!(node instanceof Element)) continue;\r\n if (isLowQualityNode(node)) continue;\r\n\r\n const anchorStages = [\r\n () => getUniqueNodeAnchorXpaths(node, docmt, isTarget),\r\n () => {\r\n const anchors: any[] = [];\r\n const attributes = Array.from(node.attributes || []).filter(\r\n (attr) =>\r\n attr?.value &&\r\n !/\\d/.test(attr.value) &&\r\n checkBlockedAttributes(attr, node, isTarget)\r\n );\r\n\r\n for (const attr of attributes) {\r\n const value = attr.value;\r\n if (!value) continue;\r\n\r\n const containsXpath = getContainsPropertyXPath(\r\n node,\r\n `@${attr.name}`,\r\n value\r\n );\r\n if (containsXpath) {\r\n anchors.push({ key: \"contains\", value: containsXpath });\r\n }\r\n\r\n const startsWithXpath = getStartsWithPropertyXPath(\r\n node,\r\n `@${attr.name}`,\r\n value\r\n );\r\n if (startsWithXpath) {\r\n anchors.push({ key: \"starts-with\", value: startsWithXpath });\r\n }\r\n }\r\n\r\n return anchors;\r\n },\r\n () => [{ key: \"tag\", value: getTagOnlyXPath(node, docmt) }]\r\n ];\r\n\r\n for (let stageIndex = 0; stageIndex < anchorStages.length; stageIndex++) {\r\n let anchors = anchorStages[stageIndex]();\r\n if (!anchors.length) continue;\r\n\r\n if (!isIndex) {\r\n anchors = anchors.filter((a) => !/\\[\\d+\\]/.test(a.value));\r\n }\r\n\r\n const seen = new Set<string>();\r\n anchors = anchors.filter((a) => {\r\n if (seen.has(a.value)) return false;\r\n seen.add(a.value);\r\n return true;\r\n });\r\n\r\n anchors = anchors.slice(0, 5);\r\n\r\n for (const anchor of anchors) {\r\n const xpath = `${anchor.value}/${axis}::${targetNodeTest}`;\r\n\r\n if (isExactUniqueXpath(xpath, targetElement, docmt)) {\r\n candidates.push({ key, value: xpath });\r\n\r\n if (candidates.length >= 2) {\r\n return candidates;\r\n }\r\n\r\n if (candidates.length >= MAX_CANDIDATES) {\r\n return candidates;\r\n }\r\n }\r\n }\r\n\r\n if (isIndex && stageIndex === anchorStages.length - 1) {\r\n for (const anchor of anchors) {\r\n const count = getCountOfXPath(anchor.value, node, docmt);\r\n\r\n for (let i = 1; i <= Math.min(count, MAX_INDEX_TRY); i++) {\r\n const xpath = `(${anchor.value})[${i}]/${axis}::${targetNodeTest}`;\r\n\r\n if (isExactUniqueXpath(xpath, targetElement, docmt)) {\r\n candidates.push({ key, value: xpath });\r\n\r\n if (candidates.length >= 2) {\r\n return candidates;\r\n }\r\n\r\n if (candidates.length >= MAX_CANDIDATES) {\r\n return candidates;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (\"expand\" in nodeItem && nodeItem.expand) {\r\n const expanded = nodeItem.expand();\r\n\r\n let childCount = 0;\r\n for (const child of expanded) {\r\n if (childCount++ > 15) break;\r\n if (candidates.length >= MAX_CANDIDATES) break;\r\n\r\n if (!(child instanceof Element)) continue;\r\n if (isLowQualityNode(child)) continue;\r\n\r\n const anchors = getUniqueNodeAnchorXpaths(child, docmt, isTarget);\r\n\r\n for (const anchor of anchors.slice(0, 5)) {\r\n const xpath = `${anchor.value}/${axis}::${targetNodeTest}`;\r\n\r\n if (isExactUniqueXpath(xpath, targetElement, docmt)) {\r\n candidates.push({ key, value: xpath });\r\n\r\n if (candidates.length >= 2) {\r\n return candidates;\r\n }\r\n\r\n if (candidates.length >= MAX_CANDIDATES) {\r\n return candidates;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return candidates;\r\n};\r\n\r\nconst buildAxesStrategyXpaths = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n isIndex: boolean\r\n) => {\r\n // const totalStart = performance.now();\r\n\r\n // let t = performance.now();\r\n\r\n const ancestors: (HTMLElement | Element)[] = [];\r\n\r\n for (\r\n let currentNode = element.parentElement;\r\n currentNode;\r\n currentNode = currentNode.parentElement\r\n ) {\r\n ancestors.push(currentNode);\r\n }\r\n // timeLog(\"ancestors collection\", t);\r\n // t = performance.now();\r\n const descendants = collectSubtreeElements(element);\r\n // timeLog(\"descendants collection\", t);\r\n // t = performance.now();\r\n const previousSiblings = getSiblingNodes(element, \"previous\");\r\n // timeLog(\"previous siblings collection\", t);\r\n\r\n const nextSiblings = getSiblingNodes(element, \"next\");\r\n // timeLog(\"next siblings collection\", t);\r\n\r\n const precedingSeeds = getDirectionalAxisSeedNodes(element, \"previous\");\r\n // timeLog(\"preceding seeds collection\", t);\r\n // t = performance.now();\r\n const followingSeeds = getDirectionalAxisSeedNodes(element, \"next\");\r\n // timeLog(\"following seeds collection\", t);\r\n // t = performance.now();\r\n const scoreNode = (node: Element) => {\r\n let score = 0;\r\n if (node.id) score += 100;\r\n if (node.getAttribute(\"data-testid\")) score += 90;\r\n if (node.className) score += 50;\r\n if (node.children.length === 0) score += 30;\r\n\r\n const text = node.textContent?.trim();\r\n if (text && text.length < 40) score += 40;\r\n\r\n return score;\r\n };\r\n\r\n const limitNodes = (nodes: any[], limit = 20) => {\r\n return nodes.length > limit ? nodes.slice(0, limit) : nodes;\r\n };\r\n\r\n const tiers = [\r\n [\r\n {\r\n nodes: limitNodes(nextSiblings),\r\n axis: \"preceding-sibling\",\r\n key: \"preceding-sibling\"\r\n },\r\n {\r\n nodes: limitNodes(previousSiblings),\r\n axis: \"following-sibling\",\r\n key: \"following-sibling\"\r\n }\r\n ],\r\n [\r\n { nodes: limitNodes(ancestors), axis: \"child\", key: \"child\" },\r\n {\r\n nodes: limitNodes(descendants, 15),\r\n axis: \"parent\",\r\n key: \"parent\"\r\n }\r\n ],\r\n [\r\n { nodes: limitNodes(ancestors), axis: \"descendant\", key: \"descendant\" },\r\n {\r\n nodes: limitNodes(ancestors),\r\n axis: \"descendant-or-self\",\r\n key: \"descendant-or-self\"\r\n },\r\n {\r\n nodes: limitNodes(descendants, 10),\r\n axis: \"ancestor\",\r\n key: \"ancestor\"\r\n },\r\n {\r\n nodes: limitNodes(descendants, 10),\r\n axis: \"ancestor-or-self\",\r\n key: \"ancestor-or-self\"\r\n }\r\n ],\r\n [\r\n {\r\n nodes: limitNodes(precedingSeeds),\r\n axis: \"following\",\r\n key: \"following\"\r\n },\r\n { nodes: limitNodes(followingSeeds), axis: \"preceding\", key: \"preceding\" }\r\n ]\r\n ];\r\n // timeLog(\"nodes sorting\", t);\r\n for (const tier of tiers) {\r\n for (const strategy of tier) {\r\n // const t = performance.now();\r\n\r\n const results = buildAxisXpathsForNodes(\r\n strategy.nodes,\r\n strategy.axis,\r\n element,\r\n docmt,\r\n isTarget,\r\n strategy.key,\r\n isIndex\r\n );\r\n\r\n // timeLog(`strategy ${strategy.key}`, t);\r\n if (results.length > 0) {\r\n // timeLog(\"TOTAL buildAxesStrategyXpaths\", totalStart);\r\n return results;\r\n }\r\n }\r\n }\r\n\r\n return [];\r\n};\r\n\r\nexport const generateIndexedXpaths = (element: Element, docmt: Document) => {\r\n const results = [];\r\n const tag = element.tagName.toLowerCase();\r\n\r\n const globalList = Array.from(docmt.querySelectorAll(tag));\r\n const idx = globalList.indexOf(element) + 1;\r\n\r\n if (idx <= 0) return [];\r\n\r\n // global must always exist)\r\n results.push({\r\n key: \"xpath by index\",\r\n value: `(//${tag})[${idx}]`\r\n });\r\n\r\n // Add at most one scoped/indexed XPath anchored by the nearest stable ancestor.\r\n let current: Element | null = element.parentElement;\r\n\r\n while (current && current !== docmt.body) {\r\n if (current.id || current.className) {\r\n const cls = current.className\r\n ?.toString()\r\n .split(\" \")\r\n .map((name) => name.trim())\r\n .find(Boolean);\r\n\r\n const scopeXpath = current.id\r\n ? `//${current.tagName.toLowerCase()}[@id='${current.id}']`\r\n : cls\r\n ? `//${current.tagName.toLowerCase()}[contains(@class,'${cls}')]`\r\n : \"\";\r\n\r\n if (!scopeXpath) {\r\n current = current.parentElement;\r\n continue;\r\n }\r\n\r\n const scopedDescendants = Array.from(current.querySelectorAll(tag));\r\n const scopedIdx = scopedDescendants.indexOf(element) + 1;\r\n\r\n if (scopedIdx > 0) {\r\n results.push({\r\n key: \"xpath by index\",\r\n value: `(${scopeXpath}//${tag})[${scopedIdx}]`\r\n });\r\n break;\r\n }\r\n }\r\n\r\n current = current.parentElement;\r\n }\r\n\r\n return results;\r\n};\r\n\r\nconst buildStrategyXpaths = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n strategy: string,\r\n fallbackXpaths: { key: string; value: string }[]\r\n) => {\r\n const strategyName = getStrategyName(strategy);\r\n\r\n if (strategyName === \"text\") {\r\n return withStrategyKey(\r\n strategy,\r\n buildTextStrategyXpaths(element, docmt, strategyName)\r\n );\r\n }\r\n\r\n if ([\"contains\", \"startsWith\", \"normalizeSpace\"].includes(strategyName)) {\r\n return withStrategyKey(\r\n strategy,\r\n buildPropertyStrategyXpaths(element, isTarget, strategyName)\r\n );\r\n }\r\n\r\n if ([\"and\", \"or\"].includes(strategyName)) {\r\n return withStrategyKey(\r\n strategy,\r\n buildConditionStrategyXpaths(element, docmt, isTarget, strategyName)\r\n );\r\n }\r\n\r\n if (strategyName === \"axes\") {\r\n return withStrategyKey(\r\n strategy,\r\n buildAxesStrategyXpaths(element, docmt, isTarget, false)\r\n );\r\n }\r\n\r\n if (strategyName === \"index\") {\r\n return withStrategyKey(strategy, generateIndexedXpaths(element, docmt));\r\n }\r\n\r\n if (strategyName === \"tag\") {\r\n return withStrategyKey(strategy, [\r\n { key: \"xpath till tag\", value: getTagOnlyXPath(element, docmt) }\r\n ]);\r\n }\r\n\r\n return [];\r\n};\r\n\r\nconst checkRelativeXpathRelation = (\r\n nodeXpath1: string,\r\n nodeXpath2: string,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n relationType: string\r\n) => {\r\n if (nodeXpath1 && !referenceElementMode) {\r\n let xpaths;\r\n\r\n if (relationType === \"parent\") {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/descendant-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/following::${nodeXpath2}`\r\n ];\r\n } else {\r\n xpaths = [\r\n // `${nodeXpath1}/descendant::${nodeXpath2}`,\r\n `${nodeXpath1}/ancestor-or-self::${nodeXpath2}`,\r\n `${nodeXpath1}/preceding::${nodeXpath2}`\r\n ];\r\n }\r\n\r\n // Iterate through XPath patterns\r\n for (const xpath of xpaths) {\r\n // Check if result is already cached to avoid recomputation\r\n if (!xpathCache?.get(xpath)) {\r\n // Compute and store result in cache\r\n xpathCache.set(xpath, getCountOfXPath(xpath, targetElemt, docmt));\r\n }\r\n\r\n const count = xpathCache?.get(xpath);\r\n\r\n // Short-circuit: Return the first valid XPath result found\r\n if (count === 1) {\r\n return xpath;\r\n }\r\n if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: xpath,\r\n count\r\n });\r\n }\r\n }\r\n\r\n if (count > 1 && isIndex && !xpathData.length) {\r\n // Try finding XPath with index if count is greater than 1\r\n const indexedXpath = findXpathWithIndex(\r\n xpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n\r\n // Cache the indexed XPath result\r\n if (\r\n indexedXpath &&\r\n getCountOfXPath(indexedXpath, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by unique parent ${isIndex ? \"index\" : \"\"}`,\r\n value: indexedXpath\r\n });\r\n }\r\n }\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nconst getUniqueParentXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean,\r\n nodeXpath: string,\r\n isIndex: boolean\r\n) => {\r\n try {\r\n if (parentXpathCache.has(domNode)) {\r\n return parentXpathCache.get(domNode);\r\n }\r\n\r\n // Direct XPath construction without loops\r\n const xpathParts = [];\r\n let currentNode = domNode;\r\n\r\n while (currentNode && currentNode.nodeType === 1) {\r\n const hasUniqueAttr = false;\r\n for (const attrName of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attrName, currentNode, isTarget)) {\r\n const attrValue = sanitizeAttributeValue(\r\n attrName.name,\r\n attrName.nodeValue\r\n );\r\n const elementName = attrName.name;\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n\r\n if (currentNode.textContent && !currentNode.textContent) {\r\n if (\r\n !isTarget ||\r\n (isTarget && !isNumberExist(currentNode.textContent))\r\n ) {\r\n let xpathe;\r\n\r\n if (!reWhiteSpace.test(currentNode.textContent)) {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`\r\n : `//${\r\n currentNode.tagName || \"*\"\r\n }[normalize-space(.)=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n } else {\r\n xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and .=${escapeCharacters(getFilteredText(currentNode))}]`\r\n : `//${currentNode.tagName || \"*\"}[.=${escapeCharacters(\r\n getFilteredText(currentNode)\r\n )}]`;\r\n }\r\n\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n } else {\r\n const combinePattern = [];\r\n const contentRes = [\r\n ...new Set(getFilteredText(currentNode).match(/([^0-9]+)/g))\r\n ];\r\n const reWhiteSpace = new RegExp(/^[\\S]+( [\\S]+)*$/gi);\r\n if (contentRes?.length) {\r\n for (let i = 0; i < contentRes?.length; i++) {\r\n if (contentRes[i] && replaceWhiteSpaces(contentRes[i].trim())) {\r\n if (!reWhiteSpace.test(contentRes[i])) {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n replaceWhiteSpaces(contentRes[i])\r\n ).trim()})`\r\n );\r\n } else {\r\n combinePattern.push(\r\n `contains(.,${escapeCharacters(\r\n contentRes[i].trim()\r\n ).trim()})`\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (combinePattern?.length) {\r\n const xpathe = isSvg(currentNode)\r\n ? `//*[local-name()='${\r\n currentNode.tagName\r\n }' and ${combinePattern.join(\" and \")}]`\r\n : `//${currentNode.tagName || \"*\"}[${combinePattern.join(\r\n \" and \"\r\n )}]`;\r\n const othersWithAttr = checkRelativeXpathRelation(\r\n xpathe,\r\n nodeXpath,\r\n node,\r\n docmt,\r\n isIndex,\r\n \"parent\"\r\n );\r\n if (othersWithAttr) {\r\n return othersWithAttr;\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Construct the XPath based on the tag name\r\n if (!hasUniqueAttr) {\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Final constructed XPath\r\n const finalXPath = xpathParts.join(\"\") + nodeXpath;\r\n let count = getCountOfXPath(finalXPath, domNode, docmt);\r\n if (count === 1) {\r\n parentXpathCache.set(domNode, finalXPath); // Cache final result\r\n return finalXPath;\r\n }\r\n } catch (error) {\r\n console.error(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getParentRelativeXpath = (\r\n domNode: HTMLElement,\r\n docmt: Document,\r\n node: HTMLElement | Element,\r\n isTarget: boolean\r\n) => {\r\n const cache = new Map(); // Cache to store computed results\r\n\r\n if (cache.has(domNode)) {\r\n return cache.get(domNode); // Return cached result if available\r\n }\r\n\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath\r\n let currentNode = domNode; // Start with the provided DOM node\r\n\r\n try {\r\n while (currentNode && currentNode.nodeType === 1) {\r\n // BASE CASE #1: If this isn't an element, we're above the root, return empty string\r\n if (!currentNode.tagName) {\r\n return \"\";\r\n }\r\n\r\n // BASE CASE #2: Check for unique attributes\r\n let uniqueAttrFound = false;\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, isTarget)) {\r\n const attrValue = sanitizeAttributeValue(attr.name, attr.nodeValue);\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n xpathParts.unshift(xpathe);\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(textXPath, currentNode, docmt);\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.unshift(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.unshift(xpathe);\r\n } else {\r\n break;\r\n }\r\n // Move to the parent node for the next iteration\r\n currentNode = currentNode.parentElement!;\r\n }\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getChildRelativeXpath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n node: HTMLElement | Element\r\n) => {\r\n const xpathParts = []; // Initialize an array to hold parts of the XPath.\r\n let currentNode: HTMLElement | Element | null;\r\n\r\n const st = [];\r\n if (\r\n domNode.firstElementChild != null &&\r\n domNode.firstElementChild.classList.contains(\"flntooltip\")\r\n ) {\r\n st.unshift(domNode.firstElementChild);\r\n } else if (domNode.nextElementSibling != null)\r\n st.unshift(domNode.nextElementSibling);\r\n\r\n for (\r\n let m = domNode.parentElement;\r\n m != null && m.nodeType === 1;\r\n m = m.parentElement\r\n ) {\r\n if (m.nextElementSibling) st.unshift(m.nextElementSibling);\r\n }\r\n\r\n try {\r\n do {\r\n let uniqueAttrFound = false;\r\n for (currentNode = st.pop()!; currentNode !== null; ) {\r\n for (const attr of Array.from(currentNode.attributes)) {\r\n if (checkBlockedAttributes(attr, currentNode, true)) {\r\n const attrValue = sanitizeAttributeValue(attr.name, attr.nodeValue);\r\n const elementName = attr.name;\r\n\r\n const xpathe = getXpathString(currentNode, elementName, attrValue);\r\n\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(xpathe, currentNode, docmt);\r\n } catch (ign) {\r\n continue;\r\n }\r\n\r\n // If the attribute is unique, return its XPath\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(xpathe);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n // If no unique attributes, check for text content\r\n if (!uniqueAttrFound && currentNode.textContent && !node.textContent) {\r\n const textXPath = getFilteredTextXPath(currentNode, docmt);\r\n if (textXPath) {\r\n const othersWithAttr = getCountOfXPath(\r\n textXPath,\r\n currentNode,\r\n docmt\r\n );\r\n if (othersWithAttr === 1) {\r\n uniqueAttrFound = true; // Mark that we found at least one unique attribute\r\n xpathParts.push(textXPath);\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (!uniqueAttrFound) {\r\n // Construct the XPath based on the tag name\r\n const xpathe = isSvg(currentNode)\r\n ? `/*[local-name()='${currentNode.tagName}']`\r\n : `/${currentNode.tagName}`;\r\n\r\n // Prepend the current XPath part to the array\r\n xpathParts.push(xpathe);\r\n\r\n if (currentNode.firstElementChild != null) {\r\n st.push(currentNode.nextElementSibling);\r\n currentNode = currentNode.firstElementChild;\r\n } else {\r\n currentNode = currentNode.nextElementSibling;\r\n }\r\n } else {\r\n break;\r\n }\r\n }\r\n } while (st.length > 0);\r\n\r\n // Combine all parts into the final XPath\r\n const finalXpath = xpathParts.join(\"\");\r\n cache.set(domNode, finalXpath); // Store result in cache\r\n return finalXpath;\r\n } catch (error) {\r\n console.log(error);\r\n return null;\r\n }\r\n};\r\n\r\nconst getSiblingRelativeXPath = (\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean,\r\n nodeXpath: string\r\n) => {\r\n try {\r\n const markedSpan = document.querySelector(\".flntooltip\");\r\n\r\n for (\r\n let m = domNode.nextElementSibling;\r\n m !== null && m !== markedSpan;\r\n m = m.nextElementSibling\r\n ) {\r\n processSibling(\r\n m,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"preceding-sibling\",\r\n isTarget\r\n );\r\n }\r\n\r\n for (\r\n let n = domNode.previousElementSibling;\r\n n !== null && n !== markedSpan;\r\n n = n.previousElementSibling\r\n ) {\r\n processSibling(\r\n n,\r\n domNode,\r\n docmt,\r\n nodeXpath,\r\n \"following-sibling\",\r\n isTarget\r\n );\r\n }\r\n } catch (error) {\r\n console.error(\"sibling error\", error);\r\n return null;\r\n }\r\n};\r\n\r\nconst processSibling = (\r\n sibling: Element,\r\n domNode: HTMLElement | Element,\r\n docmt: Document,\r\n nodeXpath: string,\r\n axis: string,\r\n isTarget: boolean\r\n) => {\r\n try {\r\n if (sibling.hasAttributes()) {\r\n for (const attr of Array.from(sibling.attributes)) {\r\n let xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: attr.name,\r\n value: attr.value\r\n },\r\n isTarget\r\n );\r\n if (xpathe) {\r\n xpathe += `/${axis}::${nodeXpath}`;\r\n\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!isTarget) {\r\n let xpathe;\r\n xpathe = intermediateXpathStep(\r\n sibling,\r\n {\r\n name: \"text\",\r\n value: sibling.textContent\r\n },\r\n isTarget\r\n );\r\n\r\n if (xpathe) {\r\n const count = getCountOfXPath(xpathe, sibling, docmt);\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `xpath by ${axis}`,\r\n value: xpathe\r\n });\r\n return;\r\n } else if (count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by ${axis}`,\r\n value: xpathe,\r\n count\r\n });\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(`${axis} xpath-error`, error);\r\n }\r\n};\r\n\r\nfunction getXPathUsingAttributeAndText(\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isTarget: boolean\r\n) {\r\n const { tagName } = targetElemt;\r\n const textContent = targetElemt.textContent.trim();\r\n if (!textContent) {\r\n return;\r\n }\r\n for (const attrName of attributes) {\r\n if (checkBlockedAttributes(attrName, targetElemt, isTarget)) {\r\n let attrValue = sanitizeAttributeValue(attrName.name, attrName.nodeValue);\r\n const elementName = attrName.name;\r\n const xpath = `//${tagName}[@${elementName}='${attrValue}' and text()='${textContent}']`;\r\n if (xpath) {\r\n const count = getCountOfXPath(xpath, targetElemt, docmt);\r\n if (count == 1) {\r\n return xpath;\r\n }\r\n }\r\n }\r\n }\r\n}\r\n\r\nconst addRelativeXpaths = (\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n attribute: Attr[]\r\n) => {\r\n try {\r\n let nodeXpath: string[] = [];\r\n let relativeXpath, relativeChildXpath;\r\n xpathData = [];\r\n\r\n console.log(attribute);\r\n if (attribute) {\r\n for (const attrName of attribute) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: attrName.name,\r\n value: attrName.value\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n }\r\n\r\n if (targetElemt.textContent) {\r\n let expression = intermediateXpathStep(\r\n targetElemt,\r\n {\r\n name: \"text\",\r\n value: targetElemt.textContent\r\n },\r\n isTarget\r\n );\r\n\r\n console.log(expression);\r\n if (expression) {\r\n nodeXpath.push(expression);\r\n }\r\n }\r\n\r\n nodeXpath.push(targetElemt.tagName);\r\n\r\n if (nodeXpath?.length) {\r\n for (let i = 0; i < nodeXpath.length; i++) {\r\n if (!xpathData.length) {\r\n getSiblingRelativeXPath(targetElemt, docmt, isTarget, nodeXpath[i]);\r\n\r\n if (!xpathData.length) {\r\n if (!relativeXpath) {\r\n relativeXpath = getParentRelativeXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget\r\n );\r\n }\r\n\r\n console.log(relativeXpath);\r\n\r\n if (\r\n relativeXpath &&\r\n (relativeXpath.includes(\"@\") ||\r\n relativeXpath.includes(\"text()\") ||\r\n relativeXpath.includes(\".=\")) &&\r\n relativeXpath.match(/\\//g)?.length - 2 < 5\r\n ) {\r\n const fullRelativeXpath = relativeXpath + `/${nodeXpath[i]}`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative parent\",\r\n value: fullRelativeXpath\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n if (!relativeChildXpath) {\r\n relativeChildXpath = getChildRelativeXpath(\r\n targetElemt,\r\n docmt,\r\n targetElemt\r\n );\r\n }\r\n\r\n if (\r\n relativeChildXpath &&\r\n (relativeChildXpath.includes(\"@\") ||\r\n relativeChildXpath.includes(\"text()\") ||\r\n relativeChildXpath.includes(\".=\"))\r\n ) {\r\n const fullRelativeXpath = `/${\r\n nodeXpath[i] + relativeChildXpath.substring(1)\r\n }`;\r\n const count = getCountOfXPath(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt\r\n );\r\n\r\n if (count === 1) {\r\n xpathData.push({\r\n key: \"relative xpath by relative child\",\r\n value: fullRelativeXpath\r\n });\r\n } else if (count > 1 && isIndex) {\r\n const relativeXpathIndex = findXpathWithIndex(\r\n fullRelativeXpath,\r\n targetElemt,\r\n docmt,\r\n count\r\n );\r\n if (\r\n relativeXpathIndex &&\r\n getCountOfXPath(relativeXpathIndex, targetElemt, docmt) === 1\r\n ) {\r\n xpathData.push({\r\n key: `relative xpath by relative parent ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: relativeXpathIndex\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (\r\n xpathData?.length === 1 &&\r\n xpathData?.[0]?.value?.match(/\\[([0-9]+)\\]/gm)?.length! > 3 &&\r\n !referenceElementMode\r\n ) {\r\n if (targetElemt.textContent) {\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, false);\r\n if (txtXpath) {\r\n xpathData.unshift({\r\n key: `xpath by text${isIndex ? \"index\" : \"\"}`,\r\n value: txtXpath\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length) {\r\n let tempRelativeXpath = getUniqueParentXpath(\r\n targetElemt.parentElement!,\r\n docmt,\r\n targetElemt,\r\n isTarget,\r\n nodeXpath[i],\r\n isIndex\r\n );\r\n\r\n if (tempRelativeXpath) {\r\n xpathData.push({\r\n key: \"xpath by unique parent\",\r\n value: tempRelativeXpath\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return xpathData;\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const attributesBasedXPath = (\r\n attr: Attr,\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let attrName;\r\n\r\n attrName = attr.name;\r\n let xpath = getPropertyXPath(\r\n targetElemt,\r\n docmt,\r\n `@${attrName}`,\r\n attr.value,\r\n isIndex,\r\n isTarget\r\n );\r\n\r\n return xpath;\r\n};\r\n\r\nexport const getUniqueClassName = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n let value = element.className;\r\n if (typeof value !== \"string\") {\r\n value = \"\";\r\n }\r\n value = value?.replace(\"flndisabled\", \"disabled\");\r\n value = sanitizeAttributeValue(\"class\", value);\r\n value = value?.trim();\r\n\r\n if (value) {\r\n return getPropertyXPath(element, docmt, `@class`, value, isIndex, isTarget);\r\n }\r\n};\r\n\r\nexport const getTextXPath = (\r\n element: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n if ((element.textContent ?? \"\").trim() != \"\") {\r\n const text = getTextContent(element);\r\n\r\n if (text) {\r\n return getPropertyXPath(element, docmt, \".\", text, isIndex, isTarget);\r\n }\r\n }\r\n};\r\n\r\nconst addAllXPathAttributes = (\r\n attributes: Attr[],\r\n targetElemt: HTMLElement | Element,\r\n docmt: Document,\r\n isIndex: boolean,\r\n isTarget: boolean\r\n) => {\r\n const attributesArray = attributes;\r\n try {\r\n attributesArray.map((attr) => {\r\n if (!(attr.name === \"className\" || attr.name === \"class\")) {\r\n if (checkBlockedAttributes(attr, targetElemt, isTarget)) {\r\n const xpth = attributesBasedXPath(\r\n attr,\r\n targetElemt,\r\n docmt,\r\n isIndex,\r\n isTarget\r\n );\r\n if (xpth) {\r\n xpathData.push({\r\n key: `xpath by ${attr.name}${isIndex ? \" index\" : \"\"}`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n }\r\n });\r\n\r\n const txtXpath = getTextXPath(targetElemt, docmt, isIndex, isTarget);\r\n if (txtXpath) {\r\n xpathData.push({\r\n key: `xpath by text${isIndex ? \" index\" : \"\"}`,\r\n value: txtXpath\r\n });\r\n }\r\n\r\n if (\r\n attributesArray.find((element) => element.name === \"className\") &&\r\n checkBlockedAttributes(\r\n attributesArray?.find((element) => element.name === \"className\")!,\r\n targetElemt,\r\n isTarget\r\n )\r\n ) {\r\n let xpath = getUniqueClassName(targetElemt, docmt, isIndex, isTarget);\r\n if (xpath) {\r\n xpathData.push({\r\n key: \"xpath by class\",\r\n value: xpath\r\n });\r\n }\r\n }\r\n\r\n if (!xpathData.length && attributesArray.length > 1) {\r\n const combinationXpath = getAttributeCombinationXpath(\r\n targetElemt,\r\n docmt,\r\n attributesArray,\r\n isTarget\r\n );\r\n if (combinationXpath)\r\n xpathData.push({\r\n key: \"xpath by combination\",\r\n value: combinationXpath\r\n });\r\n }\r\n\r\n if (!xpathData.length) {\r\n const textAttribute = getXPathUsingAttributeAndText(\r\n attributes,\r\n targetElemt,\r\n docmt,\r\n isTarget\r\n );\r\n if (textAttribute)\r\n xpathData.push({\r\n key: \"xpath by textAttribute\",\r\n value: textAttribute\r\n });\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n};\r\n\r\nexport const parseDOM = (\r\n element: HTMLElement | Element,\r\n doc: Document,\r\n isIndex: boolean,\r\n isTarget: boolean,\r\n includedAttributes: Attr[] = [],\r\n strategies: string[] = []\r\n) => {\r\n xpathData = [];\r\n console.log(element);\r\n const targetElemt = element;\r\n const rootNode = targetElemt?.getRootNode?.();\r\n const isShadowScoped = rootNode?.nodeType === Node.DOCUMENT_FRAGMENT_NODE;\r\n const docmt = (\r\n isShadowScoped ? rootNode : targetElemt?.ownerDocument || doc\r\n ) as Document;\r\n const tag = targetElemt.tagName;\r\n const { attributes } = targetElemt;\r\n const attributesToUse =\r\n includedAttributes.length > 0 ? includedAttributes : Array.from(attributes);\r\n addAllXPathAttributes(attributesToUse, targetElemt, docmt, isIndex, isTarget);\r\n\r\n if (strategies.length) {\r\n const strategyXpaths = strategies.flatMap((strategy) =>\r\n buildStrategyXpaths(targetElemt, docmt, isTarget, strategy, xpathData)\r\n );\r\n\r\n xpathData = getUniqueXpathEntries(\r\n strategyXpaths.filter(\r\n (xpath) => getCountOfXPath(xpath.value, targetElemt, docmt) === 1\r\n )\r\n );\r\n\r\n return xpathData;\r\n }\r\n\r\n if (!referenceElementMode) {\r\n if (xpathData.length) {\r\n const len = xpathData.length;\r\n for (let i = 0; i < len; i++) {\r\n let xpth = xpathData[i].value;\r\n xpth = \"//*\" + xpth.substring(xpth.indexOf(\"//\") + 2 + tag.length);\r\n const count = getCountOfXPath(xpth, element, docmt);\r\n if (count === 1) {\r\n xpathData.push({\r\n key: `${xpathData[i].key} regex`,\r\n value: xpth\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!xpathData.length && !isShadowScoped) {\r\n xpathData = buildAxesStrategyXpaths(targetElemt, docmt, isTarget, isIndex);\r\n }\r\n\r\n return xpathData;\r\n};\r\n\r\nconst xpath = {\r\n parseDOM,\r\n getTextXPath,\r\n getUniqueClassName,\r\n attributesBasedXPath,\r\n addAllXPathAttributes,\r\n addRelativeXpaths,\r\n getXPathUsingAttributeAndText,\r\n getSiblingRelativeXPath,\r\n getChildRelativeXpath,\r\n getParentRelativeXpath,\r\n getUniqueParentXpath,\r\n checkRelativeXpathRelation,\r\n buildAxesStrategyXpaths\r\n};\r\n\r\nexport default xpath;\r\n","import { parseDOM } from \"./xpath.ts\";\r\nimport {\r\n findXpathWithIndex,\r\n getShadowRoot,\r\n getTextContent,\r\n escapeCharacters,\r\n getCountOfXPath,\r\n checkBlockedAttributes,\r\n getAbsoluteXPath,\r\n isSvg,\r\n getCombinationXpath,\r\n getTextXpathFunction,\r\n replaceTempAttributes,\r\n replaceActualAttributes,\r\n getReferenceElementsXpath,\r\n getRelativeXPath,\r\n findMatchingParenthesis,\r\n removeParenthesis,\r\n sanitizeAttributeValue\r\n} from \"./xpathHelpers.ts\";\r\n\r\nlet xpathDataWithIndex: any[] = [];\r\nlet xpathData: { key: string; value: string }[] = [];\r\nconst reWhiteSpace = /^[\\S]+( [\\S]+)*$/gi;\r\n\r\nexport const findRelativeXpath = (\r\n element1: Element,\r\n element2: Element,\r\n docmt: Document,\r\n xpaths1: any[],\r\n xpaths2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean = false,\r\n allowedRelations: string[] | null = null\r\n) => {\r\n let finalXpaths: any[] = [];\r\n\r\n const relations = allowedRelations || [];\r\n\r\n const tryRelation = (relation: string, useIndex: boolean) => {\r\n let rel_xpath: any[] = [];\r\n\r\n if (relation === \"descendant\" || relation === \"descendant-or-self\") {\r\n rel_xpath =\r\n getDescendantXpath(\r\n [element1, element2],\r\n docmt,\r\n xpaths1,\r\n xpaths2,\r\n relation as \"descendant\" | \"descendant-or-self\",\r\n useIndex,\r\n multiElementReferenceMode\r\n ) || [];\r\n } else {\r\n rel_xpath =\r\n getXpathRelationExpression(\r\n element1,\r\n element2,\r\n relation,\r\n xpaths1,\r\n xpaths2,\r\n useIndex,\r\n multiElementReferenceMode\r\n ) || [];\r\n }\r\n\r\n if (rel_xpath.length) {\r\n finalXpaths = finalXpaths.concat(rel_xpath);\r\n }\r\n };\r\n\r\n for (const relation of relations) {\r\n tryRelation(relation, isIndex);\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst descendantExpression = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n xpath2: string,\r\n relation: string,\r\n docmt: Node,\r\n isIndex: any,\r\n expCommonParentXpathElements: string | any[],\r\n step4: string,\r\n refCommonParentXpathElementLength: number = 0,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n let finalExpectedElementXpath: string | undefined = \"\";\r\n\r\n if (\r\n xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g)?.length >=\r\n expCommonParentXpathElements.length\r\n ) {\r\n const xpaths2Els: string[] = [];\r\n const xpath2Elements = xpath2.split(/\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g);\r\n for (let x = 1; x <= expCommonParentXpathElements.length; x++) {\r\n xpaths2Els.unshift(\r\n x === expCommonParentXpathElements.length\r\n ? expCommonParentXpathElements[\r\n expCommonParentXpathElements.length - x\r\n ]\r\n : xpath2Elements[xpath2Elements.length - x]\r\n );\r\n }\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${\r\n step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n xpaths2Els,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n } else {\r\n finalExpectedElementXpath = `//${\r\n step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n refExpectElement[refExpectElement.length - 1]\r\n )}`;\r\n let rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation} ${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nconst getDescendantXpath = (\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Document,\r\n xpaths1: { key: string; value: string }[],\r\n xpaths2: { key: string; value: string }[],\r\n relation: \"descendant\" | \"descendant-or-self\",\r\n isIndex: boolean = false,\r\n multiElementReferenceMode: boolean = false\r\n) => {\r\n const refElement: HTMLElement | Element =\r\n refExpectElement[refExpectElement.length - 2];\r\n const expElement: HTMLElement | Element =\r\n refExpectElement[refExpectElement.length - 1];\r\n const expElementDocmnt =\r\n getShadowRoot(expElement) ?? expElement.ownerDocument;\r\n\r\n const refAbsoluteXpath =\r\n xpaths1.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(refElement, refElement.ownerDocument);\r\n\r\n const refFullXpathElements: any[] = [];\r\n const refFullXpathElementsWithoutNumber: any[] = [];\r\n refAbsoluteXpath.split(\"/\").map((x) => refFullXpathElements.push(x));\r\n refFullXpathElements.map((x) =>\r\n refFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n const expAbsoluteXpath =\r\n xpaths2.find((x) => x?.key?.includes(\"absolute\"))?.value ||\r\n getAbsoluteXPath(expElement, expElement.ownerDocument);\r\n\r\n const expFullXpathElements: any[] = [];\r\n const expFullXpathElementsWithoutNumber: any[] = [];\r\n expAbsoluteXpath.split(\"/\").map((x) => expFullXpathElements.push(x));\r\n expFullXpathElements.map((x) =>\r\n expFullXpathElementsWithoutNumber.push(x.replace(/\\[([0-9]+)\\]/gm, \"\"))\r\n );\r\n\r\n for (\r\n var parentElementNumber = 0;\r\n parentElementNumber < refFullXpathElements.length;\r\n parentElementNumber++\r\n ) {\r\n if (\r\n refFullXpathElements[parentElementNumber] !=\r\n expFullXpathElements[parentElementNumber]\r\n ) {\r\n break;\r\n }\r\n }\r\n\r\n const refCommonParentXpathElements = [];\r\n for (let i = parentElementNumber - 1; i < refFullXpathElements.length; i++) {\r\n if (refFullXpathElements[i]) {\r\n refCommonParentXpathElements.push(refFullXpathElementsWithoutNumber[i]);\r\n }\r\n }\r\n\r\n const expCommonParentXpathElements: string[] = [];\r\n for (\r\n let j =\r\n relation === \"descendant\" ? parentElementNumber : parentElementNumber - 1;\r\n j < expFullXpathElements.length;\r\n j++\r\n ) {\r\n if (expFullXpathElements[j]) {\r\n if (expCommonParentXpathElements.length)\r\n expCommonParentXpathElements.push(expFullXpathElementsWithoutNumber[j]);\r\n else\r\n expCommonParentXpathElements.push(\r\n expFullXpathElementsWithoutNumber[j].replace(/\\[([0-9]+)\\]/gm, \"\")\r\n );\r\n }\r\n }\r\n\r\n xpathData = xpaths2;\r\n\r\n let nodeXpath2;\r\n if (refExpectElement[refExpectElement.length - 2].textContent) {\r\n if (\r\n !reWhiteSpace.test(\r\n refExpectElement[refExpectElement.length - 2].textContent\r\n )\r\n ) {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }' and ${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )})]`\r\n : `${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }[${getTextXpathFunction(\r\n refExpectElement[refExpectElement.length - 2]\r\n )}]`;\r\n } else {\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }' and .=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`\r\n : `${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }[.=${escapeCharacters(\r\n getTextContent(refExpectElement[refExpectElement.length - 2])\r\n )}]`;\r\n }\r\n\r\n refCommonParentXpathElements[refCommonParentXpathElements.length - 1] =\r\n nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n if (xpath2) {\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n\r\n if (refExpectElement[refExpectElement.length - 2].attributes) {\r\n for (const attrName of Array.from(\r\n refExpectElement[refExpectElement.length - 2].attributes\r\n )) {\r\n if (\r\n checkBlockedAttributes(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2],\r\n false\r\n )\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = sanitizeAttributeValue(attrName.name, attrValue);\r\n const elementName = attrName.name;\r\n\r\n nodeXpath2 = isSvg(refExpectElement[refExpectElement.length - 2])\r\n ? `*[local-name()='${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }' and @${elementName}=${escapeCharacters(attrValue)}]`\r\n : `${\r\n refExpectElement[refExpectElement.length - 2].tagName\r\n }[@${elementName}=${escapeCharacters(attrValue)}]`;\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n\r\n for (const attrName of Array.from(\r\n refExpectElement[refExpectElement.length - 2].attributes\r\n )) {\r\n if (\r\n checkBlockedAttributes(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2],\r\n false\r\n )\r\n ) {\r\n let attrValue = attrName.nodeValue;\r\n if (attrValue) {\r\n attrValue = sanitizeAttributeValue(attrName.name, attrValue);\r\n const combinationXpath = getCombinationXpath(\r\n attrName,\r\n refExpectElement[refExpectElement.length - 2]\r\n );\r\n if (combinationXpath) {\r\n if (combinationXpath.startsWith(\"//\")) {\r\n nodeXpath2 = combinationXpath.substring(\r\n combinationXpath.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n nodeXpath2 = combinationXpath; // No need to modify the value\r\n }\r\n\r\n refCommonParentXpathElements[\r\n refCommonParentXpathElements.length - 1\r\n ] = nodeXpath2;\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n\r\n const step4 = refCommonParentXpath;\r\n\r\n for (let i = 0; i < xpathData.length; i++) {\r\n let xpath2;\r\n if (xpathData[i].value.startsWith(\"//\")) {\r\n xpath2 = xpathData[i].value.substring(\r\n xpathData[i].value.indexOf(\"//\") + 2\r\n );\r\n } else {\r\n xpath2 = xpathData[i].value; // No need to modify the value\r\n }\r\n\r\n return descendantExpression(\r\n refExpectElement,\r\n xpath2,\r\n relation,\r\n expElementDocmnt || docmt,\r\n isIndex,\r\n expCommonParentXpathElements,\r\n step4,\r\n refCommonParentXpathElementLength,\r\n multiElementReferenceMode\r\n );\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n const refCommonParentXpath = refCommonParentXpathElements.join(\"[\");\r\n const refCommonParentXpathElementLength =\r\n refCommonParentXpathElements.length - 1;\r\n const step4 = refCommonParentXpath;\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${\r\n step4 +\r\n (refCommonParentXpathElementLength\r\n ? \"]\".repeat(refCommonParentXpathElementLength)\r\n : \"\")\r\n }`,\r\n expCommonParentXpathElements,\r\n refExpectElement[refExpectElement.length - 1],\r\n refExpectElement,\r\n docmt,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n if (traverseXpath) {\r\n return traverseXpath;\r\n }\r\n};\r\n\r\nconst getXpathRelationExpression = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n relation: string,\r\n xpath1: any[],\r\n xpath2: any[],\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let xpaths1;\r\n let xpaths2;\r\n console.log(\"getXpathRelationExpression\", relation);\r\n const finalXpaths: { key: string; value: any }[] = [];\r\n\r\n try {\r\n xpaths1 = xpath1.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n xpaths2 = xpath2.filter((x) => !x?.key?.includes(\"absolute\"));\r\n\r\n if (relation === \"ancestor\" || relation === \"ancestor-or-self\") {\r\n const ancestorBridgeXpaths = getAncestorBridgeXpath(\r\n element1,\r\n element2,\r\n relation,\r\n xpaths1,\r\n xpaths2,\r\n isIndex\r\n );\r\n\r\n if (ancestorBridgeXpaths.length) {\r\n return ancestorBridgeXpaths;\r\n }\r\n }\r\n\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n let rel_xpath: string | undefined = `//${\r\n xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(xpaths1[i].value.indexOf(\"//\") + 2),\r\n element1\r\n )\r\n }/${relation}::${\r\n xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths2[j].value, element2)\r\n : replaceActualAttributes(\r\n xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2),\r\n element2\r\n )\r\n }`;\r\n console.log(\"getXpathRelationExpression\", rel_xpath);\r\n const rel_count = getCountOfXPath(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument\r\n );\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n rel_xpath = findXpathWithIndex(\r\n rel_xpath,\r\n element2,\r\n element2.ownerDocument,\r\n rel_count\r\n );\r\n if (rel_xpath) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(rel_xpath)\r\n });\r\n return finalXpaths;\r\n }\r\n } else if (rel_count > 1) {\r\n if (xpathDataWithIndex.length) {\r\n if (rel_count < xpathDataWithIndex[0].count) {\r\n xpathDataWithIndex.pop();\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count\r\n });\r\n }\r\n } else {\r\n xpathDataWithIndex.push({\r\n key: `relative xpath by relative child ${\r\n isIndex ? \"index\" : \"\"\r\n }`,\r\n value: rel_xpath,\r\n count: rel_count\r\n });\r\n }\r\n }\r\n } else if (rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(rel_xpath)\r\n });\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n if (!finalXpaths.length) {\r\n for (let i = 0; i < xpaths1.length; i++) {\r\n for (let j = 0; j < xpaths2.length; j++) {\r\n const tempPath = `${\r\n xpaths2[j].value.indexOf(\"//\") !== 0\r\n ? xpaths2[j].value\r\n : xpaths2[j].value.substring(xpaths2[j].value.indexOf(\"//\") + 2)\r\n }`;\r\n const xpath2Elements: string[] = tempPath.split(\r\n /\\/(?=(?:[^']*\\'[^\\']*\\')*[^\\']*$)/g\r\n );\r\n if (xpath2Elements.length > 1) {\r\n const traverseXpath = getTraverseXpathExpression(\r\n `${\r\n xpaths1[i].value.indexOf(\"//\") !== 0\r\n ? replaceActualAttributes(xpaths1[i].value, element1)\r\n : replaceActualAttributes(\r\n xpaths1[i].value.substring(\r\n xpaths1[i].value.indexOf(\"//\") + 2\r\n ),\r\n element1\r\n )\r\n }`,\r\n xpath2Elements,\r\n element2,\r\n [element1, element2],\r\n element2.ownerDocument,\r\n relation,\r\n isIndex,\r\n multiElementReferenceMode\r\n );\r\n\r\n console.log(\r\n \"getXpathRelationExpression traverseXpath\",\r\n traverseXpath\r\n );\r\n if (traverseXpath) {\r\n finalXpaths.push(...traverseXpath);\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst xpathStepSeparator = /\\/(?=(?:[^']*'[^']*')*[^']*$)/g;\r\n\r\nconst stripXpathPrefix = (xpath: string) =>\r\n xpath.indexOf(\"//\") === 0 ? xpath.substring(xpath.indexOf(\"//\") + 2) : xpath;\r\n\r\nconst getCommonAncestor = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element\r\n) => {\r\n let currentNode: Element | null = element1;\r\n\r\n while (currentNode) {\r\n if (currentNode.contains(element2)) {\r\n return currentNode;\r\n }\r\n\r\n currentNode = currentNode.parentElement;\r\n }\r\n\r\n return null;\r\n};\r\n\r\nconst getSingleStepXpath = (\r\n element: HTMLElement | Element,\r\n xpaths: { key: string; value: string }[]\r\n) => {\r\n for (const xpath of xpaths) {\r\n const xpathValue = stripXpathPrefix(xpath.value);\r\n\r\n if (xpathValue && xpathValue.split(xpathStepSeparator).length === 1) {\r\n return replaceActualAttributes(xpathValue, element);\r\n }\r\n }\r\n\r\n if (element.textContent) {\r\n const textXpath = getTextXpathFunction(element);\r\n\r\n if (textXpath) {\r\n return isSvg(element)\r\n ? `*[local-name()='${element.tagName}' and ${textXpath}]`\r\n : `${element.tagName}[${textXpath}]`;\r\n }\r\n }\r\n\r\n if (element.attributes) {\r\n for (const attrName of Array.from(element.attributes)) {\r\n if (\r\n checkBlockedAttributes(attrName, element, false) &&\r\n attrName.nodeValue\r\n ) {\r\n return isSvg(element)\r\n ? `*[local-name()='${element.tagName}' and @${attrName.name}=${escapeCharacters(\r\n sanitizeAttributeValue(attrName.name, attrName.nodeValue)\r\n )}]`\r\n : `${element.tagName}[@${attrName.name}=${escapeCharacters(\r\n sanitizeAttributeValue(attrName.name, attrName.nodeValue)\r\n )}]`;\r\n }\r\n }\r\n }\r\n\r\n return isSvg(element)\r\n ? `*[local-name()='${element.tagName}']`\r\n : element.tagName;\r\n};\r\n\r\nconst getRelativeXpathFromAncestor = (\r\n ancestorElement: Element,\r\n targetElement: HTMLElement | Element,\r\n targetXPaths: { key: string; value: string }[]\r\n) => {\r\n const steps: string[] = [];\r\n let currentNode: Element | null = targetElement;\r\n\r\n while (currentNode && currentNode !== ancestorElement) {\r\n const currentStep =\r\n currentNode === targetElement\r\n ? getSingleStepXpath(targetElement, targetXPaths)\r\n : isSvg(currentNode)\r\n ? `*[local-name()='${currentNode.tagName}']`\r\n : currentNode.tagName;\r\n\r\n steps.unshift(currentStep);\r\n currentNode = currentNode.parentElement;\r\n }\r\n\r\n return currentNode === ancestorElement ? steps.join(\"/\") : \"\";\r\n};\r\n\r\nconst getAncestorBridgeXpath = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element,\r\n relation: \"ancestor\" | \"ancestor-or-self\",\r\n xpaths1: { key: string; value: string }[],\r\n xpaths2: { key: string; value: string }[],\r\n isIndex: boolean\r\n) => {\r\n const finalXpaths: { key: string; value: string }[] = [];\r\n const commonAncestor = getCommonAncestor(element1, element2);\r\n\r\n if (!commonAncestor || commonAncestor === element2) {\r\n return finalXpaths;\r\n }\r\n\r\n const ancestorNodeTest = isSvg(commonAncestor)\r\n ? `*[local-name()='${commonAncestor.tagName}']`\r\n : commonAncestor.tagName;\r\n const targetRelativeXpath = getRelativeXpathFromAncestor(\r\n commonAncestor,\r\n element2,\r\n xpaths2\r\n );\r\n\r\n if (!targetRelativeXpath) {\r\n return finalXpaths;\r\n }\r\n\r\n for (const xpath of xpaths1) {\r\n const referenceXpath = stripXpathPrefix(xpath.value);\r\n\r\n if (!referenceXpath) {\r\n continue;\r\n }\r\n\r\n let finalExpectedElementXpath: string | undefined =\r\n `//${replaceActualAttributes(\r\n referenceXpath,\r\n element1\r\n )}/${relation}::${ancestorNodeTest}/${targetRelativeXpath}`;\r\n let rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n element2.ownerDocument\r\n );\r\n\r\n if (rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation} bridge`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n });\r\n return finalXpaths;\r\n }\r\n\r\n if (rel_count > 1 && isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n element2,\r\n element2.ownerDocument,\r\n rel_count\r\n );\r\n rel_count = finalExpectedElementXpath\r\n ? getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n element2.ownerDocument\r\n )\r\n : 0;\r\n\r\n if (finalExpectedElementXpath && rel_count === 1) {\r\n finalXpaths.push({\r\n key: `dynamic ${relation} bridge index`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n });\r\n return finalXpaths;\r\n }\r\n }\r\n }\r\n\r\n return finalXpaths;\r\n};\r\n\r\nconst getReferenceElementXpath = (element: HTMLElement | Element) => {\r\n let xpaths1: {\r\n key: string;\r\n value: string;\r\n }[] = [];\r\n\r\n xpaths1 = parseDOM(element, element.ownerDocument, false, false);\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = parseDOM(element, element.ownerDocument, true, false);\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n } else {\r\n let xpaths = parseDOM(element, element.ownerDocument, true, false);\r\n if (xpaths?.length) {\r\n xpaths = xpaths?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(\r\n element,\r\n element.ownerDocument,\r\n false,\r\n false,\r\n Array.from(element.attributes)\r\n )\r\n }\r\n ];\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = [\r\n {\r\n key: \"\",\r\n value: getRelativeXPath(\r\n element,\r\n element.ownerDocument,\r\n true,\r\n false,\r\n Array.from(element.attributes)\r\n )\r\n }\r\n ];\r\n xpaths1 = xpaths1?.map((x) =>\r\n x.value.charAt(0) == \"(\" &&\r\n findMatchingParenthesis(x.value, 0) + 1 === x.value.lastIndexOf(\"[\")\r\n ? { key: \"\", value: removeParenthesis(x.value) }\r\n : { key: \"\", value: x.value }\r\n );\r\n }\r\n\r\n if (!xpaths1?.length) {\r\n xpaths1 = getReferenceElementsXpath(element, element.ownerDocument, false);\r\n } else {\r\n const xpaths = getReferenceElementsXpath(\r\n element,\r\n element.ownerDocument,\r\n false\r\n );\r\n if (xpaths?.length) {\r\n xpaths1 = xpaths1.concat(xpaths);\r\n }\r\n }\r\n\r\n const referenceXpathElement = getAbsoluteXPath(\r\n element,\r\n element.ownerDocument\r\n );\r\n xpaths1 = xpaths1.filter((x) => x.value !== referenceXpathElement);\r\n\r\n xpaths1.push({\r\n key: \"absolute xpath\",\r\n value: referenceXpathElement.slice(1)\r\n });\r\n\r\n return xpaths1;\r\n};\r\n\r\nconst getTraverseXpathExpression = (\r\n xpathe1: string,\r\n absoluteXpathElements: string[],\r\n element2: HTMLElement | Element,\r\n refExpectElement: Array<HTMLElement | Element>,\r\n docmt: Node,\r\n relation: string,\r\n isIndex: boolean,\r\n multiElementReferenceMode: boolean\r\n) => {\r\n let finalExpectedElementXpath: string | undefined;\r\n if (!multiElementReferenceMode) {\r\n for (let x = 1; x <= absoluteXpathElements.length; x++) {\r\n const xpath2 = absoluteXpathElements\r\n .slice(absoluteXpathElements.length - x, absoluteXpathElements.length)\r\n .join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n } else {\r\n const xpath2 = absoluteXpathElements.join(\"/\");\r\n finalExpectedElementXpath = `//${xpathe1}/${relation}::${replaceActualAttributes(\r\n xpath2,\r\n element2\r\n )}`;\r\n const rel_count = getCountOfXPath(\r\n finalExpectedElementXpath,\r\n element2,\r\n docmt\r\n );\r\n if (rel_count === 1) {\r\n return [\r\n {\r\n key: `dynamic ${relation}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n if (rel_count > 1) {\r\n if (isIndex) {\r\n finalExpectedElementXpath = findXpathWithIndex(\r\n finalExpectedElementXpath,\r\n refExpectElement[refExpectElement.length - 1],\r\n docmt,\r\n rel_count\r\n );\r\n if (finalExpectedElementXpath) {\r\n return [\r\n {\r\n key: `dynamic ${relation}${isIndex ? \" index\" : \"\"}`,\r\n value: replaceTempAttributes(finalExpectedElementXpath)\r\n }\r\n ];\r\n }\r\n }\r\n }\r\n }\r\n};\r\n\r\nexport const getSmartRelations = (\r\n element1: HTMLElement | Element,\r\n element2: HTMLElement | Element\r\n) => {\r\n const pos = element1.compareDocumentPosition(element2);\r\n\r\n const highPriority: string[] = [];\r\n const mediumPriority: string[] = [];\r\n const lowPriority: string[] = [];\r\n\r\n // Ancestor\r\n if (pos & Node.DOCUMENT_POSITION_CONTAINS) {\r\n highPriority.push(\"ancestor\", \"ancestor-or-self\", \"parent\");\r\n }\r\n\r\n // Descendant direct\r\n if (pos & Node.DOCUMENT_POSITION_CONTAINED_BY) {\r\n highPriority.push(\"child\");\r\n }\r\n\r\n // Siblings\r\n if (element1.parentElement === element2.parentElement) {\r\n highPriority.push(\"following-sibling\", \"preceding-sibling\");\r\n }\r\n\r\n // Directional\r\n if (pos & Node.DOCUMENT_POSITION_FOLLOWING) {\r\n mediumPriority.push(\"following\");\r\n }\r\n\r\n if (pos & Node.DOCUMENT_POSITION_PRECEDING) {\r\n mediumPriority.push(\"preceding\");\r\n }\r\n\r\n // always include fallback\r\n lowPriority.push(\"descendant\", \"descendant-or-self\");\r\n\r\n const relations = [...highPriority, ...mediumPriority, ...lowPriority];\r\n\r\n return [...new Set(relations)];\r\n};\r\nconst referenceXpath = {\r\n findRelativeXpath,\r\n getDescendantXpath,\r\n getAncestorBridgeXpath,\r\n getXpathRelationExpression,\r\n getTraverseXpathExpression,\r\n getReferenceElementXpath,\r\n getSmartRelations\r\n};\r\nexport default referenceXpath;\r\n","import { SelectorMode } from \"../types/locator.ts\";\r\nimport { isNumberExist } from \"./xpathHelpers.ts\";\r\n\r\nlet modifiedElementAttributes: [] = [];\r\n\r\nconst escapeCssAttributeValue = (value: string): string => {\r\n return String(value).replace(/\\\\/g, \"\\\\\\\\\").replace(/\"/g, '\\\\\"');\r\n};\r\n\r\nconst isCssSelectorUnique = (\r\n selector: string,\r\n el: Element,\r\n root: Document | ShadowRoot | ParentNode\r\n): boolean => {\r\n try {\r\n const matches = root.querySelectorAll(selector);\r\n return matches.length === 1 && matches[0] === el;\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport const parseCssSelectors = (\r\n el: Element,\r\n mode: SelectorMode = \"single\"\r\n) => {\r\n const selectors: { key: string; value: string }[] = [];\r\n const root = el.getRootNode() as Document | ShadowRoot;\r\n\r\n try {\r\n const idPath = getIdCssPath(el);\r\n if (idPath && isCssSelectorUnique(idPath, el, root)) {\r\n selectors.push({ key: \"cssSelector by id\", value: idPath });\r\n if (mode === \"single\") return selectors;\r\n }\r\n const classPath = getClassCssPath(el);\r\n if (classPath && isCssSelectorUnique(classPath, el, root)) {\r\n selectors.push({ key: \"cssSelector by class\", value: classPath });\r\n }\r\n const namePath = getAttributeCssPath(el);\r\n if (namePath) {\r\n selectors.push({ key: \"cssSelector by name\", value: namePath });\r\n }\r\n // commented out absolute path strategy as it is not performing well and causing performance issues in large DOMs\r\n // const absPath = getAbsoluteCssPath(el);\r\n // if (absPath && isCssSelectorUnique(absPath, el, root)) {\r\n // selectors.push({ key: 'Absolute cssSelector', value: absPath });\r\n // }\r\n } catch (e) {\r\n console.error(e);\r\n }\r\n return selectors;\r\n};\r\n\r\nexport const getIdCssPath = (el: HTMLElement | Element) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName.includes(\"style\") || tagName.includes(\"script\")) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n if (el.id && !isNumberExist(el.id)) {\r\n selector += `#${CSS.escape(el.id)}`;\r\n path.unshift(selector);\r\n break;\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(\" > \");\r\n};\r\n\r\nconst EXCLUDED_ATTRS = new Set([\"id\", \"class\", \"style\"]);\r\nfunction getAttributeSelectors(el: Element): string[] {\r\n return Array.from(el.attributes)\r\n .filter(\r\n (attr) =>\r\n !EXCLUDED_ATTRS.has(attr?.name?.toLowerCase()) &&\r\n attr.value &&\r\n !isNumberExist(attr.value)\r\n )\r\n .map((attr) => `[${attr.name}=\"${escapeCssAttributeValue(attr.value)}\"]`);\r\n}\r\n\r\nexport const getAttributeCssPath = (el: Element): string | undefined => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const root = el.getRootNode() as ParentNode;\r\n const tag = el.tagName.toLowerCase();\r\n\r\n if (tag === \"style\" || tag === \"script\") return;\r\n\r\n const attrSelectors = getAttributeSelectors(el);\r\n\r\n for (const attrSelector of attrSelectors) {\r\n const candidate = `${tag}${attrSelector}`;\r\n\r\n if (isCssSelectorUnique(candidate, el, root)) {\r\n return candidate;\r\n }\r\n }\r\n return;\r\n};\r\n\r\nexport const getClassCssPath = (el: HTMLElement | Element) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n const tagName = el.tagName.toLowerCase();\r\n if (tagName.includes(\"style\") || tagName.includes(\"script\")) return;\r\n\r\n const path = [];\r\n while (el?.nodeType === Node.ELEMENT_NODE) {\r\n let selector = el.nodeName?.toLowerCase();\r\n\r\n if (\r\n typeof el.className === \"string\" &&\r\n el.className &&\r\n !isNumberExist(el.className) &&\r\n !modifiedElementAttributes?.find(\r\n (x: { element: HTMLElement | Element; attributeName: string }) =>\r\n x.element === el && x.attributeName === \"class\"\r\n )\r\n ) {\r\n el.classList.remove(\"marked-element-temp\");\r\n el.classList.remove(\"removePointers\");\r\n if (el.className) {\r\n selector += `.${el.className.trim().replace(/\\s+/g, \".\")}`;\r\n path.unshift(selector);\r\n break;\r\n }\r\n } else {\r\n let sib = el;\r\n let nth = 1;\r\n if (sib.previousElementSibling) {\r\n while ((sib = sib.previousElementSibling)) {\r\n if (sib.nodeName?.toLowerCase() === selector) nth++;\r\n }\r\n }\r\n\r\n if (nth !== 1) {\r\n selector += `:nth-of-type(${nth})`;\r\n }\r\n\r\n if (nth === 1 && sib?.parentElement?.childElementCount! > 1) {\r\n selector += `:nth-child(${nth})`;\r\n }\r\n }\r\n path.unshift(selector);\r\n el = el.parentElement!;\r\n }\r\n return path.join(\" > \");\r\n};\r\n\r\nexport const getAbsoluteCssPath = (el: Element) => {\r\n const view = el.ownerDocument?.defaultView;\r\n if (!view || !(el instanceof view.Element)) return;\r\n\r\n const path: string[] = [];\r\n\r\n while (el && el.nodeType === Node.ELEMENT_NODE) {\r\n const tagName = el.tagName.toLowerCase();\r\n\r\n if (tagName === \"style\" || tagName === \"script\") return;\r\n\r\n let selector = tagName;\r\n\r\n const parent = el.parentNode;\r\n\r\n if (parent) {\r\n const siblings = Array.from(parent.children).filter(\r\n (c) => c.tagName === el.tagName\r\n );\r\n\r\n if (siblings.length > 1) {\r\n selector += `:nth-of-type(${siblings.indexOf(el) + 1})`;\r\n }\r\n }\r\n\r\n path.unshift(selector);\r\n\r\n el = el.parentElement!;\r\n }\r\n\r\n return path.join(\" > \");\r\n};\r\n\r\nexport const cssSelectors = {\r\n parseCssSelectors,\r\n getIdCssPath,\r\n getAttributeCssPath,\r\n getClassCssPath,\r\n getAbsoluteCssPath\r\n};\r\n","import { ElementRecord, Locator } from \"../types/locator.ts\";\r\nimport { parseDOM } from \"./xpath.ts\";\r\nimport { parseCssSelectors } from \"./cssSelector.ts\";\r\nimport {\r\n isNumberExist,\r\n normalizeXPath,\r\n getXPathPattern,\r\n escapeAttrValue,\r\n isUniqueInDOM,\r\n shouldUseSnapshot\r\n} from \"./xpathHelpers.ts\";\r\n\r\nconst isSameXPathStillValid = (\r\n xpath: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n const normalized = normalizeXPath(xpath);\r\n const found = getElementFromXPath(docmt, normalized);\r\n if (found === target) return true;\r\n\r\n if (shouldUseSnapshot(normalized)) {\r\n const result = docmt.evaluate(\r\n normalized,\r\n docmt,\r\n null,\r\n XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,\r\n null\r\n );\r\n\r\n for (let i = 0; i < result.snapshotLength; i++) {\r\n if (result.snapshotItem(i) === target) return true;\r\n }\r\n }\r\n\r\n return false;\r\n};\r\n\r\nconst getElementFromCssSelector = (\r\n docmt: Document,\r\n selector: string\r\n): Element | null => {\r\n try {\r\n const found = docmt.querySelector(selector);\r\n if (found) return found;\r\n } catch (error) {\r\n console.error(\"Invalid CSS selector:\", selector, error);\r\n return null;\r\n }\r\n\r\n return getElementFromShadowRoot(docmt.body, selector);\r\n};\r\n\r\nconst isSameCssSelectorStillValid = (\r\n selector: string,\r\n docmt: Document,\r\n target: Element\r\n): boolean => {\r\n return getElementFromCssSelector(docmt, selector) === target;\r\n};\r\n\r\nconst resolveIsSelfHealed = (\r\n locName: string,\r\n oldValue: string | null | undefined,\r\n newValue: string | null | undefined\r\n): \"Y\" | null => {\r\n if (!oldValue || !newValue) return \"Y\";\r\n return oldValue === newValue ? null : \"Y\";\r\n};\r\n\r\nconst isCssSelectorLocator = (locator: { name?: string | null }): boolean => {\r\n return locator.name?.toLowerCase().includes(\"cssselector\") ?? false;\r\n};\r\n\r\ntype ElementDetails = {\r\n id?: string | null;\r\n className?: string | null;\r\n xpathByText?: string | null;\r\n xpathById?: string | null;\r\n xpathByClass?: string | null;\r\n xpathAbsolute?: string | null;\r\n xpathByName?: string | null;\r\n xpathByPlaceholder?: string | null;\r\n xpathByType?: string | null;\r\n visibleText?: string | null;\r\n relativeXpath?: string | null;\r\n [key: string]: any;\r\n};\r\n\r\nconst getElementFromShadowRoot = (\r\n el: Element | ShadowRoot,\r\n selector: string\r\n): Element | null => {\r\n // const shadowRoot = (element as HTMLElement).shadowRoot;\r\n // if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n // return shadowRoot.querySelector(selector);\r\n // }\r\n\r\n const elements = Array.from(el.querySelectorAll(\"*\"));\r\n\r\n try {\r\n for (let i = 0; i < elements.length; i++) {\r\n if (elements[i].shadowRoot) {\r\n const { shadowRoot } = elements[i];\r\n if (shadowRoot) {\r\n const nestedElement = getElementFromShadowRoot(shadowRoot, selector);\r\n if (nestedElement) {\r\n return nestedElement;\r\n }\r\n if (shadowRoot && !selector.includes(\"dynamic\")) {\r\n return shadowRoot.querySelector(selector);\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.log(error);\r\n }\r\n return null;\r\n};\r\n\r\nconst getId = (element: Element | null): string | null => {\r\n return element?.id || null;\r\n};\r\n\r\nconst getClassName = (element: Element): string | null => {\r\n return (element as HTMLElement).className || null;\r\n};\r\n\r\nconst getVisibleText = (element: Element): string | null => {\r\n return element.textContent?.trim() || null;\r\n};\r\n\r\nconst getName = (element: Element): string | null => {\r\n const elementEl = element as HTMLElement;\r\n\r\n if (elementEl.hasAttribute(\"name\")) {\r\n const attrValue = elementEl.getAttribute(\"name\");\r\n const name = `${attrValue}`;\r\n return name || null;\r\n }\r\n return null;\r\n};\r\n\r\nconst relations: string[] = [\r\n \"/preceding-sibling\",\r\n \"/following-sibling\",\r\n \"/parent\",\r\n \"/descendant\",\r\n \"/ancestor\",\r\n \"/self\",\r\n \"/ancestor-or-self\",\r\n \"/child\",\r\n \"/preceding\",\r\n \"/following\"\r\n];\r\n\r\nfunction getElementFromXPath(docmt: Document, xpath: string): Element | null {\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n xpath,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n return xpathResult.singleNodeValue as Element | null;\r\n}\r\n\r\nfunction checkReferenceElementIsValid(\r\n locator: string,\r\n relation: string,\r\n docmt: Document\r\n): string | null {\r\n if (locator.includes(relation)) {\r\n const locatotSplitArray: string[] = locator.split(relation);\r\n const sourceLoc = locatotSplitArray[0].trim();\r\n const window = docmt.defaultView;\r\n if (!window) return null;\r\n if (!locator.includes(\"dynamic\")) {\r\n const xpathEvaluator = new window.XPathEvaluator();\r\n const xpathResult = xpathEvaluator.evaluate(\r\n sourceLoc,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n\r\n const sourceElement = xpathResult.singleNodeValue;\r\n if (sourceElement) {\r\n const xpathResultComplete = xpathEvaluator.evaluate(\r\n locator,\r\n docmt,\r\n null,\r\n window.XPathResult.FIRST_ORDERED_NODE_TYPE,\r\n null\r\n );\r\n const completeElement = xpathResultComplete.singleNodeValue;\r\n let relativeXpath: string;\r\n if (completeElement) {\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n } else {\r\n console.error(\"Complete Locator is Invalid:\", locator);\r\n relativeXpath = locator;\r\n return relativeXpath;\r\n }\r\n } else {\r\n console.error(\"Source Locator Not Found:\", sourceLoc);\r\n }\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nconst getElementsFromHTML = (\r\n record: ElementRecord,\r\n docmt: Document\r\n): ElementDetails | null => {\r\n const elementsToRemove = docmt.querySelectorAll(\r\n \"script, style, link[rel='stylesheet'], meta, noscript, embed, object, param, source, svg\"\r\n );\r\n\r\n if (elementsToRemove) {\r\n elementsToRemove.forEach((tag) => {\r\n (tag as Element).remove();\r\n });\r\n }\r\n\r\n const finalLocatorsSet: Set<string> = new Set();\r\n let finalLocators: any[] = [];\r\n\r\n function createLocator(base: any, overrides: Partial<any> = {}) {\r\n const oldValue = base?.value;\r\n const newValue = overrides.value ?? base?.value;\r\n const newLocator: any = {\r\n name: overrides.name ?? base?.name,\r\n type: overrides.type ?? base?.type,\r\n value: overrides.value ?? base?.value,\r\n reference: overrides.reference ?? base?.reference,\r\n status: overrides.status ?? base?.status,\r\n isRecorded: overrides.isRecorded ?? base?.isRecorded\r\n };\r\n\r\n const previousSelfHealed = base?.isSelfHealed === \"Y\";\r\n\r\n newLocator.isSelfHealed = previousSelfHealed\r\n ? \"Y\"\r\n : overrides.hasOwnProperty(\"isSelfHealed\")\r\n ? overrides.isSelfHealed\r\n : resolveIsSelfHealed(newLocator.name, oldValue, newValue);\r\n\r\n pushUniqueLocator(newLocator);\r\n }\r\n\r\n function resolveElement(\r\n ctx: Document,\r\n locator: any,\r\n selector: string\r\n ): Element | null {\r\n if (isCssSelectorLocator(locator)) {\r\n return getElementFromCssSelector(ctx, selector);\r\n } else if (locator.name.includes(\"id\") || selector.startsWith(\"#\")) {\r\n return ctx.querySelector(\"#\" + escapeAttrValue(selector));\r\n } else if (locator.name.includes(\"className\") || selector.startsWith(\".\")) {\r\n return ctx.querySelector(\".\" + selector);\r\n } else if (locator.name === \"name\") {\r\n const safeName = escapeAttrValue(selector);\r\n return ctx.querySelector(`[name=\"${safeName}\"]`);\r\n } else if (locator.name === \"tagName\") {\r\n return ctx.querySelector(selector);\r\n } else if (locator.name === \"linkText\") {\r\n return (\r\n Array.from(ctx.querySelectorAll(\"a\")).find(\r\n (a) => a.textContent?.trim() === selector\r\n ) || null\r\n );\r\n } else if (locator.name === \"partialLinkText\") {\r\n return (\r\n Array.from(ctx.querySelectorAll(\"a\")).find((a) =>\r\n a.textContent?.includes(selector)\r\n ) || null\r\n );\r\n } else if (\r\n (locator.name.includes(\"xpath\") || selector.startsWith(\"//\")) &&\r\n !locator.type.match(\"dynamic\")\r\n ) {\r\n const normalizedXPath = normalizeXPath(selector);\r\n const el = getElementFromXPath(ctx, normalizedXPath);\r\n\r\n if (el) {\r\n createLocator(locator, {\r\n value: selector,\r\n isRecorded: String(locator.isRecorded).includes(\"N\") ? \"N\" : \"Y\"\r\n });\r\n }\r\n\r\n return el;\r\n } else {\r\n return ctx.querySelector(selector);\r\n }\r\n }\r\n\r\n function findInIframes(\r\n docmt: Document,\r\n locator: any,\r\n selector: string\r\n ): Element | null {\r\n const iframes = docmt.querySelectorAll(\"iframe\");\r\n\r\n for (const iframe of iframes) {\r\n try {\r\n const iframeDoc =\r\n iframe.contentDocument || iframe.contentWindow?.document;\r\n\r\n if (!iframeDoc) continue;\r\n\r\n const el = resolveElement(iframeDoc, locator, selector);\r\n if (el) return el;\r\n } catch {\r\n continue;\r\n }\r\n }\r\n\r\n return null;\r\n }\r\n\r\n function pushUniqueLocator(obj: any) {\r\n const key = `${obj.name}:${obj.value}`;\r\n if (!finalLocatorsSet.has(key)) {\r\n finalLocatorsSet.add(key);\r\n finalLocators.push(obj);\r\n }\r\n }\r\n\r\n /** Locator Value Cleaner (Handles Special Scenarios) **/\r\n const cleanLocatorValue = (\r\n val: string | null | undefined,\r\n type?: string,\r\n isRecorded?: string\r\n ): string | null => {\r\n if (!val) return null;\r\n\r\n let cleaned = val.trim();\r\n\r\n // Return null for empty or literal \"null\"\r\n if (!cleaned || cleaned.toLowerCase() === \"null\") return null;\r\n\r\n // Unescape any escaped quotes\r\n cleaned = cleaned.replace(/\\\\\"/g, '\"').replace(/\\\\'/g, \"'\");\r\n\r\n // Remove surrounding single or double quotes\r\n cleaned = cleaned.replace(/^['\"](.+?)['\"]$/, \"$1\");\r\n\r\n // Replace double single quotes with a single quote inside XPath\r\n cleaned = cleaned.replace(/''/g, \"'\");\r\n\r\n // Normalize double quotes in XPath attribute selectors [@id=\"\" -> [@id='']\r\n cleaned = cleaned.replace(\r\n /\\[@(id|name)=['\"]{2}(.+?)['\"]{2}\\]/g,\r\n \"[@$1='$2']\"\r\n );\r\n\r\n // For DOM selectors (id or name), remove ALL quotes\r\n if (type === \"id\" || type === \"name\") {\r\n cleaned = cleaned.replace(/['\"]/g, \"\").trim();\r\n }\r\n\r\n if (type === \"xpath\" && isRecorded === \"Y\" && !val.startsWith(\"//\"))\r\n return null;\r\n\r\n // Final check for empty strings\r\n if (!cleaned || /^['\"]{2}$/.test(cleaned)) return null;\r\n\r\n return cleaned;\r\n };\r\n\r\n locators: for (const locator of record.locators) {\r\n try {\r\n const isRecorded = String(locator.isRecorded || \"\");\r\n const recordedNLocators = record.locators.filter(\r\n (l) => l.isRecorded === \"N\"\r\n );\r\n\r\n if (recordedNLocators.length > 0) {\r\n for (const locator of recordedNLocators) {\r\n createLocator(locator);\r\n }\r\n }\r\n\r\n const isDynamic = String(locator.value || locator.type || \"\");\r\n if (\r\n isDynamic.includes(\"dynamic\") ||\r\n isDynamic.match(\"dynamic\") ||\r\n isDynamic.includes(\"{\") ||\r\n isDynamic.includes(\"}\")\r\n ) {\r\n createLocator(locator);\r\n continue;\r\n }\r\n\r\n if (record.isShared.includes(\"Y\")) {\r\n break locators;\r\n }\r\n\r\n try {\r\n let targetElement: Element | null = null;\r\n const selectors = locator.value.split(\">>>\");\r\n\r\n for (const selector of selectors) {\r\n if (!docmt) {\r\n console.error(\"Element not found at:\", selector);\r\n break;\r\n }\r\n\r\n const trimmedSelector = selector.trim();\r\n\r\n //normal DOM\r\n targetElement = resolveElement(docmt, locator, trimmedSelector);\r\n\r\n //iframe (if not found)\r\n if (!targetElement) {\r\n targetElement = findInIframes(docmt, locator, trimmedSelector);\r\n }\r\n\r\n //shadow DOM (if still not found)\r\n if (!targetElement) {\r\n targetElement = getElementFromShadowRoot(\r\n docmt.body,\r\n trimmedSelector\r\n );\r\n }\r\n\r\n if (!targetElement) {\r\n console.error(\"Element not found at:\", trimmedSelector);\r\n break;\r\n }\r\n }\r\n\r\n const locatorExists = (name: string, value: string): boolean => {\r\n const key = `${name}:${value}`;\r\n return finalLocatorsSet.has(key);\r\n };\r\n\r\n if (targetElement) {\r\n const payloadXPaths = record.locators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n const payloadCssSelectors = record.locators.filter(\r\n (l) => isCssSelectorLocator(l) && l.value\r\n );\r\n\r\n for (const px of payloadXPaths) {\r\n if (isSameXPathStillValid(px.value, docmt, targetElement))\r\n createLocator(px, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n for (const cssLocator of payloadCssSelectors) {\r\n if (\r\n isSameCssSelectorStillValid(\r\n cssLocator.value,\r\n docmt,\r\n targetElement\r\n )\r\n )\r\n createLocator(cssLocator, {\r\n isSelfHealed: null\r\n });\r\n }\r\n\r\n const existingXPaths = finalLocators.filter(\r\n (l) => l.name === \"xpath\" && l.value\r\n );\r\n\r\n // Track XPath patterns already used\r\n const usedXPathPatterns = new Set<string>(\r\n existingXPaths.map((x) => getXPathPattern(x.value))\r\n );\r\n\r\n const excludedAttributes: string[] = [];\r\n const idValue = getId(targetElement);\r\n if (\r\n idValue &&\r\n !locatorExists(\"id\", idValue) &&\r\n !isNumberExist(idValue)\r\n ) {\r\n const prevId = record.locators.find((l) => l.name === \"id\");\r\n if (isUniqueInDOM(docmt, \"id\", idValue, targetElement)) {\r\n excludedAttributes.push(\"id\");\r\n createLocator(prevId, {\r\n name: \"id\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: idValue\r\n });\r\n }\r\n }\r\n\r\n const tagName = targetElement.tagName;\r\n if (tagName && !locatorExists(\"tagName\", tagName)) {\r\n const prevTag = record.locators.find((l) => l.name === \"tagName\");\r\n if (isUniqueInDOM(docmt, \"tagName\", tagName, targetElement)) {\r\n excludedAttributes.push(\"tagName\");\r\n createLocator(prevTag, {\r\n name: \"tagName\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: tagName\r\n });\r\n }\r\n }\r\n\r\n const textValue = getVisibleText(targetElement);\r\n if (textValue && !isNumberExist(textValue)) {\r\n const prevLinkText = record.locators.find(\r\n (l) => l.name === \"linkText\"\r\n );\r\n if (isUniqueInDOM(docmt, \"linkText\", textValue, targetElement)) {\r\n excludedAttributes.push(\"linkText\");\r\n createLocator(prevLinkText, {\r\n name: \"linkText\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: textValue\r\n });\r\n }\r\n }\r\n\r\n const nameLocator = getName(targetElement);\r\n if (\r\n nameLocator &&\r\n !locatorExists(\"name\", nameLocator) &&\r\n !isNumberExist(nameLocator)\r\n ) {\r\n const prevName = record.locators.find((l) => l.name === \"name\");\r\n if (isUniqueInDOM(docmt, \"name\", nameLocator, targetElement)) {\r\n excludedAttributes.push(\"name\");\r\n createLocator(prevName, {\r\n name: \"name\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: nameLocator\r\n });\r\n }\r\n }\r\n\r\n const classValue = getClassName(targetElement);\r\n if (\r\n classValue &&\r\n classValue.trim() !== \"\" &&\r\n !classValue.includes(\" \") &&\r\n !locatorExists(\"className\", classValue) &&\r\n !isNumberExist(classValue)\r\n ) {\r\n const prevClassLocator = record.locators.find(\r\n (l) => l.name === \"className\"\r\n );\r\n if (isUniqueInDOM(docmt, \"className\", classValue, targetElement)) {\r\n excludedAttributes.push(\"className\");\r\n createLocator(prevClassLocator, {\r\n name: \"className\",\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n value: classValue\r\n });\r\n }\r\n }\r\n parseCssSelectors(targetElement, \"single\").forEach(\r\n (cssSelector) => {\r\n if (\r\n cssSelector.value &&\r\n !locatorExists(\"cssSelector\", cssSelector.value)\r\n ) {\r\n createLocator(undefined, {\r\n name: \"cssSelector\",\r\n value: cssSelector.value,\r\n type: \"static\",\r\n isRecorded: \"Y\"\r\n });\r\n }\r\n }\r\n );\r\n const allAttributes = Array.from(targetElement.attributes);\r\n const includedAttributes = allAttributes.filter(\r\n (attr) => !excludedAttributes.includes(attr.name)\r\n );\r\n\r\n //If any direct locator is broken then we consider it as broken xpath\r\n\r\n let xpathResults: any[] = [];\r\n try {\r\n xpathResults =\r\n parseDOM(targetElement, docmt, false, true, includedAttributes) ??\r\n [];\r\n } catch (error) {\r\n console.error(\"Error generating XPath candidates:\", error);\r\n }\r\n\r\n if (xpathResults?.length !== 0) {\r\n const brokenPayloadXPaths = payloadXPaths.filter(\r\n (px) => !isSameXPathStillValid(px.value, docmt, targetElement)\r\n );\r\n\r\n let xpathAdded = 0;\r\n\r\n for (const brokenPx of brokenPayloadXPaths) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n\r\n const originalPattern = getXPathPattern(brokenPx.value);\r\n if (usedXPathPatterns.has(originalPattern)) continue;\r\n\r\n const match = xpathResults.find(\r\n (r) => r.value && getXPathPattern(r.value) === originalPattern\r\n );\r\n\r\n if (match?.value) {\r\n createLocator(brokenPx, {\r\n name: \"xpath\",\r\n value: match.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(originalPattern);\r\n xpathAdded++;\r\n }\r\n }\r\n if (xpathAdded < brokenPayloadXPaths.length) {\r\n for (const result of xpathResults) {\r\n if (xpathAdded >= brokenPayloadXPaths.length) break;\r\n if (!result.value) continue;\r\n\r\n const pattern = getXPathPattern(result.value);\r\n if (usedXPathPatterns.has(pattern)) continue;\r\n\r\n createLocator(result, {\r\n name: \"xpath\",\r\n value: result.value,\r\n type: \"static\",\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n\r\n usedXPathPatterns.add(pattern);\r\n xpathAdded++;\r\n }\r\n }\r\n }\r\n for (const locator of record.locators) {\r\n try {\r\n for (const loc of record.locators) {\r\n if (!loc.value) continue;\r\n\r\n for (const relation of relations) {\r\n if (loc.value.includes(relation)) {\r\n const relativeXpath = checkReferenceElementIsValid(\r\n loc.value,\r\n relation,\r\n docmt\r\n );\r\n if (relativeXpath) {\r\n createLocator(loc, {\r\n name: \"xpath\",\r\n value: relativeXpath,\r\n isRecorded:\r\n locator.isRecorded !== \"\" &&\r\n locator.isRecorded !== null\r\n ? locator.isRecorded\r\n : \"Y\"\r\n });\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n }\r\n }\r\n if (finalLocators.length < 5) {\r\n const fallbackCandidates = [\r\n { name: \"id\", value: getId(targetElement) },\r\n { name: \"name\", value: getName(targetElement) },\r\n { name: \"className\", value: getClassName(targetElement) },\r\n { name: \"tagName\", value: targetElement.tagName },\r\n { name: \"linkText\", value: getVisibleText(targetElement) }\r\n ];\r\n\r\n for (const candidate of fallbackCandidates) {\r\n if (finalLocators.length > 4) break;\r\n\r\n const { name, value } = candidate;\r\n if (!value) continue;\r\n if (isNumberExist(value)) continue;\r\n if (locatorExists(name, value)) continue;\r\n if (name === \"className\" && value.includes(\" \")) continue;\r\n if (isUniqueInDOM(docmt, name, value, targetElement)) {\r\n createLocator(undefined, {\r\n name,\r\n type: \"static\",\r\n value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n }\r\n\r\n if (finalLocators.length < 5) {\r\n parseCssSelectors(targetElement, \"multiple\").forEach(\r\n (cssSelector) => {\r\n if (finalLocators.length > 4) return;\r\n if (!cssSelector.value) return;\r\n if (locatorExists(\"cssSelector\", cssSelector.value)) return;\r\n if (\r\n !isUniqueInDOM(\r\n docmt,\r\n \"cssSelector\",\r\n cssSelector.value,\r\n targetElement\r\n )\r\n ) {\r\n return;\r\n }\r\n\r\n createLocator(undefined, {\r\n name: \"cssSelector\",\r\n type: \"static\",\r\n value: cssSelector.value,\r\n isRecorded: \"Y\",\r\n isSelfHealed: \"Y\"\r\n });\r\n }\r\n );\r\n }\r\n }\r\n\r\n const finalAutoHealedLocators = finalLocators.map((obj) => ({\r\n ...obj,\r\n value: cleanLocatorValue(obj.value, obj.name, obj.isRecorded)\r\n }));\r\n\r\n const jsonResult = [\r\n {\r\n name: `${record.name}`,\r\n desc: `${record.desc}`,\r\n type: `${record.type}`,\r\n locators: finalAutoHealedLocators.filter(\r\n (locator) => locator?.value != null && locator.value !== \"\"\r\n ),\r\n isShared: `${record.isShared}`,\r\n projectId: `${record.projectId}`,\r\n projectType: `${record.projectType}`,\r\n isRecorded: `${record.isRecorded}`,\r\n folder: `${record.folder}`,\r\n parentId: `${record.parentId}`,\r\n parentName: `${record.parentName}`,\r\n platform: `${record.platform}`,\r\n licenseId: `${record.licenseId}`,\r\n licenseType: `${record.licenseType}`,\r\n userId: `${record.userId}`\r\n }\r\n ];\r\n\r\n return jsonResult;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n } catch (error) {\r\n console.error(\"Error processing locator:\", locator, error);\r\n continue;\r\n }\r\n }\r\n return null;\r\n};\r\n\r\nexport { getElementsFromHTML };\r\n","import { isNumberExist, getCountOfXPath } from \"./xpathHelpers\";\r\nfunction getOptimalClassChain(\r\n doc: Document,\r\n domNode: HTMLElement | Element | null,\r\n uniqueAttributes: Attr[]\r\n): string | null {\r\n\r\n try {\r\n\r\n if (\r\n !domNode ||\r\n domNode.nodeType !== 1 ||\r\n !domNode.tagName ||\r\n domNode.tagName === \"XCUIElementTypeApplication\"\r\n ) {\r\n return \"\";\r\n }\r\n\r\n const tag = domNode.tagName;\r\n\r\n // Priority attributes\r\n const priorityAttrs = [\"name\", \"label\", \"value\"];\r\n\r\n // ---------- STEP 1 : TRY GOOD ATTRIBUTES ----------\r\n for (const attrName of priorityAttrs) {\r\n\r\n const attr = uniqueAttributes.find(a => a.name === attrName);\r\n if (!attr) continue;\r\n\r\n let attrValue = attr.value;\r\n if (!attrValue) continue;\r\n\r\n attrValue = attrValue.trim().replace(/\\s+/g, \" \");\r\n\r\n if (isNumberExist(attrValue)) continue;\r\n\r\n const xpath = `//${tag}[@${attrName}=\"${attrValue}\"]`;\r\n\r\n let count = 0;\r\n\r\n try {\r\n count = getCountOfXPath(xpath, domNode, doc);\r\n } catch (err) {\r\n console.log(err);\r\n continue;\r\n }\r\n\r\n const hasSpace = /\\s/.test(attrValue);\r\n\r\n if (count === 1) {\r\n\r\n if (hasSpace) {\r\n return `/${tag}[\\`${attrName} CONTAINS \"${attrValue}\"\\`]`;\r\n }\r\n\r\n return `/${tag}[\\`${attrName} == \"${attrValue}\"\\`]`;\r\n }\r\n\r\n if (count > 1 && domNode.parentElement) {\r\n\r\n const siblings = Array.from(domNode.parentElement.children)\r\n .filter(el => el.tagName === tag);\r\n\r\n const index = siblings.indexOf(domNode) + 1;\r\n\r\n if (hasSpace) {\r\n return `/${tag}[\\`${attrName} CONTAINS \"${attrValue}\"\\`][${index}]`;\r\n }\r\n\r\n return `/${tag}[\\`${attrName} == \"${attrValue}\"\\`][${index}]`;\r\n }\r\n }\r\n\r\n // ---------- STEP 2 : FALLBACK USING TAG INDEX ----------\r\n let classChain = `/${tag}`;\r\n\r\n if (domNode.parentElement) {\r\n\r\n const siblings = Array.from(domNode.parentElement.children)\r\n .filter(el => el.tagName === tag);\r\n\r\n if (siblings.length > 1) {\r\n\r\n const index = siblings.indexOf(domNode) + 1;\r\n\r\n classChain += `[${index}]`;\r\n }\r\n }\r\n\r\n const parentChain = getOptimalClassChain(\r\n doc,\r\n domNode.parentElement,\r\n uniqueAttributes\r\n );\r\n\r\n return parentChain + classChain;\r\n\r\n } catch (error) {\r\n\r\n console.log(\r\n `Unable to generate optimal -ios class chain : ${JSON.stringify(error)}`\r\n );\r\n\r\n return null;\r\n }\r\n}\r\nfunction getOptimalPredicateString(\r\n doc: Document,\r\n domNode: HTMLElement | Element | null,\r\n uniqueAttributes: Attr[]\r\n) {\r\n try {\r\n // BASE CASE #1: If this isn't an element, we're above the root, or this is `XCUIElementTypeApplication`,\r\n // which is not an official XCUITest element, return empty string\r\n if (\r\n !domNode?.tagName ||\r\n domNode?.nodeType !== 1 ||\r\n domNode?.tagName === 'XCUIElementTypeApplication'\r\n ) {\r\n return '';\r\n }\r\n\r\n // BASE CASE #2: Check all attributes and try to find the best way\r\n let xpathAttributes: string[] = [];\r\n let predicateString: string[] = [];\r\n\r\n for (let attr of uniqueAttributes) {\r\n const attrValue = attr.value;\r\n const attrName = attr.name;\r\n\r\n if (attrValue.length === 0) {\r\n continue;\r\n }\r\n if (attrValue && !isNumberExist(attrValue)) {\r\n xpathAttributes.push(`@${attrName}=\"${attrValue}\"`);\r\n const xpathe = `//*[${xpathAttributes.join(' and ')}]`;\r\n predicateString.push(`${attrName} == \"${attrValue}\"`);\r\n let othersWithAttr;\r\n\r\n // If the XPath does not parse, move to the next unique attribute\r\n try {\r\n othersWithAttr = getCountOfXPath(\r\n xpathe,\r\n domNode,\r\n doc\r\n );\r\n } catch (ign) {\r\n console.log(ign);\r\n continue;\r\n }\r\n\r\n // If the attribute isn't actually unique, get it's index too\r\n if (othersWithAttr === 1) {\r\n return predicateString.join(' AND ');\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n // If there's an unexpected exception, abort and don't get an XPath\r\n console.log(\r\n `The most optimal '-ios predicate string' could not be determined because an error was thrown: '${JSON.stringify(\r\n error,\r\n null,\r\n 2\r\n )}'`\r\n );\r\n }\r\n return null;\r\n}\r\n\r\nexport const iosSelectors = {\r\n getOptimalClassChain,\r\n getOptimalPredicateString\r\n};","import xpath from '../utils/xpath.ts';\r\nimport referenceXpaths from '../utils/referenceXpath.ts';\r\nimport { xpathUtils } from '../utils/xpathHelpers.ts';\r\nimport { getElementsFromHTML } from '../utils/getElementsFromHTML.ts';\r\nimport { cssSelectors } from '../utils/cssSelector.ts';\r\nimport { iosSelectors } from '../utils/iosSelector.ts';\r\n\r\nexport const createXPathAPI = () => ({\r\n xpath,\r\n referenceXpaths,\r\n xpathUtils,\r\n getElementsFromHTML,\r\n cssSelectors,\r\n iosSelectors\r\n});\r\n\r\nexport default createXPathAPI;"],"names":["reWhiteSpace","xpathEvalCache","WeakMap","clearXPathEvalCache","node","contexts","addContext","candidate","includes","push","rootNode","getRootNode","Document","ShadowRoot","nodeType","Node","DOCUMENT_NODE","ownerDocument","getMutationCacheContexts","forEach","contextNode","delete","evaluateXPathOnce","xpath","docmt","owner","document","getXPathContext","nodeCache","get","Map","set","cached","result","evaluate","XPathResult","ORDERED_NODE_ITERATOR_TYPE","evalResult","first","iterateNext","second","mutationObserver","relativeXPathCache","modifiedElementAttributes","INTERNAL_CLASS_TOKENS","Set","normalizeClassTokens","classValue","split","map","token","trim","filter","has","sort","sanitizeAttributeValue","attributeName","attributeValue","join","replace","isInternalClassOnlyMutation","mutation","type","target","Element","isSvg","oldValue","classList","value","previousTokens","currentTokens","getAttribute","isNumberExist","str","test","buildPattern","pattern","tagName","getTextContent","targetElement","textContent","getFilteredText","element","childNodes","nodeValue","getCountOfXPath","multiElementReferenceMode","Array","isArray","matchCount","error","console","escapeCharacters","text","indexOf","removeParenthesis","charArr","count","length","indexArray","reverse","finalStr","i","endBracketLength","firstpart","slice","startsWith","endsWith","findXpathWithIndex","val","index","nodes","ANY_TYPE","nodex","isSameNode","log","deleteGarbageFromInnerText","a","deleteLineGap","reduce","b","c","replaceWhiteSpaces","getShadowRoot","el","root","host","createShadowEvaluationContext","tempDoc","implementation","createHTMLDocument","wrapper","createElement","innerHTML","body","appendChild","cloneForElement","defaultView","path","current","parentElement","parent","unshift","from","children","parentNode","getElementPathFromRoot","container","next","item","getElementAtPath","cloneElements","Boolean","cloneElement","checkBlockedAttributes","attribute","isTarget","sanitizedValue","name","some","x","isModified","find","doc","SVGElement","replaceTempAttributes","getPropertyXPath","prop","isIndex","combinePattern","mergePattern","toLowerCase","splitText","contentRes","match","endIndex","startIndexString","endIndexString","getAbsoluteXPath","domNode","xpathe","prototype","call","childNode","HTMLElement","offsetParent","getRelativeXPath","attributesArray","xpathParts","currentNode","hasUniqueAttr","attributes","attrName","attrValue","elementName","getXpathString","othersWithAttr","RegExp","tagBasedXPath","siblings","finalXPath","getCombinationXpath","getAttributeCombinationXpath","uniqueAttributes","candidateAttributes","attr","buildAttributeConditions","classTokens","rankedTokens","getTagOnlyXpathCandidateCount","left","right","getTextConditions","rawText","conditions","add","generateAttributeCombinations","combinationSize","results","build","startIndex","currentGroup","pop","buildXPath","tryAttributeOnlyCombinations","attributeGroups","attributeGroup","xpathConditions","attributeConditions","attributeOnlyXpath","textConditions","textCondition","JSON","stringify","intermediateXpathStep","targetElemt","isSvgElement","expression","getFilteredTextXPath","filteredText","getNormalizedPropertyXPath","getStartsWithPropertyXPath","getContainsPropertyXPath","getOrAttributesXPath","rankedToken","buildAttributeCondition","buildTextCondition","_error","getAncestorAnchorCandidates","anchors","seen","priorityAttrs","orderedAttributes","pushAnchor","isExactUniqueXpath","textXpath","combinationXpath","getStructuralPathFromAncestor","ancestor","steps","getAxisNodeTest","getTagOnlyXPath","fallbackXpath","ancestorAnchors","ancestorXpath","descendantXpath","getFirstMatchedNode","structuralPath","parentChainXpath","parentChainCount","fallbackCount","DOCUMENT_FRAGMENT_NODE","FIRST_ORDERED_NODE_TYPE","singleNodeValue","getUniqueNodeAnchorXpaths","key","tagXpath","getTextXpathFunction","trimmedText","replaceActualAttributes","getReferenceElementsXpath","nodeXpath1","xpaths1","tag","xpaths","xpth","addAttributeSplitCombineXpaths","concat","normalizeXPath","findMatchingParenthesis","openPos","closePos","counter","getXPathPattern","canonical","canonicalizeXPath","parts","xp","axisMatch","axis","attrMatch","usesNormalize","extractXPathSignatureParts","escapeAttrValue","isUniqueInDOM","queryAll","selector","querySelectorAll","xpathUtils","parseXml","xmlStr","window","DOMParser","parseFromString","getElementFromXpath","multi","getRelationship","pos","compareDocumentPosition","createObserver","addedNodeCallBack","MutationObserver","mutations","addedNodes","url","baseURI","startObserver","options","observe","stopObserver","disconnect","cspEnabled","xpathData","xpathDataWithIndex","xpathCache","cache","parentXpathCache","STRATEGY_MAP","andConditions","orConditions","contains","normalizeSpace","axes","hardCodedText","tillTag","withStrategyKey","strategy","entries","entry","getNormalizedText","collectSubtreeElements","queue","shift","getSiblingNodes","direction","previousElementSibling","nextElementSibling","getDirectionalAxisSeedNodes","sibling","expand","isLowQualityNode","id","className","buildAxisXpathsForNodes","targetNodeTest","candidates","processed","MAX_PROCESS","nodeItem","anchorStages","containsXpath","startsWithXpath","stageIndex","anchor","Math","min","expanded","childCount","child","buildAxesStrategyXpaths","ancestors","descendants","previousSiblings","nextSiblings","precedingSeeds","followingSeeds","limitNodes","limit","tiers","tier","buildStrategyXpaths","fallbackXpaths","strategyName","getStrategyName","getTextXPath","buildTextStrategyXpaths","getStrategyXPath","buildPropertyStrategyXpaths","buildConditionStrategyXpaths","idx","cls","toString","scopeXpath","scopedIdx","generateIndexedXpaths","checkRelativeXpathRelation","nodeXpath2","relationType","indexedXpath","getUniqueParentXpath","nodeXpath","ign","getParentRelativeXpath","uniqueAttrFound","textXPath","finalXpath","getChildRelativeXpath","st","firstElementChild","m","getSiblingRelativeXPath","markedSpan","querySelector","processSibling","n","hasAttributes","getXPathUsingAttributeAndText","attributesBasedXPath","getUniqueClassName","addAllXPathAttributes","txtXpath","textAttribute","parseDOM","includedAttributes","strategies","isShadowScoped","attributesToUse","strategyXpaths","flatMap","getUniqueXpathEntries","len","substring","addRelativeXpaths","relativeXpath","relativeChildXpath","fullRelativeXpath","relativeXpathIndex","tempRelativeXpath","descendantExpression","refExpectElement","xpath2","relation","expCommonParentXpathElements","step4","refCommonParentXpathElementLength","finalExpectedElementXpath","xpaths2Els","xpath2Elements","traverseXpath","getTraverseXpathExpression","repeat","rel_count","getDescendantXpath","xpaths2","refElement","expElement","expElementDocmnt","refAbsoluteXpath","refFullXpathElements","refFullXpathElementsWithoutNumber","expAbsoluteXpath","expFullXpathElements","expFullXpathElementsWithoutNumber","parentElementNumber","refCommonParentXpathElements","j","refCommonParentXpath","getXpathRelationExpression","element1","element2","xpath1","finalXpaths","ancestorBridgeXpaths","getAncestorBridgeXpath","rel_xpath","xpathStepSeparator","stripXpathPrefix","getSingleStepXpath","xpathValue","commonAncestor","getCommonAncestor","ancestorNodeTest","targetRelativeXpath","ancestorElement","targetXPaths","currentStep","getRelativeXpathFromAncestor","referenceXpath","xpathe1","absoluteXpathElements","findRelativeXpath","allowedRelations","relations","tryRelation","useIndex","getReferenceElementXpath","charAt","lastIndexOf","referenceXpathElement","getSmartRelations","highPriority","mediumPriority","lowPriority","DOCUMENT_POSITION_CONTAINS","DOCUMENT_POSITION_CONTAINED_BY","DOCUMENT_POSITION_FOLLOWING","DOCUMENT_POSITION_PRECEDING","isCssSelectorUnique","matches","parseCssSelectors","mode","selectors","idPath","getIdCssPath","classPath","getClassCssPath","namePath","getAttributeCssPath","e","view","ELEMENT_NODE","nodeName","CSS","escape","sib","nth","childElementCount","EXCLUDED_ATTRS","getAttributeSelectors","String","attrSelectors","attrSelector","remove","cssSelectors","getAbsoluteCssPath","isSameXPathStillValid","normalized","getElementFromXPath","shouldUseSnapshot","ORDERED_NODE_SNAPSHOT_TYPE","snapshotLength","snapshotItem","getElementFromCssSelector","found","getElementFromShadowRoot","isSameCssSelectorStillValid","isCssSelectorLocator","locator","elements","shadowRoot","nestedElement","getId","getClassName","getVisibleText","getName","elementEl","hasAttribute","XPathEvaluator","checkReferenceElementIsValid","sourceLoc","xpathEvaluator","getElementsFromHTML","record","elementsToRemove","finalLocatorsSet","finalLocators","createLocator","base","overrides","newValue","newLocator","reference","status","isRecorded","previousSelfHealed","isSelfHealed","hasOwnProperty","locName","resolveIsSelfHealed","obj","pushUniqueLocator","resolveElement","ctx","safeName","findInIframes","iframes","iframe","iframeDoc","contentDocument","contentWindow","cleanLocatorValue","cleaned","locators","recordedNLocators","l","isDynamic","isShared","trimmedSelector","locatorExists","payloadXPaths","payloadCssSelectors","px","cssLocator","existingXPaths","usedXPathPatterns","excludedAttributes","idValue","prevId","prevTag","textValue","prevLinkText","nameLocator","prevName","prevClassLocator","cssSelector","undefined","xpathResults","brokenPayloadXPaths","xpathAdded","brokenPx","originalPattern","r","loc","fallbackCandidates","finalAutoHealedLocators","jsonResult","desc","projectId","projectType","folder","parentId","parentName","platform","licenseId","licenseType","userId","iosSelectors","getOptimalClassChain","err","hasSpace","classChain","getOptimalPredicateString","xpathAttributes","predicateString","createXPathAPI","referenceXpaths"],"mappings":"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"}