ff-dom 2.0.7 → 2.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.browser.cjs +1 -1
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.js +1 -1
- package/dist/index.browser.js.map +1 -1
- package/dist/index.cdn.js +1 -1
- package/dist/types/browser/browser/xpath.d.ts +1 -1
- package/dist/types/browser/types/locator.d.ts +1 -0
- package/dist/types/browser/utils/cssSelector.d.ts +3 -2
- package/dist/types/browser/utils/xpathHelpers.d.ts +1 -1
- package/dist/types/node/types/locator.d.ts +1 -0
- package/dist/types/node/utils/cssSelector.d.ts +3 -2
- package/dist/types/node/utils/xpathHelpers.d.ts +1 -1
- package/dist/xpath.mjs +1 -1
- package/dist/xpath.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.browser.cjs","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): boolean {\r\n try {\r\n switch (name) {\r\n case \"id\":\r\n return (\r\n docmt.getElementById(value) !== null &&\r\n docmt.querySelectorAll(`#${escapeAttrValue(value)}`).length === 1\r\n );\r\n\r\n case \"name\":\r\n return (\r\n docmt.querySelectorAll(`[name=\"${escapeAttrValue(value)}\"]`)\r\n .length === 1\r\n );\r\n\r\n case \"className\":\r\n return docmt.getElementsByClassName(value).length === 1;\r\n\r\n case \"tagName\":\r\n return docmt.getElementsByTagName(value).length === 1;\r\n\r\n case \"linkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter(\r\n (a) => a.textContent?.trim() === value\r\n ).length === 1\r\n );\r\n case \"partialLinkText\":\r\n return (\r\n Array.from(docmt.querySelectorAll(\"a\")).filter((a) =>\r\n a.textContent?.includes(value)\r\n ).length === 1\r\n );\r\n case \"cssSelector\":\r\n return docmt.querySelectorAll(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 { isNumberExist } from \"./xpathHelpers.ts\";\r\n\r\nlet modifiedElementAttributes: [] = [];\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) => {\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 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}=\"${CSS.escape(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 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 if (locator.value.startsWith(\"iframe\")) {\r\n const iframe = docmt.querySelector(\r\n locator.value\r\n ) as HTMLIFrameElement;\r\n if (iframe) {\r\n const iframeDocument =\r\n iframe.contentDocument || iframe.contentWindow?.document;\r\n if (iframeDocument) {\r\n targetElement = iframeDocument.querySelector(\r\n locator.value.slice(6)\r\n );\r\n }\r\n }\r\n } else {\r\n const selectors = locator.value.split(\">>>\"); // Custom delimiter for shadow DOM\r\n\r\n for (const selector of selectors) {\r\n if (docmt) {\r\n const trimmedSelector = selector.trim();\r\n if (isCssSelectorLocator(locator)) {\r\n targetElement = getElementFromCssSelector(\r\n docmt,\r\n trimmedSelector\r\n );\r\n } else if (\r\n locator.name.includes(\"id\") ||\r\n trimmedSelector.startsWith(\"#\")\r\n ) {\r\n targetElement = docmt.querySelector(\r\n \"#\" + escapeAttrValue(trimmedSelector)\r\n );\r\n } else if (\r\n locator.name.includes(\"className\") ||\r\n trimmedSelector.startsWith(\".\")\r\n ) {\r\n targetElement = docmt.querySelector(\".\" + trimmedSelector);\r\n } else if (locator.name === \"name\") {\r\n const safeName = escapeAttrValue(trimmedSelector);\r\n targetElement = docmt.querySelector(`[name=\"${safeName}\"]`);\r\n } else if (locator.name === \"tagName\") {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n } else if (locator.name === \"linkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find(\r\n (a) => a.textContent?.trim() === trimmedSelector\r\n ) || null;\r\n } else if (locator.name === \"partialLinkText\") {\r\n targetElement =\r\n Array.from(docmt.querySelectorAll(\"a\")).find((a) =>\r\n a.textContent?.includes(trimmedSelector)\r\n ) || null;\r\n } else if (\r\n (locator.name.includes(\"xpath\") ||\r\n trimmedSelector.startsWith(\"//\")) &&\r\n !locator.type.match(\"dynamic\")\r\n ) {\r\n const normalizedXPath = normalizeXPath(trimmedSelector);\r\n targetElement = getElementFromXPath(docmt, normalizedXPath);\r\n if (targetElement) {\r\n createLocator(locator, {\r\n value: trimmedSelector,\r\n isRecorded: String(locator.isRecorded).includes(\"N\")\r\n ? \"N\"\r\n : \"Y\"\r\n });\r\n }\r\n } else {\r\n targetElement = docmt.querySelector(trimmedSelector);\r\n if (!targetElement) {\r\n targetElement = getElementFromShadowRoot(\r\n docmt.body,\r\n trimmedSelector\r\n );\r\n }\r\n }\r\n } else {\r\n console.error(\"Element not found at:\", selector);\r\n break;\r\n }\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)) {\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)) {\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)) {\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)) {\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)) {\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).forEach((cssSelector) => {\r\n if (\r\n cssSelector.value &&\r\n !locatorExists(\"cssSelector\", cssSelector.value) &&\r\n isUniqueInDOM(docmt, \"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 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)) {\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\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","getElementById","querySelectorAll","getElementsByClassName","getElementsByTagName","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","selector","matches","parseCssSelectors","selectors","idPath","getIdCssPath","classPath","getClassCssPath","namePath","getAttributeCssPath","absPath","getAbsoluteCssPath","e","view","defaultView","Element","path","ELEMENT_NODE","id","CSS","escape","sib","nth","childElementCount","EXCLUDED_ATTRS","attrSelectors","getAttributeSelectors","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","cleanLocatorValue","cleaned","locators","String","recordedNLocators","l","isDynamic","isShared","iframe","iframeDocument","contentDocument","contentWindow","trimmedSelector","safeName","normalizedXPath","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.cjs","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":"oEAAO,MAAMA,EAAe,oBAE5B,MAAMC,EAAsC,CAAA,EAC5C,IAOIC,EAPAC,EAAqB,IAAIC,IAClBC,EAKL,GAGC,MA+CMC,EAAiBC,GACV,KACDC,KAAKD,GAaXE,EACXC,IAEA,MAAMC,EAAcD,GAAeC,YAiBjC,OAAOA,GAMEC,EAAmBC,GACvBA,GAASC,WAAW,IAAIC,WAAa,GAGjCC,EAAkB,CAC7BC,EACAJ,EACAK,EACAC,GAAqC,KAErC,IACE,IAAIC,EAEJ,QAA0BC,IAAtBpB,EAAWgB,GACbG,EAAQnB,EAAWgB,OACd,CAMLG,GAJqB,IAAnBF,EAAMI,SACDJ,EACDA,EAAMK,eAEEC,SACZ,SAASP,KACTC,EACA,KACAO,YAAYC,YACZ,MACAC,YACF1B,EAAWgB,GAASG,CACtB,CAEA,GAAID,GAA6BS,MAAMC,QAAQhB,IAC7C,GAAIO,EAAQ,EAAG,CACb,MAAMU,EAAoBC,EAAoBd,EAAOC,GAAO,GAC5D,IAAIc,EACFC,EAAe,EACjB,GAAIH,aAA6BL,YAC/B,MAAQO,EAAQF,GAAmBI,kBAC7BrB,EAAQsB,SAASH,KACnBC,GAAgB,EAEK,IAAjBA,MAKV,GAAqB,IAAjBA,EAAoB,OAAO,CACjC,OAGA,GAAc,IAAVb,EAAa,CAEf,OADyBW,EAAoBd,EAAOC,KACxBL,EAAUO,EAAQ,CAChD,CAEF,OAAOA,CACT,CAAE,MAAOgB,GAEP,OADAC,QAAQD,MAAM,2BAA2BnB,IAASmB,GAC3C,CACT,GAGWE,EAAoBC,IAC/B,GAAIA,EAAM,CACR,IAA4B,IAAtBA,EAAKC,QAAQ,KACjB,MAAO,IAAID,KAEb,IAA4B,IAAtBA,EAAKC,QAAQ,KACjB,MAAO,IAAID,IAEf,CACA,MAAO,IAAIA,MAGAE,EAAqBxB,IAChC,MAAMyB,EAAUzB,EAAM0B,MAAM,IAE5B,IAAIvB,EAAQsB,EAAQE,OACpB,MAAMC,EAAa,GAEnB,KAA8B,MAAvBH,EAAQtB,EAAQ,IACrByB,EAAWC,KAAKJ,EAAQtB,EAAQ,IAChCA,IAGFyB,EAAWE,UACX,IAAIC,EAAW,GACf,IAAK,IAAIC,EAAI,EAAGA,EAAIJ,EAAWD,OAAQK,IACrCD,GAAYH,EAAWI,GAGzB,MAAMC,EAAmBF,EAASJ,OAAS,EAC3C,IAAIO,EAAYlC,EAAMmC,MAAM,EAAGnC,EAAM2B,OAASM,GAQ9C,OALEC,EADEA,EAAUE,WAAW,MAAQF,EAAUG,SAAS,KACtCH,EAAUC,MAAM,GAAG,GAEnBnC,EAGPkC,GAGII,EAAqB,CAChCC,EACAC,EACAvC,EACAE,KAEA,IACE,MAAMsC,EACe,IAAnBxC,EAAMI,SACDJ,EACDA,EAAMK,cAEZ,IAAIoC,EAAQ,EACZ,GAAIvC,EAAO,CACT,GAAyD,IAArDJ,EAAgB,GAAGwC,KAAOpC,KAAUqC,EAAMvC,GAC5C,MAAO,GAAGsC,KAAOpC,KAGnB,GAA2D,IAAvDJ,EAAgB,IAAIwC,MAAQpC,KAAUqC,EAAMvC,GAC9C,MAAO,IAAIsC,MAAQpC,IAEvB,CAEA,MAAMwC,EAAQF,EAAMlC,SAASgC,EAAKtC,EAAO,KAAMO,YAAYoC,SAAU,MACrE,IAAI7B,EACJ,KAAQA,EAAQ4B,EAAM1B,eAEpB,GADAyB,IACI3B,EAAM8B,WAAWL,GACnB,OAAyD,IAArDzC,EAAgB,GAAGwC,KAAOG,KAAUF,EAAMvC,GACrC,GAAGsC,KAAOG,KAEwC,IAAvD3C,EAAgB,IAAIwC,MAAQG,KAAUF,EAAMvC,GACvC,IAAIsC,MAAQG,UAErB,CAGN,CAAE,MAAOvB,GACPC,QAAQ0B,IAAI3B,EACd,GAQI4B,EAA8BC,IAElCA,GADAA,EANoB,CAACA,IACrBA,IAAMA,EAAEtB,MAAM,MAAM,GAAGC,OAAS,EAAIqB,EAAEtB,MAAM,MAAM,GAAKsB,EAAEtB,MAAM,MAAM,GAC9DsB,GAIHC,CAAcD,IAEftB,MAAM,oBACNwB,OAAO,CAACC,EAAGC,IACHD,EAAExB,OAASyB,EAAEzB,OAASwB,EAAIC,EAChC,IACFC,QACW3B,MAAM,KAAK,GAAG2B,OAGjBC,EAAsBhE,GAC7BA,EACKA,EAAIiE,QAAQ,SAAU,KAAKF,OAG7B/D,EAGIkE,EAAiBC,IAC5B,IAAKA,IAAOA,GAAIC,YAAa,OAAO,KAEpC,MAAMC,EAAOF,EAAGC,cAChB,OAAOC,GAAQA,GAAMC,KAAQD,EAA8B,MAGhDE,EAAyB,CACpCC,EAIArE,EACAsE,KAGA,IAAKD,GAAWE,OAAqC,kBAArBF,GAAWE,MACzC,OAAO,EAGT,GADsB,CAAC,OAAQ,QAAS,KAAM,MAAO,cACnCC,KAAMC,GAAMA,IAAMJ,EAAUE,OAC5C,OAAO,EAGT,GADqB,CAAC,OAAQ,QAAS,uBAAwB,SAC9CC,KAAMC,GAAMA,IAAMJ,EAAUK,MAC3C,OAAO,EAGT,MAAMC,EAAahF,GAA2BiF,KAC3CH,GACCA,EAAEI,MAAQ7E,EAAca,eACxB4D,EAAEtE,UAAYH,GACdyE,EAAEK,gBAAkBT,EAAUK,MAElC,OAAIC,MAImC,IAAnCN,GAAWK,MAAM5C,QAAQ,OAAeuC,GAAWK,MAAMxC,OAAS,KAIvC,mBAApBmC,EAAUE,SAIjBD,IAAY1E,EAAcyE,EAAUE,WAuB7BQ,EAAS5E,GACbA,aAAmB6E,WAGfC,EAAyBpF,GAC/BA,EAEEA,EAAIiE,QAAQ,2BAA4B,YAF9BjE,EAKbwB,EAAsB,CAACd,EAAeC,EAAa0E,GAAQ,KAC/D,IAAIC,EAAoB3E,EAGpBA,EAAMI,WAAawE,KAAKC,yBAC1BF,EAAe3E,EAAqB2D,MAAQ3D,GAG9C,MAAMwC,EACJmC,EAAYvE,WAAawE,KAAKE,cACzBH,EACDA,EAAYtE,cAElB,OAAIqE,EACKlC,EAAMlC,SAASP,EAAO4E,EAAa,KAAMpE,YAAYoC,SAAU,MAGjEH,EAAMlC,SACXP,EACA4E,EACA,KACApE,YAAYwE,wBACZ,MACAC,iBAGSC,EAAmB,CAC9BtF,EACAK,EACAkF,EACAnB,EACAoB,EACArB,KAEA,GAAIC,EAAO,CACT,MAAMqB,QAAEA,GAAYzF,EACpB,IAAIO,EACAmF,EAAiB,GACrB,MAAMC,EAAe,GACrB,IAAIC,EAEJ,GAAIxB,KAAWD,IAAa1E,EAAc2E,MAUtCwB,EATGzG,EAAaQ,KAAKyE,GASX,KAAKqB,KAAWF,KAAQ9D,EAAiB2C,MA/U/B,EAC1BwB,EACAhB,EACAa,IAEOb,EACH,qBAAqBa,UAAgBG,KACrC,KAAKH,KAAWG,KAgUJC,CACR,mBAAmBN,MAAS9D,EAC1BiC,EAAmBU,IACnBX,SACFmB,EAAM5E,GACNA,EAAQyF,QAAQK,eAMpBvF,EAAQJ,EAAgByF,EAAS5F,EAASK,GAE5B,IAAVE,IAAgBiF,GAClB,OAAOI,EAIX,GAAIxB,GAASD,EAAU,CACrB,MAAM4B,EAAY3B,EAAMtC,MAAM,KAC9B,GAAIiE,GAAWhE,OACb,GAAyB,IAArBgE,EAAUhE,OAAc,CAC1B,MAAMiE,EAAa,IAAI,IAAIC,IAAIF,EAAU,GAAGG,MAAM,gBAwClD,GAvCIF,GAAYjE,QAAU,GAEtBiE,EAAW,IACXtC,EAAmBsC,EAAW,GAAGvC,SAAS1B,OAAS,GAE/CqC,EAAM5B,WAAWwD,EAAW,MAM5BN,EALGvG,EAAaQ,KAAKqG,EAAW,IAKf,eAAeT,KAAQ9D,EACtCuE,EAAW,IACXvC,UANe,eAAe8B,KAAQ9D,EACtCiC,EAAmBsC,EAAW,KAC9BvC,WAUNuC,GAAYjE,OAAS,GAErBiE,EAAWA,EAAWjE,OAAS,IAC/B2B,EAAmBsC,EAAWA,EAAWjE,OAAS,GAAG0B,SACjD1B,OAAS,GAETqC,EAAM3B,SAASuD,EAAWA,EAAWjE,OAAS,MAM9C2D,EALGvG,EAAaQ,KAAKqG,EAAWA,EAAWjE,OAAS,IAKnC,aAAawD,KAAQ9D,EACpCuE,EAAWA,EAAWjE,OAAS,IAC/B0B,UANe,aAAa8B,KAAQ9D,EACpCiC,EAAmBsC,EAAWA,EAAWjE,OAAS,KAClD0B,WAUNiC,GAAgB3D,SAEhB6D,EADEhB,EAAM5E,GACE,qBAAqByF,UAAgBC,KAErC,KAAKD,KAAWC,KAE5BnF,EAAQJ,EAAgByF,EAAS5F,EAASK,GAC5B,IAAVE,IAAgBiF,GAClB,OAAOI,CAGb,KAAO,CACL,MAAMO,EACJJ,EAAUhE,OAAS,GAAM,EACrBgE,EAAUhE,OAAS,EACnBgE,EAAUhE,OAAS,EACnBqE,EAAmBL,EAAUxD,MAAM,EAAG4D,GAAUE,KAAK,KAC3D,IAAIL,EAAa,IAAI,IAAIC,IAAIG,EAAiBF,MAAM,gBAoBpD,GAnBIF,GAAYjE,QAEZiE,EAAW,IACXtC,EAAmBsC,EAAW,GAAGvC,SAAS1B,QAEtCqC,EAAM5B,WAAWwD,EAAW,MAM5BN,EALGvG,EAAaQ,KAAKqG,EAAW,IAKf,eAAeT,KAAQ9D,EACtCuE,EAAW,IACXvC,UANe,eAAe8B,KAAQ9D,EACtCiC,EAAmBsC,EAAW,KAC9BvC,WAUNiC,GAAgB3D,SAEhB6D,EADEhB,EAAM5E,GACE,qBAAqByF,UAAgBC,KAErC,KAAKD,KAAWC,KAE5BnF,EAAQJ,EAAgByF,EAAS5F,EAASK,GAC5B,IAAVE,IAAgBiF,GAClB,OAAOI,EAIX,MAAMU,EAAiBP,EACpBxD,MAAM4D,EAAUJ,EAAUhE,OAAS,GACnCsE,KAAK,KAqBR,GApBAL,EAAa,IAAI,IAAIC,IAAIK,EAAeJ,MAAM,gBAC1CF,GAAYjE,QAEZiE,EAAW,IACXtC,EAAmBsC,EAAW,GAAGvC,SAAS1B,OAAS,GAE/CqC,EAAM3B,SAASuD,EAAW,MAM1BN,EALGvG,EAAaQ,KAAKqG,EAAW,IAKf,aAAaT,KAAQ9D,EACpCuE,EAAW,IACXvC,UANe,aAAa8B,KAAQ9D,EACpCiC,EAAmBsC,EAAW,KAC9BvC,WAUNiC,GAAgB3D,SAEhB6D,EADEhB,EAAM5E,GACE,qBAAqByF,UAAgBC,KAErC,KAAKD,KAAWC,KAE5BnF,EAAQJ,EAAgByF,EAAS5F,EAASK,GAC5B,IAAVE,IAAgBiF,GAClB,OAAOI,CAGb,CAEJ,CAEA,GAAIxB,GAASD,GAAY1E,EAAc2E,GAAQ,CAC7C,MAAM4B,EAAa,IAAI,IAAIC,IAAI7B,EAAM8B,MAAM,gBAC3C,GAAIF,GAAYjE,OACd,IAAK,IAAIK,EAAI,EAAGA,EAAI4D,GAAYjE,OAAQK,IAEpC4D,EAAW5D,IACXsB,EAAmBsC,EAAW5D,GAAGqB,SAAS1B,OAAS,IAE9C5C,EAAaQ,KAAKqG,EAAW5D,IAOhCuD,EAAa1D,KACX,YAAYsD,KAAQ9D,EAClBuE,EAAW5D,GAAGqB,QACdA,WATJkC,EAAa1D,KACX,YAAYsD,KAAQ9D,EAClBiC,EAAmBsC,EAAW5D,KAC9BqB,YAaZ,GAAIkC,GAAc5D,SAEd6D,EADEhB,EAAM5E,GACE,qBAAqByF,UAAgBE,EAAaU,KAC1D,YAGQ,KAAKZ,KAAWE,EAAaU,KAAK,YAE9C9F,EAAQJ,EAAgByF,EAAS5F,EAASK,GAC5B,IAAVE,IAAgBiF,GAClB,OAAOI,CAGb,CASA,GANEA,EADEhB,EAAM5E,GACE,qBAAqByF,iBAErB,KAAKA,YAGjBlF,EAAQJ,EAAgByF,EAAS5F,EAASK,GAC5B,IAAVE,IAAgBiF,EAClB,OAAOI,CAEX,GAGWW,EAAmB,CAC9BC,EACAnG,KAEA,IACE,IAAKmG,EACH,MAAO,GAGT,IAAIC,EAAS7B,EAAM4B,GACf,oBAAoBA,EAAQf,YAC5B,IAAIe,EAAQf,UAGhB,GAAIe,EAAQE,cAAe,CAEzB,MAAMzG,EAAac,MAAM4F,UAAUpE,MAChCqE,KAAKJ,EAAQE,cAAcG,SAAU,GACrCC,OACEC,GAA2BA,EAAUtB,UAAYe,EAAQf,SAI9D,GAAIxF,EAAW8B,OAAS,EAAG,CAEzB0E,GAAU,IADIxG,EAAW0B,QAAQ6E,GACX,IACxB,CACF,MAAO,GAAIA,aAAmBQ,aACxBR,EAAQS,aAAc,CACxB,MAAMhH,EAAac,MAAM4F,UAAUpE,MAChCqE,KAAKJ,EAAQS,aAAaJ,SAAU,GACpCC,OACEC,GAA2BA,EAAUtB,UAAYe,EAAQf,SAI9D,GAAIxF,EAAW8B,OAAS,EAAG,CAEzB0E,GAAU,IADIxG,EAAW0B,QAAQ6E,GACX,IACxB,CACF,CAIF,OAAOD,EAAiBC,GAASE,cAAerG,GAASoG,CAC3D,CAAE,MAAOlF,GAIP,OAFAC,QAAQ0B,IAAI,QAAS3B,GAEd,EACT,GAGW2F,EAAmB,CAC9BV,EACAnG,EACAmF,EACArB,GAAoB,EACpBgD,KAEA,IAGE,GAAI7H,EAAmB8H,IAAIZ,GACzB,OAAOlH,EAAmB+H,IAAIb,GAIhC,MAAMc,EAAa,GACnB,IAAIC,EAAcf,EAGlB,KAAOe,GAAa,CAClB,IAAId,EAA6B,GAC7Be,GAAgB,EAChBC,EACFjB,IAAYe,EACPJ,GAAmBI,EAAYE,WAChCF,EAAYE,WAGlB,IAAK,MAAMC,KAAY3G,MAAM4G,KAAKF,GAChC,GAAIxD,EAAuByD,EAAUH,EAAapD,GAAW,CAC3D,IAAIyD,EAAYF,EAASxH,UAGzB0H,EAAYA,GAAWjE,QAAQ,iBAAkB,KAAO,GAExD,MAAMkE,EAAcH,EAASnD,KAG7BkC,EAASqB,EAAeP,EAAaM,EAAaD,GAElD,IAAIG,EAAyB,EAC7B,GAAItB,IACFsB,EAAiB5H,EAAgBsG,EAAQc,EAAalH,GAC/B,IAAnB0H,GAAsB,CACxBT,EAAWU,QAAQlD,EAAsB2B,IACzCe,GAAgB,EAChB,KACF,CAGF,GAAIO,EAAiB,GAAKvC,IACxBiB,EAAS/D,EACP+D,EACAc,EACAlH,EACA0H,GAEEtB,GAAQ,CACVa,EAAWU,QAAQlD,EAAsB2B,IACzCe,GAAgB,EAChB,KACF,CAGJ,CAGF,GAAID,EAAYzH,YACd,IACGqE,GACAA,IAAa1E,EAAc8H,EAAYzH,aACxC,CAcE2G,EAbiB,IAAIwB,OAAO,sBAEZtI,KAAK4H,EAAYzH,aAWxB8E,EAAM2C,GACX,qBAAqBA,EAAY9B,kBACxBhE,EAAiB1B,EAAgBwH,OAC1C,KAAKA,EAAY9B,SAAW,SAAShE,EACrC1B,EAAgBwH,OAdX3C,EAAM2C,GACX,qBAAqBA,EAAY9B,mCACPhE,EAC1B1B,EAAgBwH,OAEhB,KAAKA,EAAY9B,SAAW,0BACPhE,EACrB1B,EAAgBwH,OAWtB,IAAIQ,EAAiB5H,EAAgBsG,EAAQc,EAAalH,GAC1D,GAAuB,IAAnB0H,EACF,OAAOtB,EAGT,GAAIsB,EAAiB,GAAKvC,EAOxB,OANAiB,EAAS/D,EACP+D,EACAc,EACAlH,EACA0H,GAEKtB,CAEX,KAAO,CACL,IAAIf,EAA2B,GAC/B,MAAMM,EAAa,IACd,IAAIC,IAAIlG,EAAgBwH,GAAarB,MAAM,gBAEhD,IAAI/G,EAAe,IAAI8I,OAAO,sBAC9B,GAAIjC,GAAYjE,OACd,IAAK,IAAIK,EAAI,EAAGA,EAAI4D,GAAYjE,OAAQK,IAEpC4D,EAAW5D,IACXsB,EAAoBsC,EAAW5D,GAAcqB,UAExCtE,EAAaQ,KAAKqG,EAAW5D,IAOhCsD,EAAezD,KACb,cAAcR,EACXuE,EAAW5D,GAAcqB,QAC1BA,WATJiC,EAAezD,KACb,cAAcR,EACZiC,EAAmBsC,EAAW5D,KAC9BqB,YAaZ,GAAIiC,GAAgB3D,OAAQ,CAC1B0E,EAAS7B,EAAM2C,GACX,qBAAqBA,EAAY9B,gBAC1BC,EAAeW,KAAK,YAC3B,KAAKkB,EAAY9B,SAAW,OAAOC,EAAeW,KAClD,YAEJ,IAAI0B,EAAiB5H,EAAgBsG,EAAQc,EAAalH,GAC1D,GAAuB,IAAnB0H,EACF,OAAOtB,EAGT,GAAIsB,EAAiB,GAAKvC,EAOxB,OANAiB,EAAS/D,EACP+D,EACAc,EACAlH,EACA0H,GAEKtB,CAEX,CACF,CAIF,GAAKe,EAqBH,MArBkB,CAClB,IAAIU,EAAgBtD,EAAM2C,GACtB,oBAAoBA,EAAY9B,YAChC,IAAI8B,EAAY9B,UAGpB,GAAI8B,EAAYb,cAAe,CAC7B,MAAMyB,EAAWpH,MAAM4G,KACrBJ,EAAYb,cAAcG,UAC1BC,OAAQC,GAAcA,EAAUtB,UAAY8B,EAAY9B,SAG1D,GAAI0C,EAASpG,OAAS,EAAG,CAEvBmG,GAAiB,IADHC,EAASxG,QAAQ4F,GACF,IAC/B,CACF,CAGAD,EAAWU,QAAQE,EACrB,CAKAX,EAAcA,EAAYb,aAC5B,CAGA,MAAM0B,EAAa,GAAGd,EAAWjB,KAAK,MAItC,OADA/G,EAAmB+I,IAAI7B,EAAS4B,GACzBA,CACT,CAAE,MAAO7G,GAEP,OADAC,QAAQ0B,IAAI3B,GACL,IACT,GAGW+G,EAAsB,CACjCpE,EACAsC,KAEA,MAAMd,EAAiB,GACvB,IAAIE,EAAkB,GAEtB,GACE1B,IACCzE,EAAcyE,EAAUE,QACM,mBAAxBF,EAAUhE,UAIjB,CACA,MAAM8F,EAAa,IAAI,IAAIC,IAAI/B,EAAUE,MAAM8B,MAAM,gBACrD,GAAIF,GAAYjE,OACd,IAAK,IAAIK,EAAI,EAAGA,EAAI4D,GAAYjE,OAAQK,IAEpC4D,EAAW5D,IACXsB,EAAmBsC,EAAW5D,GAAGqB,SAAS1B,OAAS,IAE9C5C,EAAaQ,KAAKqG,EAAW5D,IAOhCsD,EAAezD,KACb,aAAaiC,EAAUK,QAAQ9C,EAC7BuE,EAAW5D,GAAGqB,YARlBiC,EAAezD,KACb,aAAaiC,EAAUK,QAAQ9C,EAC7BiC,EAAmBsC,EAAW5D,KAC9BqB,YAaZ,GAAIiC,GAAgB3D,OAMlB,OALA6D,EAAUhB,EAAM4B,GACZ,qBAAqBA,EAAQf,gBAAgBC,EAAeW,KAC5D,YAEA,KAAKG,EAAQf,WAAWC,EAAeW,KAAK,YACzCT,CAEX,GAGW2C,EAA+B,CAC1C/B,EACAnG,EACAmI,EACArE,KAEA,IACE,MAAMsE,EAAkB,GAExB,GAAID,EAAiBzG,OAAS,EAC5B,IAAK,MAAM2F,KAAYc,EACrB,GAAIvE,EAAuByD,EAAUlB,EAASrC,GAAW,CACvD,MAAMyD,EAAYF,EAASxH,UAEtBf,EAAaQ,KAAKiI,GAIU,UAAtBF,EAASgB,SAClBD,EAAgBxG,KACd,aAAayF,EAASgB,aAAad,OAGrCa,EAAgBxG,KAAK,IAAIyF,EAASgB,aAAad,MAR/Ca,EAAgBxG,KACd,oBAAoByF,EAASgB,cAAcd,MAU/C,MAAMnB,EAAS7B,EAAM4B,GACjB,qBAAqBA,EAAQf,gBAAgBgD,EAAgBpC,KAC7D,YAEA,KAAKG,EAAQf,WAAWgD,EAAgBpC,KAAK,YACjD,IAAI0B,EAGJ,IACEA,EAAiB5H,EAAgBsG,EAAQD,EAASnG,EACpD,CAAE,MAAOsI,GACP,QACF,CAEA,GAAuB,IAAnBZ,IAAyBtB,EAAOnF,SAAS,OAC3C,MAAO,GAGT,GAAuB,IAAnByG,GAAwBtB,EAAOnF,SAAS,OAC1C,OAAOmF,CAEX,CAGN,CAAE,MAAOlF,GAEPC,QAAQ0B,IAAI,IAAI0F,KAAKC,UAAUtH,EAAO,KAAM,MAC9C,GAGWuH,EAAwB,CACnCC,EACAC,EACA7E,KAEA,IAAI8E,EAAerE,EAAMmE,GACrBG,EAAqB,GAEzB,GAAIjF,EAAuB+E,EAAMD,EAAa5E,GAAW,CACvD,IAAIyD,EAAYoB,EAAK5E,MACrBwD,EAAYA,EAAUjE,QAAQ,iBAAkB,IAChD,MAAMkE,EAAcmB,EAAKzE,KAWvB2E,EATG/J,EAAaQ,KAAKiI,GASRqB,EACT,mBAAmBF,EAAYtD,iBACvBoC,KAAepG,EAAiBmG,MACxC,GAAGmB,EAAYtD,SAAW,QAAQoC,KAAepG,EACjDmG,MAZSqB,EACT,mBAAmBF,EAAYtD,iCACPoC,MAAgBpG,EACxCmG,MAEA,GAAGmB,EAAYtD,SAAW,wBACPoC,MAAgBpG,EAAiBmG,KAS5D,CAEA,OAAOsB,GAGIC,EAAuB,CAClCvG,EACAvC,KAEA,IAAKuC,EAAK9C,YAAa,MAAO,GAE9B,MAAMsJ,EAAerJ,EAAgB6C,GAErC,IAAI6D,EAiBJ,OAPEA,EARGtH,EAAaQ,KAAKyJ,GAQZxE,EAAMhC,GACX,qBAAqBA,EAAK6C,kBAAkBhE,EAC5C2H,MAEA,KAAKxG,EAAK6C,SAAW,SAAShE,EAAiB2H,MAX1CxE,EAAMhC,GACX,qBAAqBA,EAAK6C,mCACAhE,EAAiB2H,MAC3C,KAAKxG,EAAK6C,SAAW,0BAA0BhE,EAC/C2H,MAUC3C,GAGI4C,EACX7C,IAEA,MAAM8C,EAAc1J,EAAe4G,IAAU/C,OACvC2F,EAAeE,EACjB7H,EAAiB0B,EAA2BmG,IAC5CA,EACJ,GAAIF,EACF,OAAIA,IAAiB,IAAIE,KAChB,cAAcF,KAEhB,uBAAuBE,MAIrBxB,EAAiB,CAC5BlF,EACA8E,EACAE,KAEA,MAAMzI,EAAe,IAAI8I,OAAO,sBAChC,IAAIxB,EAAiB,GA2BrB,OAzBImB,IASAnB,EARGtH,EAAaQ,KAAKiI,GAOC,UAAbF,EACA9C,EAAMhC,GACX,qBAAqBA,EAAK6C,0BACTiC,KAAYjG,EAAiBmG,OAC9C,KAAKhF,EAAK6C,SAAW,iBAAiBiC,KAAYjG,EAClDmG,OAGKhD,EAAMhC,GACX,qBAAqBA,EAAK6C,iBAClBiC,KAAYjG,EAAiBmG,MACrC,KAAKhF,EAAK6C,SAAW,QAAQiC,KAAYjG,EACzCmG,MAlBKhD,EAAMhC,GACX,qBAAqBA,EAAK6C,0BACTiC,KAAYjG,EAAiBmG,OAC9C,KAAKhF,EAAK6C,SAAW,iBAAiBiC,KAAYjG,EAClDmG,QAmBDnB,GAGI8C,EAA0B,CACrC7J,EACAM,IAEIN,EACKA,EAAIiE,QAAQ,iBAAkB,eAEhCjE,EA8BI8J,EAA4B,CACvChD,EACAnG,EACA8D,KAEA,IAAIsF,EACJ,MAAMC,EAAU,GA0BhB,GAxBElD,EAAQ1G,eACNqE,GAAaA,IAAa1E,EAAc+G,EAAQ1G,gBAE7CX,EAAaQ,KAAK6G,EAAQ1G,cAU7B2J,EAAa7E,EAAM4B,GACf,mBAAmBA,EAAQf,kBAAkBhE,EAC7C7B,EAAe4G,OAEf,GAAGA,EAAQf,aAAahE,EAAiB7B,EAAe4G,OACxDiD,GACFC,EAAQzH,KAAK,CAAE0H,IAAK,4BAA6BvF,MAAOqF,MAf1DA,EAAa7E,EAAM4B,GACf,mBAAmBA,EAAQf,gBAAgB4D,EAC3C7C,OAEA,GAAGA,EAAQf,WAAW4D,EAAqB7C,MAC3CiD,GACFC,EAAQzH,KAAK,CAAE0H,IAAK,4BAA6BvF,MAAOqF,MAc1DjD,EAAQiB,WACV,IAAK,MAAMC,KAAY3G,MAAM4G,KAAKnB,EAAQiB,YACxC,GAAIxD,EAAuByD,EAAUlB,EAASrC,GAAW,CACvD,IAAIyD,EAAYF,EAASxH,UACzB,GAAI0H,EAAW,CACbA,EAAYA,EAAUjE,QAAQ,iBAAkB,IAChD,MAAMkE,EAAcH,EAASnD,KAG3BkF,EADkB,UAAhB5B,EACWjD,EAAM4B,GACf,mBAAmBA,EAAQf,0BACVoC,KAAepG,EAChCmG,OAEA,GAAGpB,EAAQf,qBAAqBoC,KAAepG,EAC/CmG,OAGShD,EAAM4B,GACf,mBAAmBA,EAAQf,iBACnBoC,KAAepG,EAAiBmG,MACxC,GAAGpB,EAAQf,YAAYoC,KAAepG,EACtCmG,MAIF6B,GACFC,EAAQzH,KAAK,CACX0H,IAAK,4BACLvF,MAAOqF,GAGb,CACF,CAIJ,IAAKC,GAAS3H,OAAQ,CACpB,MAAMoF,EAAkBpG,MAAM4F,UAAUpE,MAAMqE,KAAKJ,EAAQiB,YAC3D,GAAIN,GAAiBpF,OAAS,EAAG,CAC/B,MAAM6H,EAAmBrB,EACvB/B,EACAnG,EACAU,MAAM4F,UAAUpE,MAAMqE,KAAKJ,EAAQiB,YACnCtD,GAEEyF,GACFF,EAAQzH,KAAK,CACX0H,IAAK,4BACLvF,MAAOwF,GAGb,CACF,CAEA,IAAKF,GAAS3H,OAAQ,CACpB,MAAM2D,EAAiB,GACvB,IAAIE,EACJ,MAAMiE,EAAMjF,EAAM4B,GAClB,GAAIA,EAAQ1G,aAAeqE,GAAY1E,EAAc+G,EAAQ1G,aAAc,CACzE,MAAMkG,EAAa,IAAI,IAAIC,IAAIO,EAAQ1G,YAAYoG,MAAM,gBACzD,GAAIF,GAAYjE,OACd,IAAK,IAAIK,EAAI,EAAGA,EAAI4D,GAAYjE,OAAQK,IAEpC4D,EAAW5D,IACXsB,EAAmBsC,EAAW5D,GAAGqB,SAAS1B,OAAS,IAE9C5C,EAAaQ,KAAKqG,EAAW5D,IAOhCsD,EAAezD,KACb,cAAcR,EAAiBuE,EAAW5D,IAAIqB,WAPhDiC,EAAezD,KACb,cAAcR,EACZiC,EAAmBsC,EAAW5D,KAC9BqB,YAWRiC,GAAgB3D,SAEhB6D,EADEiE,EACQ,qBAAqBA,UAAYnE,EAAeW,KACxD,YAGQ,KAAKwD,KAAOnE,EAAeW,KAAK,YAGxCT,GACF8D,EAAQzH,KAAK,CAAE0H,IAAK,4BAA6BvF,MAAOwB,IAE9D,CACF,CAEA,IAAK8D,GAAS3H,OAAQ,CACpB,MAAM+H,EA7J6B,EACrCrC,EACAsB,EACA1I,EACA8D,KAEA,MAAMgD,EAAkBpG,MAAM4F,UAAUpE,MAAMqE,KAAKa,GAC7CqC,EAA2C,GACjD,IACE3C,EAAgB4C,IAAK/J,IACnB,GAAIiE,EAAuBjE,EAAS+I,EAAa5E,GAAW,CAC1D,MAAM6F,EAAO1B,EAAoBtI,EAAS+I,GACtCiB,GACFF,EAAO7H,KAAK,CACV0H,IAAK,kBAAkB3J,EAAQuE,OAC/BH,MAAO4F,GAGb,GAEJ,CAAE,MAAOzI,GACPC,QAAQ0B,IAAI3B,EACd,CAEA,OAAOuI,GAqIUG,CACbzD,EAAQiB,WACRjB,EACAnG,EACA8D,GAEE2F,GAAQ/H,QACV2H,EAAQQ,OAAOJ,EAEnB,CAEA,OAAOJ,GAcIS,EAAkB/J,GAQ7BA,GANAA,EAAQA,EAAMuD,QACZ,gCACA,8BAIYA,QAAQ,0BAA2B,6BAKtCyG,EAA0B,CACrC1I,EACA2I,KAEA,IAAIC,EAAWD,EACXE,EAAU,EACd,KAAOA,EAAU,GAAG,CAClB,MAAM/G,EAAI9B,IAAO4I,GACR,KAAL9G,EACF+G,IACc,KAAL/G,GACT+G,GAEJ,CACA,OAAOD,GAkCH,SAAUE,EAAgBpK,GAC9B,MAAMqK,EAhCF,SAA4BrK,GAChC,OACEA,EACG0F,cAEAnC,QAAQ,WAAY,KACpBA,QAAQ,WAAY,KAEpBA,QAAQ,WAAY,OAEpBA,QAAQ,mBAAoB,UAC5BA,QAAQ,iBAAkB,QAEjC,CAmBoB+G,CAAkBtK,GAC9BuK,EAlBF,SAAqCvK,GACzC,MAAMwK,EAAKxK,EAAM0F,cAEX+E,EAAYD,EAAG1E,MACnB,yIAEI4E,EAAOD,IAAY,IAAM,OAEzBE,EAAYH,EAAG1E,MAAM,kBAK3B,MAAO,CAAE4E,OAAM5G,UAJG6G,IAAY,IAAM,OAIVC,cAFJJ,EAAGtJ,SAAS,mBAGpC,CAIgB2J,CAA2B7K,GAEzC,MAAO,CACL,QACA,QAAQuK,EAAMG,OACd,QAAQH,EAAMzG,YACd,aAAayG,EAAMK,gBACnB,SAASP,KACTpE,KAAK,IACT,CAEM,SAAU6E,EAAgB9G,GAC9B,OAAOA,EAAMT,QAAQ,MAAO,QAAQA,QAAQ,KAAM,OAAOA,QAAQ,KAAM,MACzE,CAQM,SAAUwH,EACd9K,EACAkE,EACAH,EACApE,GAEA,MAAM+D,EAAQ/D,GAAS8D,iBAAyCzD,EAC1D+K,EAAYC,IAChB,IACE,OAAOtK,MAAM4G,KAAK5D,EAAKuH,iBAAiBD,GAC1C,CAAE,MACA,MAAO,EACT,GAGF,IACE,OAAQ9G,GACN,IAAK,KACH,OAAyD,IAAlD6G,EAAS,IAAIF,EAAgB9G,MAAUrC,OAEhD,IAAK,OACH,OAAiE,IAA1DqJ,EAAS,UAAUF,EAAgB9G,QAAYrC,OAExD,IAAK,YACH,OAAwC,IAAjCqJ,EAAS,IAAIhH,KAASrC,OAE/B,IAAK,UAeL,IAAK,cACH,OAAkC,IAA3BqJ,EAAShH,GAAOrC,OAbzB,IAAK,WACH,OAGe,IAFbqJ,EAAS,KAAKtE,OACX1D,GAAMA,EAAEtD,aAAa2D,SAAWW,GACjCrC,OAEN,IAAK,kBACH,OAGe,IAFbqJ,EAAS,KAAKtE,OAAQ1D,GACpBA,EAAEtD,aAAawB,SAAS8C,IACxBrC,OAIN,QACE,OAAO,EAEb,CAAE,MACA,OAAO,CACT,CACF,CAEO,MAAMwJ,EAAa,CACxBC,SAnJsB,CACtBC,EACAC,IAEIC,OAAOC,WACF,IAAID,OAAOC,WAAYC,gBAAgBJ,EAAQC,GAGjD,KA4IPlC,4BACAjD,mBACAW,mBACAoB,sBACAC,+BACArH,sBACA0D,QACAlC,qBACAjD,gBACAG,iBACAO,kBACAgK,iBACAvG,gBACAnC,mBACAG,oBACAqC,yBACA6H,gBAjkC6B,CAAC1I,EAAgBG,KAC9C,IAAIwI,EAAM3I,EAAE4I,wBAAwBzI,GACpC,OAAe,IAARwI,EACH,YACQ,IAARA,EACE,YACQ,IAARA,EACE,WACQ,KAARA,EACE,aACQ,KAARA,EACE,OACA,IAsjCZ3B,0BACAjH,6BACA2B,wBACAmH,eA53C6BC,IAC7B7M,EAAmB,IAAI8M,iBAAkBC,IACvCA,EAAUC,QAASC,IACbA,GAAUC,YAAYxK,QACxBmK,EAAkBI,GAAUC,YAG1BD,EAASE,kBAAkBxF,cAER,eAAnBsF,GAAUZ,MACiB,UAA3BY,EAAS3H,gBACPC,EAAM0H,EAASE,SACfF,EAASG,UAAUhJ,SACnB6I,EAASE,OAAOE,UAAUtI,OAAOX,QAGnB,wBAFd6I,EAASE,OAAOE,WAAWtI,OACvBT,QAAQ2I,EAASG,SAAW,IAC7BhJ,QAGW,wBAFd6I,GAAUG,UACN9I,QAAQ2I,EAASE,OAAOE,WAAWtI,MAAO,IAC3CX,SAGc,eAAnB6I,GAAUZ,MACT,CAAC,eAAepK,SAASgL,EAAS3H,gBAEnCnF,EAA0ByC,KAAK,CAC7B0K,IAAKL,EAASE,OAAOI,QACrBjI,cAAe2H,EAAS3H,cACxB3E,QAASsM,EAASE,OAClB9H,IAAK4H,EAASE,OAAO9L,sBAg2C/BmM,cAz1C2B,CAC3BL,EACAM,KAEAzN,GAAkB0N,QAAQP,EAAQM,IAs1ClCE,aAn1C0B,KAC1B3N,GAAkB4N,wCAm1ClBzN,EACA0N,YA34C+B,EA44C/B1C,kBACAU,kBACAC,iBC73CF,IAAIgC,EAA8C,GAC9CC,EAAsE,GAEtEhO,EAAa,IAAIG,IACjB8N,EAAQ,IAAI9N,IAEhB,MAAM+N,EAAmB,IAAI/N,IAEvBgO,EAA6B,CACjC9D,EACA+D,EACAzE,EACA1I,EACAmF,EACAiI,KAEA,GAAIhE,EAAqC,CACvC,IAAIK,EAGFA,EADmB,WAAjB2D,EACO,CAEP,GAAGhE,yBAAkC+D,IACrC,GAAG/D,gBAAyB+D,KAGrB,CAEP,GAAG/D,uBAAgC+D,IACnC,GAAG/D,gBAAyB+D,KAKhC,IAAK,MAAMpN,KAAS0J,EAAQ,CAErB1K,GAAYiI,IAAIjH,IAEnBhB,EAAWiJ,IAAIjI,EAAOD,EAAgBC,EAAO2I,EAAa1I,IAG5D,MAAME,EAAQnB,GAAYiI,IAAIjH,GAG9B,GAAc,IAAVG,EACF,OAAOH,EAqBT,GAnBIG,EAAQ,IACN6M,EAAmBrL,OACjBxB,EAAQ6M,EAAmB,GAAG7M,QAChC6M,EAAmBM,MACnBN,EAAmBnL,KAAK,CACtB0H,IAAK,oCAAmCnE,EAAU,QAAU,IAC5DpB,MAAOhE,EACPG,WAIJ6M,EAAmBnL,KAAK,CACtB0H,IAAK,oCAAmCnE,EAAU,QAAU,IAC5DpB,MAAOhE,EACPG,WAKFA,EAAQ,GAAKiF,IAAY2H,EAAUpL,OAAQ,CAE7C,MAAM4L,EAAejL,EACnBtC,EACA2I,EACA1I,EACAE,GAKAoN,GACsD,IAAtDxN,EAAgBwN,EAAc5E,EAAa1I,IAE3C8M,EAAUlL,KAAK,CACb0H,IAAK,oCAAmCnE,EAAU,QAAU,IAC5DpB,MAAOuJ,GAGb,CACF,CACF,CACA,OAAO,MAGHC,EAAuB,CAC3BpH,EACAnG,EACAuC,EACAuB,EACA0J,EACArI,KAEA,IACE,GAAI8H,EAAiBlG,IAAIZ,GACvB,OAAO8G,EAAiBjG,IAAIb,GAI9B,MAAMc,EAAa,GACnB,IAAIC,EAAcf,EAElB,KAAOe,GAAwC,IAAzBA,EAAY9G,UAAgB,CAChD,MAAM+G,GAAgB,EACtB,IAAK,MAAME,KAAY3G,MAAM4G,KAAKJ,EAAYE,YAC5C,GAAIxD,EAAuByD,EAAUH,EAAapD,GAAW,CAC3D,IAAIyD,EAAYF,EAASxH,UAEzB0H,EAAYA,GAAWjE,QAAQ,iBAAkB,KAAO,GACxD,MAAMkE,EAAcH,EAASnD,KACvBkC,EAASqB,EAAeP,EAAaM,EAAaD,GAExD,IAAIG,EAGJ,IACEA,EAAiBwF,EACf9G,EACAoH,EACAjL,EACAvC,EACAmF,EACA,SAEJ,CAAE,MAAOmD,GACP,QACF,CAGA,GAAIZ,EACF,OAAOA,CAEX,CAGF,GAAIR,EAAYzH,cAAgByH,EAAYzH,YAC1C,IACGqE,GACAA,IAAa1E,EAAc8H,EAAYzH,aACxC,CACA,IAAI2G,EAeFA,EAbGtH,EAAaQ,KAAK4H,EAAYzH,aAaxB8E,EAAM2C,GACX,qBACEA,EAAY9B,kBACHhE,EAAiB1B,EAAgBwH,OAC5C,KAAKA,EAAY9B,SAAW,SAAShE,EACnC1B,EAAgBwH,OAjBb3C,EAAM2C,GACX,qBACEA,EAAY9B,mCACchE,EAC1B1B,EAAgBwH,OAElB,KACEA,EAAY9B,SAAW,0BACFhE,EACrB1B,EAAgBwH,OAYxB,MAAMQ,EAAiBwF,EACrB9G,EACAoH,EACAjL,EACAvC,EACAmF,EACA,UAEF,GAAIuC,EACF,OAAOA,CAEX,KAAO,CACL,MAAMrC,EAAiB,GACjBM,EAAa,IACd,IAAIC,IAAIlG,EAAgBwH,GAAarB,MAAM,gBAE1C/G,EAAe,IAAI8I,OAAO,sBAChC,GAAIjC,GAAYjE,OACd,IAAK,IAAIK,EAAI,EAAGA,EAAI4D,GAAYjE,OAAQK,IAClC4D,EAAW5D,IAAMsB,EAAmBsC,EAAW5D,GAAGqB,UAC/CtE,EAAaQ,KAAKqG,EAAW5D,IAOhCsD,EAAezD,KACb,cAAcR,EACZuE,EAAW5D,GAAGqB,QACdA,WATJiC,EAAezD,KACb,cAAcR,EACZiC,EAAmBsC,EAAW5D,KAC9BqB,YAaZ,GAAIiC,GAAgB3D,OAAQ,CAC1B,MAAM0E,EAAS7B,EAAM2C,GACjB,qBACEA,EAAY9B,gBACLC,EAAeW,KAAK,YAC7B,KAAKkB,EAAY9B,SAAW,OAAOC,EAAeW,KAChD,YAEA0B,EAAiBwF,EACrB9G,EACAoH,EACAjL,EACAvC,EACAmF,EACA,UAEF,GAAIuC,EACF,OAAOA,CAEX,CACF,CAIF,IAAKP,EAAe,CAClB,MAAMf,EAAS7B,EAAM2C,GACjB,oBAAoBA,EAAY9B,YAChC,IAAI8B,EAAY9B,UAEpB6B,EAAWU,QAAQvB,EACrB,CAKAc,EAAcA,EAAYb,aAC5B,CAGA,MAAM0B,EAAad,EAAWjB,KAAK,IAAMwH,EAEzC,GAAc,IADF1N,EAAgBiI,EAAY5B,EAASnG,GAG/C,OADAiN,EAAiBjF,IAAI7B,EAAS4B,GACvBA,CAEX,CAAE,MAAO7G,GAEP,OADAC,QAAQD,MAAMA,GACP,IACT,GAGIuM,EAAyB,CAC7BtH,EACAnG,EACAuC,EACAuB,KAEA,MAAMkJ,EAAQ,IAAI9N,IAElB,GAAI8N,EAAMjG,IAAIZ,GACZ,OAAO6G,EAAMhG,IAAIb,GAGnB,MAAMc,EAAa,GACnB,IAAIC,EAAcf,EAElB,IACE,KAAOe,GAAwC,IAAzBA,EAAY9G,UAAgB,CAEhD,IAAK8G,EAAY9B,QACf,MAAO,GAIT,IAAIsI,GAAkB,EACtB,IAAK,MAAM/E,KAAQjI,MAAM4G,KAAKJ,EAAYE,YACxC,GAAIxD,EAAuB+E,EAAMzB,EAAapD,GAAW,CACvD,IAAIyD,EAAYoB,EAAK9I,UAErB0H,EAAYA,GAAWjE,QAAQ,iBAAkB,KAAO,GACxD,MAAMkE,EAAcmB,EAAKzE,KAEnBkC,EAASqB,EAAeP,EAAaM,EAAaD,GAExD,IAAIG,EAGJ,IACEA,EAAiB5H,EAAgBsG,EAAQc,EAAalH,EACxD,CAAE,MAAOsI,GACP,QACF,CAGA,GAAuB,IAAnBZ,EAAsB,CACxBT,EAAWU,QAAQvB,GACnBsH,GAAkB,EAClB,KACF,CACF,CAIF,IAAKA,GAAmBxG,EAAYzH,cAAgB8C,EAAK9C,YAAa,CACpE,MAAMkO,EAAY7E,EAAqB5B,GACvC,GAAIyG,EAAW,CAEb,GAAuB,IADA7N,EAAgB6N,EAAWzG,EAAalH,GACrC,CACxB0N,GAAkB,EAClBzG,EAAWU,QAAQgG,GACnB,KACF,CACF,CACF,CAEA,GAAKD,EASH,MAToB,CAEpB,MAAMtH,EAAS7B,EAAM2C,GACjB,oBAAoBA,EAAY9B,YAChC,IAAI8B,EAAY9B,UAGpB6B,EAAWU,QAAQvB,EACrB,CAIAc,EAAcA,EAAYb,aAC5B,CAGA,MAAMuH,EAAa3G,EAAWjB,KAAK,IAEnC,OADAgH,EAAMhF,IAAI7B,EAASyH,GACZA,CACT,CAAE,MAAO1M,GAEP,OADAC,QAAQ0B,IAAI3B,GACL,IACT,GAGI2M,EAAwB,CAC5B1H,EACAnG,EACAuC,KAEA,MAAM0E,EAAa,GACnB,IAAIC,EAEJ,MAAM4G,EAAK,GAEoB,MAA7B3H,EAAQ4H,mBACR5H,EAAQ4H,kBAAkB1B,UAAU2B,SAAS,cAE7CF,EAAGnG,QAAQxB,EAAQ4H,mBACoB,MAA9B5H,EAAQ8H,oBACjBH,EAAGnG,QAAQxB,EAAQ8H,oBAErB,IACE,IAAIC,EAAI/H,EAAQE,cACX,MAAL6H,GAA4B,IAAfA,EAAE9N,SACf8N,EAAIA,EAAE7H,cAEF6H,EAAED,oBAAoBH,EAAGnG,QAAQuG,EAAED,oBAGzC,IACE,EAAG,CACD,IAAIP,GAAkB,EACtB,IAAKxG,EAAc4G,EAAGT,MAAwB,OAAhBnG,GAAwB,CACpD,IAAK,MAAMyB,KAAQjI,MAAM4G,KAAKJ,EAAYE,YACxC,GAAIxD,EAAuB+E,EAAMzB,GAAa,GAAO,CACnD,IAAIK,EAAYoB,EAAK9I,UAErB0H,EAAYA,GAAWjE,QAAQ,iBAAkB,KAAO,GACxD,MAAMkE,EAAcmB,EAAKzE,KAEnBkC,EAASqB,EAAeP,EAAaM,EAAaD,GAExD,IAAIG,EAGJ,IACEA,EAAiB5H,EAAgBsG,EAAQc,EAAalH,EACxD,CAAE,MAAOsI,GACP,QACF,CAGA,GAAuB,IAAnBZ,EAAsB,CACxBgG,GAAkB,EAClBzG,EAAWrF,KAAKwE,GAChB,KACF,CACF,CAIF,IAAKsH,GAAmBxG,EAAYzH,cAAgB8C,EAAK9C,YAAa,CACpE,MAAMkO,EAAY7E,EAAqB5B,GACvC,GAAIyG,EAAW,CAMb,GAAuB,IALA7N,EACrB6N,EACAzG,EACAlH,GAEwB,CACxB0N,GAAkB,EAClBzG,EAAWrF,KAAK+L,GAChB,KACF,CACF,CACF,CAEA,GAAKD,EAgBH,MAhBoB,CAEpB,MAAMtH,EAAS7B,EAAM2C,GACjB,oBAAoBA,EAAY9B,YAChC,IAAI8B,EAAY9B,UAGpB6B,EAAWrF,KAAKwE,GAEqB,MAAjCc,EAAY6G,mBACdD,EAAGlM,KAAKsF,EAAY+G,oBACpB/G,EAAcA,EAAY6G,mBAE1B7G,EAAcA,EAAY+G,kBAE9B,CAGF,CACF,OAASH,EAAGpM,OAAS,GAGrB,MAAMkM,EAAa3G,EAAWjB,KAAK,IAEnC,OADAgH,EAAMhF,IAAI7B,EAASyH,GACZA,CACT,CAAE,MAAO1M,GAEP,OADAC,QAAQ0B,IAAI3B,GACL,IACT,GAGIiN,EAA0B,CAC9BhI,EACAnG,EACA8D,EACA0J,KAEA,IACE,MAAMY,EAAaC,SAASC,cAAc,eAE1C,IACE,IAAIJ,EAAI/H,EAAQ8H,mBACV,OAANC,GAAcA,IAAME,EACpBF,EAAIA,EAAED,mBAENM,EACEL,EACA/H,EACAnG,EACAwN,EACA,oBACA1J,GAIJ,IACE,IAAI0K,EAAIrI,EAAQsI,uBACV,OAAND,GAAcA,IAAMJ,EACpBI,EAAIA,EAAEC,uBAENF,EACEC,EACArI,EACAnG,EACAwN,EACA,oBACA1J,EAGN,CAAE,MAAO5C,GAEP,OADAC,QAAQD,MAAM,gBAAiBA,GACxB,IACT,GAGIqN,EAAiB,CACrBG,EACAvI,EACAnG,EACAwN,EACA/C,EACA3G,KAEA,IACE,GAAI4K,EAAQC,gBACV,IAAK,MAAMhG,KAAQjI,MAAM4G,KAAKoH,EAAQtH,YAAa,CACjD,IAAIhB,EAASqC,EACXiG,EACA,CACExK,KAAMyE,EAAKzE,KACXH,MAAO4E,EAAK5E,OAEdD,GAEF,GAAIsC,EAAQ,CACVA,GAAU,IAAIqE,MAAS+C,IAEvB,MAAMtN,EAAQJ,EAAgBsG,EAAQsI,EAAS1O,GAE/C,GAAc,IAAVE,EAKF,YAJA4M,EAAUlL,KAAK,CACb0H,IAAK,YAAYmB,IACjB1G,MAAOqC,IAGAlG,EAAQ,IACb6M,EAAmBrL,OACjBxB,EAAQ6M,EAAmB,GAAG7M,QAChC6M,EAAmBM,MACnBN,EAAmBnL,KAAK,CACtB0H,IAAK,qBAAqBmB,IAC1B1G,MAAOqC,EACPlG,WAIJ6M,EAAmBnL,KAAK,CACtB0H,IAAK,qBAAqBmB,IAC1B1G,MAAOqC,EACPlG,UAIR,CACF,CAGF,IAAK4D,EAAU,CACb,IAAIsC,EAUJ,GATAA,EAASqC,EACPiG,EACA,CACExK,KAAM,OACNH,MAAO2K,EAAQjP,aAEjBqE,GAGEsC,EAAQ,CACV,MAAMlG,EAAQJ,EAAgBsG,EAAQsI,EAAS1O,GAE/C,GAAc,IAAVE,EAKF,YAJA4M,EAAUlL,KAAK,CACb0H,IAAK,YAAYmB,IACjB1G,MAAOqC,IAGAlG,EAAQ,IACb6M,EAAmBrL,OACjBxB,EAAQ6M,EAAmB,GAAG7M,QAChC6M,EAAmBM,MACnBN,EAAmBnL,KAAK,CACtB0H,IAAK,qBAAqBmB,IAC1B1G,MAAOqC,EACPlG,WAIJ6M,EAAmBnL,KAAK,CACtB0H,IAAK,qBAAqBmB,IAC1B1G,MAAOqC,EACPlG,UAIR,CACF,CACF,CAAE,MAAOgB,GACPC,QAAQ0B,IAAI,GAAG4H,gBAAoBvJ,EACrC,GAGF,SAAS0N,EACPxH,EACAsB,EACA1I,EACA8D,GAEA,MAAMsB,QAAEA,GAAYsD,EACdjJ,EAAciJ,EAAYjJ,YAAY2D,OAC5C,IAAK,MAAMiE,KAAYD,EACrB,GAAIxD,EAAuByD,EAAUqB,EAAa5E,GAAW,CAC3D,IAAIyD,EAAYF,EAASxH,UAEzB0H,EAAYA,GAAWjE,QAAQ,iBAAkB,KAAO,GACxD,MACMvD,EAAQ,KAAKqF,MADCiC,EAASnD,SACkBqD,kBAA0B9H,MACzE,GAAIM,EAAO,CAET,GAAa,GADCD,EAAgBC,EAAO2I,EAAa1I,GAEhD,OAAOD,CAEX,CACF,CAEJ,CAEA,MAAM8O,EAAoB,CACxBnG,EACA1I,EACAmF,EACArB,EACAD,KAEA,IACE,IACIiL,EAAeC,EADfvB,EAAsB,GAK1B,GAHAV,EAAY,GAEZ3L,QAAQ0B,IAAIgB,GACRA,EACF,IAAK,MAAMwD,KAAYxD,EAAW,CAChC,IAAIgF,EAAaJ,EACfC,EACA,CACExE,KAAMmD,EAASnD,KACfH,MAAOsD,EAAStD,OAElBD,GAGF3C,QAAQ0B,IAAIgG,GACRA,GACF2E,EAAU5L,KAAKiH,EAEnB,CAGF,GAAIH,EAAYjJ,YAAa,CAC3B,IAAIoJ,EAAaJ,EACfC,EACA,CACExE,KAAM,OACNH,MAAO2E,EAAYjJ,aAErBqE,GAGF3C,QAAQ0B,IAAIgG,GACRA,GACF2E,EAAU5L,KAAKiH,EAEnB,CAIA,GAFA2E,EAAU5L,KAAK8G,EAAYtD,SAEvBoI,GAAW9L,OACb,IAAK,IAAIK,EAAI,EAAGA,EAAIyL,EAAU9L,OAAQK,IACpC,IAAK+K,EAAUpL,OAAQ,CAGrB,GAFAyM,EAAwBzF,EAAa1I,EAAO8D,EAAU0J,EAAUzL,KAE3D+K,EAAUpL,SACRoN,IACHA,EAAgBrB,EACd/E,EAAYrC,cACZrG,EACA0I,EACA5E,IAIJ3C,QAAQ0B,IAAIiM,GAGVA,IACCA,EAAc7N,SAAS,MACtB6N,EAAc7N,SAAS,WACvB6N,EAAc7N,SAAS,QACzB6N,EAAcjJ,MAAM,QAAQnE,OAAS,EAAI,GACzC,CACA,MAAMsN,EAAoBF,EAAgB,IAAItB,EAAUzL,KAClD7B,EAAQJ,EACZkP,EACAtG,EACA1I,GAGF,GAAc,IAAVE,EACF4M,EAAUlL,KAAK,CACb0H,IAAK,oCACLvF,MAAOiL,SAEJ,GAAI9O,EAAQ,GAAKiF,EAAS,CAC/B,MAAM8J,EAAqB5M,EACzB2M,EACAtG,EACA1I,EACAE,GAGA+O,GAC4D,IAA5DnP,EAAgBmP,EAAoBvG,EAAa1I,IAEjD8M,EAAUlL,KAAK,CACb0H,IAAK,uCACHnE,EAAU,QAAU,IAEtBpB,MAAOkL,GAGb,CACF,CAGF,IAAKnC,EAAUpL,SACRqN,IACHA,EAAqBlB,EACnBnF,EACA1I,EACA0I,IAKFqG,IACCA,EAAmB9N,SAAS,MAC3B8N,EAAmB9N,SAAS,WAC5B8N,EAAmB9N,SAAS,QAC9B,CACA,MAAM+N,EAAoB,IACxBxB,EAAUzL,GAAKgN,EAAmBG,UAAU,KAExChP,EAAQJ,EACZkP,EACAtG,EACA1I,GAGF,GAAc,IAAVE,EACF4M,EAAUlL,KAAK,CACb0H,IAAK,mCACLvF,MAAOiL,SAEJ,GAAI9O,EAAQ,GAAKiF,EAAS,CAC/B,MAAM8J,EAAqB5M,EACzB2M,EACAtG,EACA1I,EACAE,GAGA+O,GAC4D,IAA5DnP,EAAgBmP,EAAoBvG,EAAa1I,IAEjD8M,EAAUlL,KAAK,CACb0H,IAAK,uCACHnE,EAAU,QAAU,IAEtBpB,MAAOkL,GAGb,CACF,CAGF,GACwB,IAAtBnC,GAAWpL,QACXoL,IAAY,IAAI/I,OAAO8B,MAAM,mBAAmBnE,OAAU,GAGtDgH,EAAYjJ,YAAa,CAC3B,MAAM0P,EAAWC,EAAa1G,EAAa1I,EAAOmF,GAAS,GACvDgK,GACFrC,EAAUnF,QAAQ,CAChB2B,IAAK,iBAAgBnE,EAAU,QAAU,IACzCpB,MAAOoL,GAGb,CAGF,IAAKrC,EAAUpL,OAAQ,CACrB,IAAI2N,EAAoB9B,EACtB7E,EAAYrC,cACZrG,EACA0I,EACA5E,EACA0J,EAAUzL,GACVoD,GAGEkK,GACFvC,EAAUlL,KAAK,CACb0H,IAAK,yBACLvF,MAAOsL,GAGb,CACF,CAIJ,OAAOvC,CACT,CAAE,MAAO5L,GACPC,QAAQ0B,IAAI3B,EACd,GAGWoO,EAAuB,CAClC3G,EACAD,EACA1I,EACAmF,EACArB,KAEA,IAAIuD,EAYJ,OAVAA,EAAWsB,EAAKzE,KACJe,EACVyD,EACA1I,EACA,IAAIqH,IACJsB,EAAK5E,MACLoB,EACArB,IAMSyL,EAAqB,CAChC5P,EACAK,EACAmF,EACArB,KAEA,IAAIC,EAAQpE,EAAQ6P,UAQpB,GAPqB,iBAAVzL,IACTA,EAAQ,IAEVA,EAAQA,GAAOT,QAAQ,cAAe,YACtCS,EAAQA,GAAOT,QAAQ,iBAAkB,IACzCS,EAAQA,GAAOX,OAEXW,EACF,OAAOkB,EAAiBtF,EAASK,EAAO,SAAU+D,EAAOoB,EAASrB,IAIzDsL,EAAe,CAC1BzP,EACAK,EACAmF,EACArB,KAEA,GAA2B,IAAvBnE,EAAQF,YAAmB,CAC7B,MAAM4B,EAAO9B,EAAeI,GAE5B,GAAI0B,EACF,OAAO4D,EAAiBtF,EAASK,EAAO,IAAKqB,EAAM8D,EAASrB,EAEhE,GAGI2L,EAAwB,CAC5BrI,EACAsB,EACA1I,EACAmF,EACArB,KAEA,MAAMgD,EAAkBM,EACxB,IACEN,EAAgB4C,IAAKf,IACnB,GAAoB,cAAdA,EAAKzE,MAAsC,UAAdyE,EAAKzE,MAClCN,EAAuB+E,EAAMD,EAAa5E,GAAW,CACvD,MAAM6F,EAAO2F,EACX3G,EACAD,EACA1I,EACAmF,EACArB,GAEE6F,GACFmD,EAAUlL,KAAK,CACb0H,IAAK,YAAYX,EAAKzE,OAAOiB,EAAU,SAAW,KAClDpB,MAAO4F,GAGb,IAIJ,MAAMwF,EAAWC,EAAa1G,EAAa1I,EAAOmF,EAASrB,GAQ3D,GAPIqL,GACFrC,EAAUlL,KAAK,CACb0H,IAAK,iBAAgBnE,EAAU,SAAW,IAC1CpB,MAAOoL,IAKTrI,EAAgB1C,KAAMzE,GAA6B,cAAjBA,EAAQuE,OAC1CN,EACEkD,GAAiB1C,KAAMzE,GAA6B,cAAjBA,EAAQuE,MAC3CwE,EACA5E,GAEF,CACA,IAAI/D,EAAQwP,EAAmB7G,EAAa1I,EAAOmF,EAASrB,GACxD/D,GACF+M,EAAUlL,KAAK,CACb0H,IAAK,iBACLvF,MAAOhE,GAGb,CAEA,IAAK+M,EAAUpL,OAAQ,CACrB,MAAMgO,EAAgBd,EACpBxH,EACAsB,EACA1I,EACA8D,GAEE4L,GACF5C,EAAUlL,KAAK,CACb0H,IAAK,yBACLvF,MAAO2L,GAEb,CAEA,IAAK5C,EAAUpL,QAAUoF,EAAgBpF,OAAS,EAAG,CACnD,MAAM6H,EAAmBrB,EACvBQ,EACA1I,EACA8G,EACAhD,GAEEyF,GACFuD,EAAUlL,KAAK,CACb0H,IAAK,uBACLvF,MAAOwF,GAEb,CACF,CAAE,MAAOrI,GACPC,QAAQ0B,IAAI3B,EACd,GAGWyO,EAAW,CACtBhQ,EACA0E,EACAc,EACArB,EACA8L,EAA6B,MAE7B9C,EAAY,GACZ3L,QAAQ0B,IAAIlD,GACZ,MAAM+I,EAAc/I,EACdK,EAAQ0I,GAAarI,eAAiBgE,EACtCmF,EAAMd,EAAYtD,SAClBgC,WAAEA,GAAesB,EACfmH,EACND,EAAmBlO,OAAS,EAAIkO,EAAqBlP,MAAM4G,KAAKF,GAShE,GARFqI,EACCI,EACCnH,EACA1I,EACAmF,EACArB,GAGIgJ,EAAUpL,OAAQ,CACpB,MAAMoO,EAAMhD,EAAUpL,OACtB,IAAK,IAAIK,EAAI,EAAGA,EAAI+N,EAAK/N,IAAK,CAC5B,IAAI4H,EAAOmD,EAAU/K,GAAGgC,MACxB4F,EAAO,MAAQA,EAAKuF,UAAUvF,EAAKrI,QAAQ,MAAQ,EAAIkI,EAAI9H,QAE7C,IADA5B,EAAgB6J,EAAMhK,EAASK,IAE3C8M,EAAUlL,KAAK,CACb0H,IAAK,GAAGwD,EAAU/K,GAAGuH,YACrBvF,MAAO4F,GAGb,CACF,CAaF,OAVKmD,EAAUpL,QACbmN,EACEnG,EACA1I,EACAmF,EACArB,EACApD,MAAM4G,KAAKoB,EAAYtB,aAIpB0F,GAGH/M,GAAQ,CACZ4P,WACAP,eACAG,qBACAD,uBACAG,wBACAZ,oBACAD,gCACAT,0BACAN,wBACAJ,yBACAF,uBACAL,8BC9/BF,IAAIH,GAA4B,GAC5BD,GAA8C,GAClD,MAAMhO,GAAe,qBA6PfiR,GAAuB,CAC3BC,EACAC,EACAC,EACAlQ,EACAmF,EACAgL,EACAC,EACAC,EAA4C,EAC5CpQ,GAAqC,KAErC,IAAIqQ,EAAgD,GAEpD,GACEL,EAAOxO,MAAM,uCAAuCC,QACpDyO,EAA6BzO,OAC7B,CACA,MAAM6O,EAAuB,GACvBC,EAAiBP,EAAOxO,MAAM,sCACpC,IAAK,IAAIwC,EAAI,EAAGA,GAAKkM,EAA6BzO,OAAQuC,IACxDsM,EAAW5I,QACT1D,IAAMkM,EAA6BzO,OAC/ByO,EACFA,EAA6BzO,OAASuC,GAEpCuM,EAAeA,EAAe9O,OAASuC,IAG/C,MAAMwM,EAAgBC,GACpB,GAAGN,GACFC,EACG,IAAIM,OAAON,GACX,MAEJE,EACAP,EAAiBA,EAAiBtO,OAAS,GAC3CsO,EACAhQ,EACAkQ,EACA/K,EACAlF,GAEF,GAAIwQ,EACF,OAAOA,CAEX,KAAO,CACLH,EAA4B,KAAKF,GAC9BC,EACG,IAAIM,OAAON,GACX,OACAH,MAAahH,EACf+G,EACAD,EAAiBA,EAAiBtO,OAAS,MAE/C,IAAIkP,EAAY9Q,EACdwQ,EACAN,EAAiBA,EAAiBtO,OAAS,GAC3C1B,GAEF,GAAkB,IAAd4Q,EACF,MAAO,CACL,CACEtH,IAAK,WAAW4G,IAChBnM,MAAOU,EAAsB6L,KAInC,GAAIM,EAAY,GACVzL,IACFmL,EAA4BjO,EAC1BiO,EACAN,EAAiBA,EAAiBtO,OAAS,GAC3C1B,EACA4Q,GAEEN,IACFM,EAAY9Q,EACVwQ,EACAN,EAAiBA,EAAiBtO,OAAS,GAC3C1B,GAEgB,IAAd4Q,IACF,MAAO,CACL,CACEtH,IAAK,WAAW4G,KAAY/K,EAAU,SAAW,KACjDpB,MAAOU,EAAsB6L,IAO3C,GAGIO,GAAqB,CACzBb,EACAhQ,EACAqJ,EACAyH,EACAZ,EACA/K,GAAmB,EACnBlF,GAAqC,KAErC,MAAM8Q,EAAoCf,EAAiBA,EAAiBtO,OAAS,GAC/EsP,EAAoChB,EAAiBA,EAAiBtO,OAAS,GAC/EuP,EAAmB1N,EAAcyN,IAAeA,EAAW3Q,cAE3D6Q,EACJ7H,EAAQjF,KAAMH,GAAMA,GAAGqF,KAAKrI,SAAS,cAAc8C,OACnDmC,EAAiB6K,EAAYA,EAAW1Q,eAEpC8Q,EAA8B,GAC9BC,EAA2C,GACjDF,EAAiBzP,MAAM,KAAKiI,IAAKzF,GAAMkN,EAAqBvP,KAAKqC,IACjEkN,EAAqBzH,IAAKzF,GACxBmN,EAAkCxP,KAAKqC,EAAEX,QAAQ,iBAAkB,MAGrE,MAAM+N,EACJP,EAAQ1M,KAAMH,GAAMA,GAAGqF,KAAKrI,SAAS,cAAc8C,OACnDmC,EAAiB8K,EAAYA,EAAW3Q,eAEpCiR,EAA8B,GAC9BC,EAA2C,GACjDF,EAAiB5P,MAAM,KAAKiI,IAAKzF,GAAMqN,EAAqB1P,KAAKqC,IACjEqN,EAAqB5H,IAAKzF,GACxBsN,EAAkC3P,KAAKqC,EAAEX,QAAQ,iBAAkB,MAGrE,IACE,IAAIkO,EAAsB,EAC1BA,EAAsBL,EAAqBzP,QAIzCyP,EAAqBK,IACrBF,EAAqBE,GAJvBA,KAUF,MAAMC,EAA+B,GACrC,IAAK,IAAI1P,EAAIyP,EAAsB,EAAGzP,EAAIoP,EAAqBzP,OAAQK,IACjEoP,EAAqBpP,IACvB0P,EAA6B7P,KAAKwP,EAAkCrP,IAIxE,MAAMoO,EAAyC,GAC/C,IACE,IAAIuB,EACW,eAAbxB,EAA4BsB,EAAsBA,EAAsB,EAC1EE,EAAIJ,EAAqB5P,OACzBgQ,IAEIJ,EAAqBI,KACnBvB,EAA6BzO,OAC/ByO,EAA6BvO,KAAK2P,EAAkCG,IAEpEvB,EAA6BvO,KAC3B2P,EAAkCG,GAAGpO,QAAQ,iBAAkB,MAOvE,IAAI6J,EACJ,GAHAL,GAAYgE,EAGRd,EAAiBA,EAAiBtO,OAAS,GAAGjC,YAAa,CAgB3D0N,EAdCrO,GAAaQ,KACZ0Q,EAAiBA,EAAiBtO,OAAS,GAAGjC,aAanC8E,EAAMyL,EAAiBA,EAAiBtO,OAAS,IAC1D,mBAAmBsO,EAAiBA,EAAiBtO,OAAS,GAAG0D,kBACxDhE,EACT7B,EAAeyQ,EAAiBA,EAAiBtO,OAAS,QAE1D,GAAGsO,EAAiBA,EAAiBtO,OAAS,GAAG0D,aAC7ChE,EACJ7B,EAAeyQ,EAAiBA,EAAiBtO,OAAS,QAjBjD6C,EAAMyL,EAAiBA,EAAiBtO,OAAS,IAC1D,mBAAmBsO,EAAiBA,EAAiBtO,OAAS,GAAG0D,gBAC1D4D,EACPgH,EAAiBA,EAAiBtO,OAAS,QAE3C,GAAGsO,EAAiBA,EAAiBtO,OAAS,GAAG0D,WAC/C4D,EACFgH,EAAiBA,EAAiBtO,OAAS,OAcjD+P,EAA6BA,EAA6B/P,OAAS,GACjEyL,EAEF,MAAMwE,EAAuBF,EAA6BzL,KAAK,KACzDqK,EACJoB,EAA6B/P,OAAS,EAElC0O,EAAQuB,EAEd,IAAK,IAAI5P,EAAI,EAAGA,EAAI+K,GAAUpL,OAAQK,IAAK,CACzC,IAAIkO,EASJ,GANEA,EADEnD,GAAU/K,GAAGgC,MAAM5B,WAAW,MACvB2K,GAAU/K,GAAGgC,MAAMmL,UAC1BpC,GAAU/K,GAAGgC,MAAMzC,QAAQ,MAAQ,GAG5BwL,GAAU/K,GAAGgC,MAEpBkM,EACF,OAAOF,GACLC,EACAC,EACAC,EACAe,GAAoBjR,EACpBmF,EACAgL,EACAC,EACAC,EACApQ,EAGN,CACF,CAEA,GAAI+P,EAAiBA,EAAiBtO,OAAS,GAAG0F,WAAY,CAC5D,IAAK,MAAMC,KAAY3G,MAAM4G,KAAK0I,EAAiBA,EAAiBtO,OAAS,GAC1E0F,YACD,GACExD,EAAuByD,EAAU2I,EAAiBA,EAAiBtO,OAAS,IAAI,GAChF,CACA,IAAI6F,EAAYF,EAASxH,UACzB,GAAI0H,EAAW,CACbA,EAAYA,EAAUjE,QAAQ,iBAAkB,IAChD,MAAMkE,EAAcH,EAASnD,KAE7BiJ,EAAa5I,EAAMyL,EAAiBA,EAAiBtO,OAAS,IAC1D,mBAAmBsO,EAAiBA,EAAiBtO,OAAS,GAAG0D,iBACzDoC,KAAepG,EAAiBmG,MACxC,GAAGyI,EAAiBA,EAAiBtO,OAAS,GAAG0D,YAC9CoC,KAAepG,EAAiBmG,MAEvCkK,EACEA,EAA6B/P,OAAS,GACpCyL,EAEJ,MAAMwE,EAAuBF,EAA6BzL,KAAK,KACzDqK,EACJoB,EAA6B/P,OAAS,EAElC0O,EAAQuB,EAEd,IAAK,IAAI5P,EAAI,EAAGA,EAAI+K,GAAUpL,OAAQK,IAAK,CACzC,IAAIkO,EASJ,OAPEA,EADEnD,GAAU/K,GAAGgC,MAAM5B,WAAW,MACvB2K,GAAU/K,GAAGgC,MAAMmL,UAC1BpC,GAAU/K,GAAGgC,MAAMzC,QAAQ,MAAQ,GAG5BwL,GAAU/K,GAAGgC,MAGjBgM,GACLC,EACAC,EACAC,EACAe,GAAoBjR,EACpBmF,EACAgL,EACAC,EACAC,EACApQ,EAEJ,CACF,CACF,CAGF,IAAK,MAAMoH,KAAY3G,MAAM4G,KAAK0I,EAAiBA,EAAiBtO,OAAS,GAC1E0F,YACD,GACExD,EAAuByD,EAAU2I,EAAiBA,EAAiBtO,OAAS,IAAI,GAChF,CACA,IAAI6F,EAAYF,EAASxH,UACzB,GAAI0H,EAAW,CACbA,EAAYA,EAAUjE,QAAQ,iBAAkB,IAChD,MAAMiG,EAAmBtB,EACvBZ,EACA2I,EAAiBA,EAAiBtO,OAAS,IAE7C,GAAI6H,EAAkB,CAElB4D,EADE5D,EAAiBpH,WAAW,MACjBoH,EAAiB2F,UAC5B3F,EAAiBjI,QAAQ,MAAQ,GAGtBiI,EAGfkI,EACEA,EAA6B/P,OAAS,GACpCyL,EAEJ,MAAMwE,EAAuBF,EAA6BzL,KAAK,KACzDqK,EACJoB,EAA6B/P,OAAS,EAElC0O,EAAQuB,EAEd,IAAK,IAAI5P,EAAI,EAAGA,EAAI+K,GAAUpL,OAAQK,IAAK,CACzC,IAAIkO,EASJ,OAPEA,EADEnD,GAAU/K,GAAGgC,MAAM5B,WAAW,MACvB2K,GAAU/K,GAAGgC,MAAMmL,UAC1BpC,GAAU/K,GAAGgC,MAAMzC,QAAQ,MAAQ,GAG5BwL,GAAU/K,GAAGgC,MAGjBgM,GACLC,EACAC,EACAC,EACAe,GAAoBjR,EACpBmF,EACAgL,EACAC,EACAC,EACApQ,EAEJ,CACF,CACF,CACF,CAEJ,CAEA,MAAM0R,EAAuBF,EAA6BzL,KAAK,KACzDqK,EACJoB,EAA6B/P,OAAS,EAElC+O,EAAgBC,GACpB,GAFYiB,GAGXtB,EACG,IAAIM,OAAON,GACX,MAEJF,EACAH,EAAiBA,EAAiBtO,OAAS,GAC3CsO,EACAhQ,EACAkQ,EACA/K,EACAlF,GAEF,GAAIwQ,EACF,OAAOA,GAILmB,GAA6B,CACjCC,EACAC,EACA5B,EACA6B,EACA9B,EACA9K,EACAlF,KAEA,IAAIoJ,EACAyH,EACJ3P,QAAQ0B,IAAI,6BAA8BqN,GAC1C,MAAM8B,EAA6C,GAEnD,IACE3I,EAAU0I,EAAOtL,OAAQxC,IAAOA,GAAGqF,KAAKrI,SAAS,aAEjD6P,EAAUb,EAAOxJ,OAAQxC,IAAOA,GAAGqF,KAAKrI,SAAS,aAEjD,IAAK,IAAIc,EAAI,EAAGA,EAAIsH,EAAQ3H,OAAQK,IAClC,IAAK,IAAI2P,EAAI,EAAGA,EAAIZ,EAAQpP,OAAQgQ,IAAK,CACvC,IAAIO,EAAgC,KAAwC,IAAnC5I,EAAQtH,GAAGgC,MAAMzC,QAAQ,MAC9D4H,EAAwBG,EAAQtH,GAAGgC,OACnCmF,EACAG,EAAQtH,GAAGgC,MAAMmL,UAAU7F,EAAQtH,GAAGgC,MAAMzC,QAAQ,MAAQ,OAG1D4O,MAAgD,IAAnCY,EAAQY,GAAG3N,MAAMzC,QAAQ,MACtC4H,EAAwB4H,EAAQY,GAAG3N,OACnCmF,EACA4H,EAAQY,GAAG3N,MAAMmL,UAAU4B,EAAQY,GAAG3N,MAAMzC,QAAQ,MAAQ,MAIlEH,QAAQ0B,IAAI,6BAA8BoP,GAC1C,MAAMrB,EAAY9Q,EAChBmS,EACAH,EACAA,EAASzR,eAEX,GAAIuQ,EAAY,EACd,GAAIzL,GAOF,GANA8M,EAAY5P,EACV4P,EACAH,EACAA,EAASzR,cACTuQ,GAEEqB,EAKF,OAJAD,EAAYpQ,KAAK,CACf0H,IAAK,WAAW4G,IAAW/K,EAAU,SAAW,KAChDpB,MAAOU,EAAsBwN,KAExBD,OAEApB,EAAY,IACjB7D,GAAmBrL,OACjBkP,EAAY7D,GAAmB,GAAG7M,QACpC6M,GAAmBM,MACnBN,GAAmBnL,KAAK,CACtB0H,IAAK,qCAAoCnE,EAAU,QAAU,IAE7DpB,MAAOkO,EACP/R,MAAO0Q,KAIX7D,GAAmBnL,KAAK,CACtB0H,IAAK,qCAAoCnE,EAAU,QAAU,IAE7DpB,MAAOkO,EACP/R,MAAO0Q,UAIR,GAAkB,IAAdA,EAKT,OAJAoB,EAAYpQ,KAAK,CACf0H,IAAK,WAAW4G,IAChBnM,MAAOU,EAAsBwN,KAExBD,CAEX,CAEF,IAAKA,EAAYtQ,OACf,IAAK,IAAIK,EAAI,EAAGA,EAAIsH,EAAQ3H,OAAQK,IAClC,IAAK,IAAI2P,EAAI,EAAGA,EAAIZ,EAAQpP,OAAQgQ,IAAK,CACvC,MAIMlB,EAJW,GAAsC,IAAnCM,EAAQY,GAAG3N,MAAMzC,QAAQ,MACzCwP,EAAQY,GAAG3N,MACX+M,EAAQY,GAAG3N,MAAMmL,UAAU4B,EAAQY,GAAG3N,MAAMzC,QAAQ,MAAQ,KAEtBG,MACxC,sCAEF,GAAI+O,EAAe9O,OAAS,EAAG,CAC7B,MAAM+O,EAAgBC,GACpB,GAAsC,IAAnCrH,EAAQtH,GAAGgC,MAAMzC,QAAQ,MACxB4H,EAAwBG,EAAQtH,GAAGgC,OACnCmF,EACAG,EAAQtH,GAAGgC,MAAMmL,UACf7F,EAAQtH,GAAGgC,MAAMzC,QAAQ,MAAQ,MAKvCkP,EACAsB,EACA,CAACD,EAAUC,GACXA,EAASzR,cACT6P,EACA/K,EACAlF,GAIF,GADAkB,QAAQ0B,IAAI,2CAA4C4N,GACpDA,EAEF,OADAuB,EAAYnI,OAAO4G,GACZuB,CAEX,CACF,CAGN,CAAE,MAAO9Q,GACPC,QAAQ0B,IAAI3B,EACd,CAEA,OAAO8Q,GAmFHtB,GAA6B,CACjCwB,EACAC,EACAL,EACA9B,EACAhQ,EACAkQ,EACA/K,EACAlF,KAEA,IAAIqQ,EACJ,GAAKrQ,EAyCE,CACL,MAAMgQ,EAASkC,EAAsBnM,KAAK,KAC1CsK,EAA4B,KAAK4B,KAAWhC,MAAahH,EACvD+G,KAGF,MAAMW,EAAY9Q,EAChBwQ,EACAwB,EACA9R,GAEF,GAAkB,IAAd4Q,EACF,MAAO,CACL,CACEtH,IAAK,WAAW4G,IAChBnM,MAAOU,EAAsB6L,KAInC,GAAIM,EAAY,GACVzL,IACFmL,EAA4BjO,EAC1BiO,EACAN,EAAiBA,EAAiBtO,OAAS,GAC3C1B,EACA4Q,GAEEN,GACF,MAAO,CACL,CACEhH,IAAK,WAAW4G,IAAW/K,EAAU,SAAW,KAChDpB,MAAOU,EAAsB6L,IAMzC,MA7EE,IAAK,IAAIrM,EAAI,EAAGA,GAAKkO,EAAsBzQ,OAAQuC,IAAK,CACtD,MAAMgM,EAASkC,EACZjQ,MAAMiQ,EAAsBzQ,OAASuC,EAAGkO,EAAsBzQ,QAC9DsE,KAAK,KACRsK,EAA4B,KAAK4B,KAAWhC,MAAahH,EACvD+G,KAGF,MAAMW,EAAY9Q,EAChBwQ,EACAwB,EACA9R,GAEF,GAAkB,IAAd4Q,EACF,MAAO,CACL,CACEtH,IAAK,WAAW4G,IAChBnM,MAAOU,EAAsB6L,KAInC,GAAIM,EAAY,GACVzL,IACFmL,EAA4BjO,EAC1BiO,EACAN,EAAiBA,EAAiBtO,OAAS,GAC3C1B,EACA4Q,GAEEN,GACF,MAAO,CACL,CACEhH,IAAK,WAAW4G,IAAW/K,EAAU,SAAW,KAChDpB,MAAOU,EAAsB6L,IAMzC,GAyCE8B,GAAiB,CACrBC,kBAz5B+B,CAC/BR,EACAC,EACA9R,EACAqJ,EACAyH,EACA3L,EACAlF,GAAqC,KAGrC,MAAMqS,EAAOT,EAASxL,cAChBkM,EAAOT,EAASzL,cACtB,IAEImM,EAFAP,EAAmB,GAGnBD,EAAqB,GAEzB,GAAI7M,GACE4H,GAAmBrL,OAAQ,CAC7B,MAAM+Q,EAAiBpQ,EACrB0K,GAAmB,GAAGhJ,MACtB+N,EACAA,EAASzR,cACT0M,GAAmB,GAAG7M,OAEpBuS,IACFT,EAAcA,EAAYnI,OAAO,CAC/BP,IAAK,GAAGyD,GAAmB,IAAIzD,IAC3ByD,GAAmB,IAAIzD,IACvB,sBAEJvF,MAAO0O,IAET1F,GAAmBM,MAEvB,CAGF,IAAK2E,EAAYtQ,OAAQ,CAmCvB,IAjCImQ,EAASjP,WAAWkP,KAEtBG,EAAYL,GACVC,EACAC,EACA,OACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,IAAWD,EAAcA,EAAYnI,OAAOoI,KAIlDO,EAAcX,EAASxL,cAEnBmM,IAAgBV,IAClBG,EAAYL,GACVC,EACAC,EACA,SACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,IAAWD,EAAcA,EAAYnI,OAAOoI,KAIlDO,EAAcX,EAASxL,cAEA,OAAhBmM,GAAsB,CAC3B,GAAIA,IAAgBV,IAClBG,EAAYL,GACVC,EACAC,EACA,WACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,GAAW,CACbD,EAAcA,EAAYnI,OAAOoI,GACjC,KACF,CAGFO,EAAcA,EAAYE,UAC5B,CAGAF,EAAcX,EACd,EAAG,CACD,GAAIW,IAAgBV,IAClBG,EAAYL,GACVC,EACAC,EACA,mBACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,GAAW,CACbD,EAAcA,EAAYnI,OAAOoI,GACjC,KACF,CAGFO,EAAcA,EAAYE,UAC5B,OAAyB,OAAhBF,GAGT,GAAIF,GAAM1P,WAAW2P,GAAO,CAC1B,IACE,IAAIrE,EAAI2D,EAAS5D,mBACZ,MAALC,EACAA,EAAIA,EAAED,mBAEN,GAAS,MAALC,GAAaA,EAAEtL,WAAWkP,KAC5BG,EAAYL,GACVC,EACAC,EACA,oBACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,GAAW,CACbD,EAAcA,EAAYnI,OAAOoI,GACjC,KACF,CAIJ,IACE,IAAIzD,EAAIqD,EAASpD,uBACZ,MAALD,EACAA,EAAIA,EAAEC,uBAEN,GAAS,MAALD,GAAaA,EAAE5L,WAAWkP,KAC5BG,EAAYL,GACVC,EACAC,EACA,oBACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,GAAW,CACbD,EAAcA,EAAYnI,OAAOoI,GACjC,KACF,CAGN,CAGA,GAAIJ,GAAUrL,UAAU9E,OACtB,IAAK,IAAIwM,EAAI2D,EAASrL,SAAS,GAAU,OAAN0H,EAAYA,EAAIA,GAAGD,mBACpD,GAAIC,IAAM4D,IACRG,EAAYL,GACVC,EACAC,EACA,QACAzI,EACAyH,EACA3L,EACAlF,GAEEgS,GAAW,CACbD,EAAcA,EAAYnI,OAAOoI,GACjC,KACF,CAMN,MAAM/B,EAAW2B,EAASlG,wBAAwBmG,GACjC,IAAb5B,IACF+B,EAAYL,GACVC,EACAC,EACA,YACAzI,EACAyH,EACA3L,EACAlF,IAIa,IAAbiQ,IACF+B,EAAYL,GACVC,EACAC,EACA,YACAzI,EACAyH,EACA3L,EACAlF,IAGAgS,IACFD,EAAcA,EAAYnI,OAAOoI,IAGnC,MAAMU,EAAkB9B,GACtB,CAACgB,EAAUC,GACX9R,EACAqJ,EACAyH,EACA,aACA3L,EACAlF,GAEE0S,IAAiBX,EAAcA,EAAYnI,OAAO8I,IAEtD,MAAMC,EAAsB/B,GAC1B,CAACgB,EAAUC,GACX9R,EACAqJ,EACAyH,EACA,qBACA3L,EACAlF,GAEE2S,IACFZ,EAAcA,EAAYnI,OAAO+I,GAErC,CAEA,GAAIZ,EAAYtQ,OAOd,OANIsQ,EAAYtQ,OAAS,GACvBsQ,EAAYa,KAAK,SAAU9P,EAAGG,GAC5B,OAAOH,EAAEgB,MAAMrC,OAASwB,EAAEa,MAAMrC,MAClC,GAGEsQ,EAAYvL,OAAQxC,IAAOA,EAAEqF,KAAKrI,SAAS,WAAWS,OACjD,CAACsQ,EAAYvL,OAAQxC,IAAOA,EAAEqF,KAAKrI,SAAS,UAAU,IAExD,CAAC+Q,EAAY,KAmqBtBnB,sBACAe,8BACAlB,8BACAoC,yBAjLgCnT,IAChC,IAAI0J,EAGE,GAIN,GAFAA,EAAUsG,EAAShQ,EAASA,EAAQU,eAAe,GAAO,GAErDgJ,GAAS3H,OAQP,CACL,IAAI+H,EAASkG,EAAShQ,EAASA,EAAQU,eAAe,GAAM,GACxDoJ,GAAQ/H,SACV+H,EAASA,GAAQC,IAAKzF,GACC,KAArBA,EAAEF,MAAMgP,OAAO,IACbhJ,EAAwB9F,EAAEF,MAAO,GAAK,IAAME,EAAEF,MAAMiP,YAAY,KAC9D,CAAE1J,IAAK,GAAIvF,MAAOxC,EAAkB0C,EAAEF,QACtC,CAAEuF,IAAK,GAAIvF,MAAOE,EAAEF,QAE1BsF,EAAUA,EAAQQ,OAAOJ,GAE7B,MAlBEJ,EAAUsG,EAAShQ,EAASA,EAAQU,eAAe,GAAM,GACzDgJ,EAAUA,GAASK,IAAKzF,GACD,KAArBA,EAAEF,MAAMgP,OAAO,IACbhJ,EAAwB9F,EAAEF,MAAO,GAAK,IAAME,EAAEF,MAAMiP,YAAY,KAC9D,CAAE1J,IAAK,GAAIvF,MAAOxC,EAAkB0C,EAAEF,QACtC,CAAEuF,IAAK,GAAIvF,MAAOE,EAAEF,QAuC5B,GAxBKsF,GAAS3H,SACZ2H,EAAU,CACR,CACEC,IAAK,GACLvF,MAAO8C,EAAiBlH,EAASA,EAAQU,eAAe,GAAO,EAAOK,MAAM4G,KAAK3H,EAAQyH,gBAK1FiC,GAAS3H,SACZ2H,EAAU,CACR,CACEC,IAAK,GACLvF,MAAO8C,EAAiBlH,EAASA,EAAQU,eAAe,GAAM,EAAOK,MAAM4G,KAAK3H,EAAQyH,eAG5FiC,EAAUA,GAASK,IAAKzF,GACD,KAArBA,EAAEF,MAAMgP,OAAO,IACbhJ,EAAwB9F,EAAEF,MAAO,GAAK,IAAME,EAAEF,MAAMiP,YAAY,KAC9D,CAAE1J,IAAK,GAAIvF,MAAOxC,EAAkB0C,EAAEF,QACtC,CAAEuF,IAAK,GAAIvF,MAAOE,EAAEF,SAIvBsF,GAAS3H,OAEP,CACL,MAAM+H,EAASN,EACbxJ,EACAA,EAAQU,eACR,GAEEoJ,GAAQ/H,SACV2H,EAAUA,EAAQQ,OAAOJ,GAE7B,MAVEJ,EAAUF,EAA0BxJ,EAASA,EAAQU,eAAe,GAYtE,MAAM4S,EAAwB/M,EAC5BvG,EACAA,EAAQU,eASV,OAPAgJ,EAAUA,EAAQ5C,OAAQxC,GAAMA,EAAEF,QAAUkP,GAE5C5J,EAAQzH,KAAK,CACX0H,IAAK,iBACLvF,MAAOkP,EAAsB/Q,MAAM,KAG9BmH,IC90BT,IAAIlK,GAAgC,GAEpC,MAIM+T,GAAsB,CAC1BlI,EACAxH,EACAE,KAEA,IACE,MAAMyP,EAAUzP,EAAKuH,iBAAiBD,GACtC,OAA0B,IAAnBmI,EAAQzR,QAAgByR,EAAQ,KAAO3P,CAChD,CAAE,MACA,OAAO,CACT,GAIW4P,GAAoB,CAAC5P,EAAa6P,EAAmB,YAChE,MAAMC,EAA8C,GAC9C5P,EAAOF,EAAGC,cAEhB,IACE,MAAM8P,EAASC,GAAahQ,GAC5B,GAAI+P,GAAUL,GAAoBK,EAAQ/P,EAAIE,KAC5C4P,EAAU1R,KAAK,CAAE0H,IAAK,oBAAqBvF,MAAOwP,IACrC,WAATF,GAAmB,OAAOC,EAEhC,MAAMG,EAAYC,GAAgBlQ,GAC9BiQ,GAAaP,GAAoBO,EAAWjQ,EAAIE,IAClD4P,EAAU1R,KAAK,CAAE0H,IAAK,uBAAwBvF,MAAO0P,IAEvD,MAAME,EAAWC,GAAoBpQ,GACjCmQ,GACFL,EAAU1R,KAAK,CAAE0H,IAAK,sBAAuBvF,MAAO4P,IAEtD,MAAME,EAAUC,GAAmBtQ,GAC/BqQ,GAAWX,GAAoBW,EAASrQ,EAAIE,IAC9C4P,EAAU1R,KAAK,CAAE0H,IAAK,uBAAwBvF,MAAO8P,GAEzD,CAAE,MAAOE,GACP5S,QAAQD,MAAM6S,EAChB,CACA,OAAOT,GAIIE,GAAgBhQ,IAC3B,MAAMwQ,EAAOxQ,EAAGnD,eAAe4T,YAC/B,KAAKD,GAAUxQ,aAAcwQ,EAAKE,SAAU,OAC5C,MAAM9O,EAAU5B,EAAG4B,QAAQK,cAC3B,GAAIL,EAAQnE,SAAS,UAAYmE,EAAQnE,SAAS,UAAW,OAE7D,MAAMkT,EAAO,GACb,KAAO3Q,GAAIpD,WAAawE,KAAKwP,cAAc,CACzC,IAAIpJ,EAAWxH,EAAG6E,UAAU5C,cAC5B,GAAIjC,EAAG6Q,KAAOjV,EAAcoE,EAAG6Q,IAAK,CAClCrJ,GAAY,IAAIsJ,IAAIC,OAAO/Q,EAAG6Q,MAC9BF,EAAKxM,QAAQqD,GACb,KACF,CAAO,CACL,IAAIwJ,EAAMhR,EACNiR,EAAM,EACV,GAAID,EAAI/F,uBACN,KAAQ+F,EAAMA,EAAI/F,wBACZ+F,EAAInM,UAAU5C,gBAAkBuF,GAAUyJ,IAItC,IAARA,IACFzJ,GAAY,gBAAgByJ,MAGlB,IAARA,GAAaD,GAAKnO,eAAeqO,kBAAqB,IACxD1J,GAAY,cAAcyJ,KAE9B,CACAN,EAAKxM,QAAQqD,GACbxH,EAAKA,EAAG6C,aACV,CACA,OAAO8N,EAAKnO,KAAK,QAGb2O,GAAiB,IAAI/O,IAAI,CAC7B,KACA,QACA,UAEF,SAASgP,GAAsBpR,GAC7B,OAAO9C,MAAM4G,KAAK9D,EAAG4D,YAClBX,OAAOkC,IACLgM,GAAe5N,IAAI4B,GAAMzE,MAAMuB,gBAChCkD,EAAK5E,QACJ3E,EAAcuJ,EAAK5E,QAErB2F,IAAIf,IACH,UAAIA,EAAKzE,SAhGkBH,EAgGe4E,EAAK5E,MA/F5C8Q,OAAO9Q,GAAOT,QAAQ,MAAO,QAAQA,QAAQ,KAAM,WAD5B,IAACS,GAkGjC,CAGO,MAAM6P,GACXpQ,IAEA,MAAMwQ,EAAOxQ,EAAGnD,eAAe4T,YAC/B,KAAKD,GAAUxQ,aAAcwQ,EAAKE,SAAU,OAE5C,MAAMxQ,EAAOF,EAAGC,cACV+F,EAAMhG,EAAG4B,QAAQK,cAEvB,GAAY,UAAR+D,GAA2B,WAARA,EAAkB,OAEzC,MAAMsL,EAAgBF,GAAsBpR,GAE5C,IAAK,MAAMuR,KAAgBD,EAAe,CACxC,MAAME,EAAY,GAAGxL,IAAMuL,IAE3B,GAAI7B,GAAoB8B,EAAWxR,EAAIE,GACrC,OAAOsR,CAEX,GAMWtB,GAAmBlQ,IAC9B,MAAMwQ,EAAOxQ,EAAGnD,eAAe4T,YAC/B,KAAKD,GAAUxQ,aAAcwQ,EAAKE,SAAU,OAC5C,MAAM9O,EAAU5B,EAAG4B,QAAQK,cAC3B,GAAIL,EAAQnE,SAAS,UAAYmE,EAAQnE,SAAS,UAAW,OAE7D,MAAMkT,EAAO,GACb,KAAO3Q,GAAIpD,WAAawE,KAAKwP,cAAc,CACzC,IAAIpJ,EAAWxH,EAAG6E,UAAU5C,cAE5B,GAC0B,iBAAjBjC,EAAGgM,YACVhM,EAAGgM,WACFpQ,EAAcoE,EAAGgM,YACjBrQ,IAA2BiF,KACzBH,GAAkEA,EAAEtE,UAAY6D,GAA0B,UAApBS,EAAEK,eAUtF,CACL,IAAIkQ,EAAMhR,EACNiR,EAAM,EACV,GAAID,EAAI/F,uBACN,KAAQ+F,EAAMA,EAAI/F,wBACZ+F,EAAInM,UAAU5C,gBAAkBuF,GAAUyJ,IAItC,IAARA,IACFzJ,GAAY,gBAAgByJ,MAGlB,IAARA,GAAaD,GAAKnO,eAAeqO,kBAAqB,IACxD1J,GAAY,cAAcyJ,KAE9B,MArBE,GAFAjR,EAAG6I,UAAU4I,OAAO,uBACpBzR,EAAG6I,UAAU4I,OAAO,kBAChBzR,EAAGgM,UAAW,CAChBxE,GAAY,IAAIxH,EAAGgM,UAAUpM,OAAOE,QAAQ,OAAQ,OACpD6Q,EAAKxM,QAAQqD,GACb,KACF,CAkBFmJ,EAAKxM,QAAQqD,GACbxH,EAAKA,EAAG6C,aACV,CACA,OAAO8N,EAAKnO,KAAK,QAGN8N,GAAsBtQ,IACjC,MAAMwQ,EAAOxQ,EAAGnD,eAAe4T,YAC/B,KAAKD,GAAUxQ,aAAcwQ,EAAKE,SAAU,OAE5C,MAAMC,EAAiB,GAEvB,KAAO3Q,GAAMA,EAAGpD,WAAawE,KAAKwP,cAAc,CAC9C,MAAMhP,EAAU5B,EAAG4B,QAAQK,cAE3B,GAAgB,UAAZL,GAAmC,WAAZA,EAAsB,OAEjD,IAAI4F,EAAW5F,EAEf,MAAM8P,EAAS1R,EAAGkP,WAElB,GAAIwC,EAAQ,CACV,MAAMpN,EAAWpH,MAAM4G,KAAK4N,EAAO1O,UAChCC,OAAOtD,GAAKA,EAAEiC,UAAY5B,EAAG4B,SAE5B0C,EAASpG,OAAS,IACpBsJ,GAAY,gBAAgBlD,EAASxG,QAAQkC,GAAM,KAEvD,CAEA2Q,EAAKxM,QAAQqD,GAEbxH,EAAKA,EAAG6C,aACV,CAEA,OAAO8N,EAAKnO,KAAK,QAGNmP,GAAe,CAC1B/B,qBACAI,gBACAI,uBACAF,mBACAI,uBC5MIsB,GAAwB,CAC5BrV,EACAC,EACAmM,KAEA,MAAMkJ,EAAavL,EAAe/J,GAElC,GADcuV,GAAoBtV,EAAOqV,KAC3BlJ,EAAQ,OAAO,EAE7B,GJoyCI,SAA4BpM,GAChC,MAAO,iEAAiET,KACtES,EAEJ,CIxyCMwV,CAAkBF,GAAa,CACjC,MAAMG,EAASxV,EAAMM,SACnB+U,EACArV,EACA,KACAO,YAAYkV,2BACZ,MAGF,IAAK,IAAI1T,EAAI,EAAGA,EAAIyT,EAAOE,eAAgB3T,IACzC,GAAIyT,EAAOG,aAAa5T,KAAOoK,EAAQ,OAAO,CAElD,CAEA,OAAO,GAGHyJ,GAA4B,CAChC5V,EACAgL,KAEA,IACE,MAAM6K,EAAQ7V,EAAMsO,cAActD,GAClC,GAAI6K,EAAO,OAAOA,CACpB,CAAE,MAAO3U,GAEP,OADAC,QAAQD,MAAM,wBAAyB8J,EAAU9J,GAC1C,IACT,CAEA,OAAO4U,GAAyB9V,EAAM+V,KAAM/K,IAGxCgL,GAA8B,CAClChL,EACAhL,EACAmM,IAEOyJ,GAA0B5V,EAAOgL,KAAcmB,EAYlD8J,GAAwBC,GACrBA,EAAQhS,MAAMuB,cAAcxE,SAAS,iBAAkB,EAkB1D6U,GAA2B,CAC/BtS,EACAwH,KAOA,MAAMmL,EAAWzV,MAAM4G,KAAK9D,EAAGyH,iBAAiB,MAEhD,IACE,IAAK,IAAIlJ,EAAI,EAAGA,EAAIoU,EAASzU,OAAQK,IACnC,GAAIoU,EAASpU,GAAGqU,WAAY,CAC1B,MAAMA,WAAEA,GAAeD,EAASpU,GAChC,GAAIqU,EAAY,CACd,MAAMC,EAAgBP,GAAyBM,EAAYpL,GAC3D,GAAIqL,EACF,OAAOA,EAET,GAAID,IAAepL,EAAS/J,SAAS,WACnC,OAAOmV,EAAW9H,cAActD,EAEpC,CACF,CAEJ,CAAE,MAAO9J,GACPC,QAAQ0B,IAAI3B,EACd,CACA,OAAO,MAGHoV,GAAS3W,GACNA,GAAS0U,IAAM,KAGlBkC,GAAgB5W,GACZA,EAAwB6P,WAAa,KAGzCgH,GAAkB7W,GACfA,EAAQF,aAAa2D,QAAU,KAGlCqT,GAAW9W,IACf,MAAM+W,EAAY/W,EAElB,GAAI+W,EAAUC,aAAa,QAAS,CAGlC,MADa,GADKD,EAAUE,aAAa,WAE1B,IACjB,CACA,OAAO,MAGHC,GAAsB,CAC1B,qBACA,qBACA,UACA,cACA,YACA,QACA,oBACA,SACA,aACA,cAGF,SAASvB,GAAoBtV,EAAiBD,GAC5C,MAAMuL,EAAStL,EAAMiU,YACrB,IAAK3I,EAAQ,OAAO,KAUpB,OARuB,IAAIA,EAAOwL,gBACCxW,SACjCP,EACAC,EACA,KACAsL,EAAO/K,YAAYwE,wBACnB,MAEiBC,eACrB,CAEA,SAAS+R,GACPb,EACAhG,EACAlQ,GAEA,GAAIkW,EAAQjV,SAASiP,GAAW,CAC9B,MACM8G,EAD8Bd,EAAQzU,MAAMyO,GACd,GAAG9M,OACjCkI,EAAStL,EAAMiU,YACrB,IAAK3I,EAAQ,OAAO,KACpB,IAAK4K,EAAQjV,SAAS,WAAY,CAChC,MAAMgW,EAAiB,IAAI3L,EAAOwL,eAUlC,GAToBG,EAAe3W,SACjC0W,EACAhX,EACA,KACAsL,EAAO/K,YAAYwE,wBACnB,MAGgCC,gBACf,CASjB,IAAI8J,EACJ,OAT4BmI,EAAe3W,SACzC4V,EACAlW,EACA,KACAsL,EAAO/K,YAAYwE,wBACnB,MAE0CC,iBAG1C8J,EAAgBoH,EACTpH,IAEP3N,QAAQD,MAAM,+BAAgCgV,GAC9CpH,EAAgBoH,EACTpH,EAEX,CACE3N,QAAQD,MAAM,4BAA6B8V,EAE/C,CACF,CACA,OAAO,IACT,CAEA,MAAME,GAAsB,CAC1BC,EACAnX,KAEA,MAAMoX,EAAmBpX,EAAMiL,iBAC7B,4FAGEmM,GACFA,EAAiBpL,QAASxC,IACvBA,EAAgByL,WAIrB,MAAMoC,EAAgC,IAAIzR,IAC1C,IAAI0R,EAAuB,GAE3B,SAASC,EAAcC,EAAWC,EAA0B,IAC1D,MAAMrL,EAAWoL,GAAMzT,MACjB2T,EAAWD,EAAU1T,OAASyT,GAAMzT,MACpC4T,EAAkB,CACtBzT,KAAMuT,EAAUvT,MAAQsT,GAAMtT,KAC9BmH,KAAMoM,EAAUpM,MAAQmM,GAAMnM,KAC9BtH,MAAO0T,EAAU1T,OAASyT,GAAMzT,MAChC6T,UAAWH,EAAUG,WAAaJ,GAAMI,UACxCC,OAAQJ,EAAUI,QAAUL,GAAMK,OAClCC,WAAYL,EAAUK,YAAcN,GAAMM,YAGtCC,EAA4C,MAAvBP,GAAMQ,aAEjCL,EAAWK,aAAeD,EACtB,IACAN,EAAUQ,eAAe,gBACvBR,EAAUO,aAhMQ,EAC1BE,EACA9L,EACAsL,IAEKtL,GAAasL,GACXtL,IAAasL,EAAW,KADI,IA4L3BS,CAAoBR,EAAWzT,KAAMkI,EAAUsL,GA6EvD,SAA2BU,GACzB,MAAM9O,EAAM,GAAG8O,EAAIlU,QAAQkU,EAAIrU,QAC1BsT,EAAiBtQ,IAAIuC,KACxB+N,EAAiBgB,IAAI/O,GACrBgO,EAAc1V,KAAKwW,GAEvB,CAjFEE,CAAkBX,EACpB,CAEA,SAASY,EACPC,EACAtC,EACAlL,GAEA,GAAIiL,GAAqBC,GACvB,OAAON,GAA0B4C,EAAKxN,GACjC,GAAIkL,EAAQhS,KAAKjD,SAAS,OAAS+J,EAAS7I,WAAW,KAC5D,OAAOqW,EAAIlK,cAAc,IAAMzD,EAAgBG,IAC1C,GAAIkL,EAAQhS,KAAKjD,SAAS,cAAgB+J,EAAS7I,WAAW,KACnE,OAAOqW,EAAIlK,cAAc,IAAMtD,GAC1B,GAAqB,SAAjBkL,EAAQhS,KAAiB,CAClC,MAAMuU,EAAW5N,EAAgBG,GACjC,OAAOwN,EAAIlK,cAAc,UAAUmK,MACrC,CAAO,GAAqB,YAAjBvC,EAAQhS,KACjB,OAAOsU,EAAIlK,cAActD,GACpB,GAAqB,aAAjBkL,EAAQhS,KACjB,OACExD,MAAM4G,KAAKkR,EAAIvN,iBAAiB,MAAM7G,KACnCrB,GAAMA,EAAEtD,aAAa2D,SAAW4H,IAC9B,KAEF,GAAqB,oBAAjBkL,EAAQhS,KACjB,OACExD,MAAM4G,KAAKkR,EAAIvN,iBAAiB,MAAM7G,KAAMrB,GAC1CA,EAAEtD,aAAawB,SAAS+J,KACrB,KAEF,IACJkL,EAAQhS,KAAKjD,SAAS,WAAY+J,EAAS7I,WAAW,OACtD+T,EAAQ7K,KAAKxF,MAAM,WAcpB,OAAO2S,EAAIlK,cAActD,GAbzB,CACA,MACMxH,EAAK8R,GAAoBkD,EADP1O,EAAekB,IAUvC,OAPIxH,GACF+T,EAAcrB,EAAS,CACrBnS,MAAOiH,EACP8M,WAAYjD,OAAOqB,EAAQ4B,YAAY7W,SAAS,KAAO,IAAM,MAI1DuC,CACT,CAGF,CAEA,SAASkV,EACP1Y,EACAkW,EACAlL,GAEA,MAAM2N,EAAU3Y,EAAMiL,iBAAiB,UAEvC,IAAK,MAAM2N,KAAUD,EACnB,IACE,MAAME,EACJD,EAAOE,iBAAmBF,EAAOG,eAAe1K,SAElD,IAAKwK,EAAW,SAEhB,MAAMrV,EAAK+U,EAAeM,EAAW3C,EAASlL,GAC9C,GAAIxH,EAAI,OAAOA,CACjB,CAAE,MACA,QACF,CAGF,OAAO,IACT,CAWA,MAAMwV,EAAoB,CACxB1W,EACA+I,EACAyM,KAEA,IAAKxV,EAAK,OAAO,KAEjB,IAAI2W,EAAU3W,EAAIc,OAGlB,OAAK6V,GAAqC,SAA1BA,EAAQxT,eAGxBwT,EAAUA,EAAQ3V,QAAQ,OAAQ,KAAKA,QAAQ,OAAQ,KAGvD2V,EAAUA,EAAQ3V,QAAQ,kBAAmB,MAG7C2V,EAAUA,EAAQ3V,QAAQ,MAAO,KAGjC2V,EAAUA,EAAQ3V,QAChB,sCACA,cAIW,OAAT+H,GAA0B,SAATA,IACnB4N,EAAUA,EAAQ3V,QAAQ,QAAS,IAAIF,QAG5B,UAATiI,GAAmC,MAAfyM,GAAuBxV,EAAIH,WAAW,OAIzD8W,GAAW,YAAY3Z,KAAK2Z,GAAiB,KAE3CA,EALE,MAvBgD,MA+B3DC,EAAU,IAAK,MAAMhD,KAAWiB,EAAO+B,SACrC,IACqBrE,OAAOqB,EAAQ4B,YAAc,IAAhD,MACMqB,EAAoBhC,EAAO+B,SAASzS,OACvC2S,GAAuB,MAAjBA,EAAEtB,YAGX,GAAIqB,EAAkBzX,OAAS,EAC7B,IAAK,MAAMwU,KAAWiD,EACpB5B,EAAcrB,GAIlB,MAAMmD,EAAYxE,OAAOqB,EAAQnS,OAASmS,EAAQ7K,MAAQ,IAC1D,GACEgO,EAAUpY,SAAS,YACnBoY,EAAUxT,MAAM,YAChBwT,EAAUpY,SAAS,MACnBoY,EAAUpY,SAAS,KACnB,CACAsW,EAAcrB,GACd,QACF,CAEA,GAAIiB,EAAOmC,SAASrY,SAAS,KAC3B,MAAMiY,EAGR,IACE,IAAI1Z,EAAgC,KACpC,MAAM8T,EAAY4C,EAAQnS,MAAMtC,MAAM,OAEtC,IAAK,MAAMuJ,KAAYsI,EAAW,CAChC,IAAKtT,EAAO,CACVmB,QAAQD,MAAM,wBAAyB8J,GACvC,KACF,CAEA,MAAMuO,EAAkBvO,EAAS5H,OAkBjC,GAfA5D,EAAgB+Y,EAAevY,EAAOkW,EAASqD,GAG1C/Z,IACHA,EAAgBkZ,EAAc1Y,EAAOkW,EAASqD,IAI3C/Z,IACHA,EAAgBsW,GACd9V,EAAM+V,KACNwD,KAIC/Z,EAAe,CAClB2B,QAAQD,MAAM,wBAAyBqY,GACvC,KACF,CACF,CAEA,MAAMC,EAAgB,CAACtV,EAAcH,KACnC,MAAMuF,EAAM,GAAGpF,KAAQH,IACvB,OAAOsT,EAAiBtQ,IAAIuC,IAG9B,GAAI9J,EAAe,CACjB,MAAMia,EAAgBtC,EAAO+B,SAASzS,OACnC2S,GAAiB,UAAXA,EAAElV,MAAoBkV,EAAErV,OAE3B2V,EAAsBvC,EAAO+B,SAASzS,OACzC2S,GAAMnD,GAAqBmD,IAAMA,EAAErV,OAGtC,IAAK,MAAM4V,KAAMF,EACXrE,GAAsBuE,EAAG5V,MAAO/D,EAAOR,IACzC+X,EAAcoC,EAAI,CAChB3B,aAAc,OAIpB,IAAK,MAAM4B,KAAcF,EAErB1D,GACE4D,EAAW7V,MACX/D,EACAR,IAGF+X,EAAcqC,EAAY,CACxB5B,aAAc,OAIpB,MAAM6B,EAAiBvC,EAAc7Q,OAClC2S,GAAiB,UAAXA,EAAElV,MAAoBkV,EAAErV,OAI3B+V,EAAoB,IAAIlU,IAC5BiU,EAAenQ,IAAKzF,GAAMkG,EAAgBlG,EAAEF,SAGxCgW,EAA+B,GAC/BC,EAAU1D,GAAM9W,GACtB,GACEwa,IACCR,EAAc,KAAMQ,KACpB5a,EAAc4a,GACf,CACA,MAAMC,EAAS9C,EAAO+B,SAAS9U,KAAMgV,GAAiB,OAAXA,EAAElV,MACzC4G,EAAc9K,EAAO,KAAMga,EAASxa,KACtCua,EAAmBnY,KAAK,MACxB2V,EAAc0C,EAAQ,CACpB/V,KAAM,KACNmH,KAAM,SACNyM,WAAY,IACZ/T,MAAOiW,IAGb,CAEA,MAAM5U,EAAU5F,EAAc4F,QAC9B,GAAIA,IAAYoU,EAAc,UAAWpU,GAAU,CACjD,MAAM8U,EAAU/C,EAAO+B,SAAS9U,KAAMgV,GAAiB,YAAXA,EAAElV,MAC1C4G,EAAc9K,EAAO,UAAWoF,EAAS5F,KAC3Cua,EAAmBnY,KAAK,WACxB2V,EAAc2C,EAAS,CACrBhW,KAAM,UACNmH,KAAM,SACNyM,WAAY,IACZ/T,MAAOqB,IAGb,CAEA,MAAM+U,EAAY3D,GAAehX,GACjC,GAAI2a,IAAc/a,EAAc+a,GAAY,CAC1C,MAAMC,EAAejD,EAAO+B,SAAS9U,KAClCgV,GAAiB,aAAXA,EAAElV,MAEP4G,EAAc9K,EAAO,WAAYma,EAAW3a,KAC9Cua,EAAmBnY,KAAK,YACxB2V,EAAc6C,EAAc,CAC1BlW,KAAM,WACNmH,KAAM,SACNyM,WAAY,IACZ/T,MAAOoW,IAGb,CAEA,MAAME,EAAc5D,GAAQjX,GAC5B,GACE6a,IACCb,EAAc,OAAQa,KACtBjb,EAAcib,GACf,CACA,MAAMC,EAAWnD,EAAO+B,SAAS9U,KAAMgV,GAAiB,SAAXA,EAAElV,MAC3C4G,EAAc9K,EAAO,OAAQqa,EAAa7a,KAC5Cua,EAAmBnY,KAAK,QACxB2V,EAAc+C,EAAU,CACtBpW,KAAM,OACNmH,KAAM,SACNyM,WAAY,IACZ/T,MAAOsW,IAGb,CAEA,MAAME,EAAahE,GAAa/W,GAChC,GACE+a,GACsB,KAAtBA,EAAWnX,SACVmX,EAAWtZ,SAAS,OACpBuY,EAAc,YAAae,KAC3Bnb,EAAcmb,GACf,CACA,MAAMC,EAAmBrD,EAAO+B,SAAS9U,KACtCgV,GAAiB,cAAXA,EAAElV,MAEP4G,EAAc9K,EAAO,YAAaua,EAAY/a,KAChDua,EAAmBnY,KAAK,aACxB2V,EAAciD,EAAkB,CAC9BtW,KAAM,YACNmH,KAAM,SACNyM,WAAY,IACZ/T,MAAOwW,IAGb,CACAnH,GAAkB5T,EAAe,UAAUwM,QACxCyO,IAEGA,EAAY1W,QACXyV,EAAc,cAAeiB,EAAY1W,QAE1CwT,OAAcpX,EAAW,CACvB+D,KAAM,cACNH,MAAO0W,EAAY1W,MACnBsH,KAAM,SACNyM,WAAY,QAKpB,MACMlI,EADgBlP,MAAM4G,KAAK9H,EAAc4H,YACNX,OACtCkC,IAAUoR,EAAmB9Y,SAAS0H,EAAKzE,OAK9C,IAAIwW,EAAsB,GAC1B,IACEA,EACE/K,EAASnQ,EAAeQ,GAAO,GAAO,EAAM4P,IAC5C,EACJ,CAAE,MAAO1O,GACPC,QAAQD,MAAM,qCAAsCA,EACtD,CAEA,GAA6B,IAAzBwZ,GAAchZ,OAAc,CAC9B,MAAMiZ,EAAsBlB,EAAchT,OACvCkT,IAAQvE,GAAsBuE,EAAG5V,MAAO/D,EAAOR,IAGlD,IAAIob,EAAa,EAEjB,IAAK,MAAMC,KAAYF,EAAqB,CAC1C,GAAIC,GAAcD,EAAoBjZ,OAAQ,MAE9C,MAAMoZ,EAAkB3Q,EAAgB0Q,EAAS9W,OACjD,GAAI+V,EAAkB/S,IAAI+T,GAAkB,SAE5C,MAAMjV,EAAQ6U,EAAatW,KACxB2W,GAAMA,EAAEhX,OAASoG,EAAgB4Q,EAAEhX,SAAW+W,GAG7CjV,GAAO9B,QACTwT,EAAcsD,EAAU,CACtB3W,KAAM,QACNH,MAAO8B,EAAM9B,MACbsH,KAAM,SACNyM,WAAY,IACZE,aAAc,MAGhB8B,EAAkBzB,IAAIyC,GACtBF,IAEJ,CACA,GAAIA,EAAaD,EAAoBjZ,OACnC,IAAK,MAAM8T,KAAUkF,EAAc,CACjC,GAAIE,GAAcD,EAAoBjZ,OAAQ,MAC9C,IAAK8T,EAAOzR,MAAO,SAEnB,MAAMwB,EAAU4E,EAAgBqL,EAAOzR,OACnC+V,EAAkB/S,IAAIxB,KAE1BgS,EAAc/B,EAAQ,CACpBtR,KAAM,QACNH,MAAOyR,EAAOzR,MACdsH,KAAM,SACNyM,WAAY,IACZE,aAAc,MAGhB8B,EAAkBzB,IAAI9S,GACtBqV,IACF,CAEJ,CACA,IAAK,MAAM1E,KAAWiB,EAAO+B,SAC3B,IACE,IAAK,MAAM8B,KAAO7D,EAAO+B,SACvB,GAAK8B,EAAIjX,MAET,IAAK,MAAMmM,KAAY2G,GACrB,GAAImE,EAAIjX,MAAM9C,SAASiP,GAAW,CAChC,MAAMpB,EAAgBiI,GACpBiE,EAAIjX,MACJmM,EACAlQ,GAEF,GAAI8O,EAAe,CACjByI,EAAcyD,EAAK,CACjB9W,KAAM,QACNH,MAAO+K,EACPgJ,WACyB,KAAvB5B,EAAQ4B,YACe,OAAvB5B,EAAQ4B,WACJ5B,EAAQ4B,WACR,MAER,KACF,CACF,CAGN,CAAE,MAAO5W,GACPC,QAAQD,MAAM,4BAA6BgV,EAAShV,EACtD,CAEF,GAAIoW,EAAc5V,OAAS,EAAG,CAC5B,MAAMuZ,EAAqB,CACzB,CAAE/W,KAAM,KAAMH,MAAOuS,GAAM9W,IAC3B,CAAE0E,KAAM,OAAQH,MAAO0S,GAAQjX,IAC/B,CAAE0E,KAAM,YAAaH,MAAOwS,GAAa/W,IACzC,CAAE0E,KAAM,UAAWH,MAAOvE,EAAc4F,SACxC,CAAElB,KAAM,WAAYH,MAAOyS,GAAehX,KAG5C,IAAK,MAAMwV,KAAaiG,EAAoB,CAC1C,GAAI3D,EAAc5V,OAAS,EAAG,MAE9B,MAAMwC,KAAEA,EAAIH,MAAEA,GAAUiR,EACnBjR,IACD3E,EAAc2E,IACdyV,EAActV,EAAMH,IACX,cAATG,GAAwBH,EAAM9C,SAAS,MACvC6J,EAAc9K,EAAOkE,EAAMH,EAAOvE,IACpC+X,OAAcpX,EAAW,CACvB+D,OACAmH,KAAM,SACNtH,QACA+T,WAAY,IACZE,aAAc,MAGpB,CAEIV,EAAc5V,OAAS,GACzB0R,GAAkB5T,EAAe,YAAYwM,QAC1CyO,IACKnD,EAAc5V,OAAS,GACtB+Y,EAAY1W,QACbyV,EAAc,cAAeiB,EAAY1W,QAE1C+G,EACC9K,EACA,cACAya,EAAY1W,MACZvE,IAMJ+X,OAAcpX,EAAW,CACvB+D,KAAM,cACNmH,KAAM,SACNtH,MAAO0W,EAAY1W,MACnB+T,WAAY,IACZE,aAAc,QAKxB,CAEA,MAAMkD,EAA0B5D,EAAc5N,IAAK0O,IAAG,IACjDA,EACHrU,MAAOiV,EAAkBZ,EAAIrU,MAAOqU,EAAIlU,KAAMkU,EAAIN,eAG9CqD,EAAa,CACjB,CACEjX,KAAM,GAAGiT,EAAOjT,OAChBkX,KAAM,GAAGjE,EAAOiE,OAChB/P,KAAM,GAAG8L,EAAO9L,OAChB6N,SAAUgC,EAAwBzU,OAC/ByP,GAA8B,MAAlBA,GAASnS,OAAmC,KAAlBmS,EAAQnS,OAEjDuV,SAAU,GAAGnC,EAAOmC,WACpB+B,UAAW,GAAGlE,EAAOkE,YACrBC,YAAa,GAAGnE,EAAOmE,cACvBxD,WAAY,GAAGX,EAAOW,aACtByD,OAAQ,GAAGpE,EAAOoE,SAClBC,SAAU,GAAGrE,EAAOqE,WACpBC,WAAY,GAAGtE,EAAOsE,aACtBC,SAAU,GAAGvE,EAAOuE,WACpBC,UAAW,GAAGxE,EAAOwE,YACrBC,YAAa,GAAGzE,EAAOyE,cACvBC,OAAQ,GAAG1E,EAAO0E,WAItB,OAAOV,CACT,CACF,CAAE,MAAOja,GACPC,QAAQD,MAAM,4BAA6BgV,EAAShV,GACpD,QACF,CACF,CAAE,MAAOA,GACPC,QAAQD,MAAM,4BAA6BgV,EAAShV,GACpD,QACF,CAEF,OAAO,MCvwBI4a,GAAiB,KAAA,CAC5B/b,yBACAgc,GACA7Q,aACAgM,uBACA/B"}
|