@nodebug/browser-element-finder 1.0.8 → 1.1.5
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/README.md +215 -111
- package/index.js +417 -206
- package/index.min.js +1 -0
- package/package.json +10 -4
- package/src/element-definitions.json +4 -1
- package/src/searchable-attributes.json +0 -1
package/index.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var ElementFinder=(()=>{var M=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var F=(e,t)=>{for(var n in t)M(e,n,{get:t[n],enumerable:!0})},U=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of j(t))!_.call(e,r)&&r!==n&&M(e,r,{get:()=>t[r],enumerable:!(o=P(t,r))||o.enumerable});return e};var V=e=>U(M({},"__esModule",{value:!0}),e);var re={};F(re,{ELEMENT_DEFINITIONS:()=>g,findElementByAttributes:()=>$,findElementByType:()=>L,findElements:()=>G,findProbableElements:()=>K,getAllElements:()=>b,getAllFrames:()=>N,getBoundingBox:()=>x,getSearchableAttributes:()=>W,getValidAttributes:()=>ne,getValidTypes:()=>te,highlight:()=>v,matchesAttribute:()=>E,matchesType:()=>w,parseCondition:()=>k,parseXPath:()=>p,setSearchableAttributes:()=>Z,splitByOperator:()=>T,unhighlight:()=>ee});var S={link:"self::a or @role='link' or @href",navigation:"@role='navigation' or self::nav",heading:"@role='heading' or self::h1 or self::h2 or self::h3 or self::h4 or self::h5 or self::h6",button:"self::button or @role='button' or @type='button' or @type='submit'",checkbox:"(self::input and @type='checkbox') or @role='checkbox'",switch:"(self::input and @type='checkbox') or @role='switch' or (self::button and (contains(@class, 'switch') or @data-state))",slider:"self::input[@type='range'] or @role='slider'",datepicker:"self::input and @type='date'",colorpicker:"self::input and @type='color'",radio:"(self::input and @type='radio') or @role='radio'",dropdown:"(self::select[descendant::option] or @role='combobox' or @role='listbox' or contains(@class, 'dropdown') or contains(@class, 'trigger') or ancestor::*[contains(@class, 'dropdown') or @role='combobox'])",textbox:"self::textarea or (self::input and (@type='text' or @type='password' or @type='search' or @type='email' or @type='number' or @type='tel' or @type='url')) or @role='textbox'",file:"self::input and @type='file'",list:"self::ul or self::ol or @role='list'",listitem:"self::li or @role='listitem'",menu:"self::menu or @role='menu'",menuitem:"@role='menuitem'",toolbar:"@role='toolbar'",dialog:"@role='dialog'",table:"self::table or @role='table'",row:"self::tr or @role='row'",column:"self::td or self::th or @role='cell' or @role='gridcell' or @role='columnheader'",cell:"self::td or @role='cell' or @role='gridcell'",image:"self::img or @role='img' or @alt",element:"true()"};var O=["placeholder","value","data-test-id","data-testid","id","resource-id","name","aria-label","hint","title","tooltip","alt","src","aria-labelledby"];var h={selfWithTag:/^self::([a-zA-Z0-9-]+)(?:\[([^\]]+)\])?$/,contains:/contains\(@([a-zA-Z0-9-]+),\s*['"]([^'"]+)['"]\)/i,attrEquals:/@([a-zA-Z0-9-]+)\s*=\s*['"]([^'"]*)['"]/,attrExists:/^@([a-zA-Z0-9-]+)$/,descendant:/descendant::([a-zA-Z0-9-]+)/i,ancestor:/ancestor::\*\[([^\]]+)\]/i,operatorOr:/^\s*\bor\b\s*/i,operatorAnd:/^\s*\band\b\s*/i},Y=100,I=new Map;for(let[e,t]of Object.entries(S))t==="true()"?I.set(e,()=>!0):I.set(e,n=>p(t,n));var y=O;function Z(e){if(!Array.isArray(e))throw new TypeError("attributes must be an array");y=e}function W(){return[...y]}function p(e,t,n=0){if(e==null||t==null)return!1;if(n>Y)throw new Error("XPath expression exceeds maximum recursion depth");if(e=e.trim(),e==="true()")return!0;if(e[0]==="("&&e[e.length-1]===")"){let s=1,a=!0;for(let l=1;l<e.length-1;l++)if(e[l]==="("?s++:e[l]===")"&&s--,s===0){a=!1;break}if(a)return p(e.slice(1,-1),t,n+1)}let o=T(e,"or");if(o.length>1){for(let s of o)if(p(s,t,n+1))return!0;return!1}let r=T(e,"and");if(r.length>1){for(let s of r)if(!p(s,t,n+1))return!1;return!0}return k(e,t,n)}function T(e,t){let n=[],o=0,r="",s=!1,a="",l=t==="or"?h.operatorOr:h.operatorAnd;for(let i=0;i<e.length;i++){let f=e[i];if((f==="'"||f==='"')&&(i===0||e[i-1]!=="\\")&&(s?f===a&&(s=!1):(s=!0,a=f)),!s&&(f==="("?o++:f===")"&&o--,o===0)){let u=e.slice(i).match(l);if(u){n.push(r.trim()),i+=u[0].length-1,r="";continue}}r+=f}return r.trim()&&n.push(r.trim()),n}function k(e,t,n=0){if(e==null||t==null)return!1;e=e.trim();let o=e.match(h.selfWithTag);if(o){let f=o[1].toUpperCase();return t.tagName!==f?!1:o[2]?p(o[2],t,n+1):!0}let r=e.match(h.contains);if(r)return(t.getAttribute(r[1])||"").toLowerCase().includes(r[2].toLowerCase());let s=e.match(h.attrEquals);if(s)return t.getAttribute(s[1])===s[2];let a=e.match(h.attrExists);if(a)return t.hasAttribute(a[1]);let l=e.match(h.descendant);if(l)return t.querySelector(l[1])!==null;let i=e.match(h.ancestor);if(i){let f=t.parentElement;for(;f;){if(p(i[1],f,n+1))return!0;f=f.parentElement}return!1}return!1}var g=Object.freeze(S);function R(e){let t="";for(let n=0;n<e.childNodes.length;n++){let o=e.childNodes[n];o.nodeType===Node.TEXT_NODE&&(t+=o.textContent)}return t.trim()}function H(e){if(e.tagName==="STYLE"||e.tagName==="SCRIPT"||e.querySelector("STYLE, SCRIPT"))return!0;let t=e.parentElement;for(;t;){if(t.tagName==="STYLE"||t.tagName==="SCRIPT")return!0;t=t.parentElement}return!1}function E(e,t,n=!1){if(e==null)return!1;if(t==null||t==="")return!0;if(H(e))return!1;let o=y;for(let a=0;a<o.length;a++){let l=o[a],i;try{i=e.getAttribute(l)}catch(f){continue}if(i&&(n?i===t:i.includes(t)))return!0}let r=R(e);if(n?r===t:r.includes(t))return!0;let s=e.textContent;return!!(n?s.trim()===t:s.includes(t))}function w(e,t){if(e==null)return!1;let n=I.get(t);return n?n(e):!1}function b(e=document){let t=[];if(e==null)return t;let n=e.nodeType===Node.DOCUMENT_NODE?e.documentElement:e;if(!n)return t;let o=[n];for(;o.length>0;){let r=o.pop();if(r.nodeType!==Node.ELEMENT_NODE||r.tagName==="SCRIPT"||r.tagName==="STYLE")continue;t.push(r);let s=r.children;for(let a=s.length-1;a>=0;a--)o.push(s[a]);try{if(r.shadowRoot){let a=r.shadowRoot.children;for(let l=a.length-1;l>=0;l--)o.push(a[l])}}catch(a){}}return t}function N(e=window){let t=[];try{t.push({window:e,document:e.document,isMainFrame:!0,frameIndex:-1});let n=e.document.querySelectorAll("iframe");for(let o=0;o<n.length;o++){let r=n[o];try{r.contentWindow&&r.contentDocument&&t.push({window:r.contentWindow,document:r.contentDocument,isMainFrame:!1,frameElement:r,frameIndex:o})}catch(s){s.name==="SecurityError"?console.warn("Skipping cross-origin iframe:",s.message):console.warn("Error accessing iframe:",s.message)}}}catch(n){console.warn("Error getting frames:",n.message)}return t}function x(e){let t=e.getBoundingClientRect();return{x:t.x,y:t.y,width:t.width,height:t.height,top:t.top,bottom:t.bottom,left:t.left,right:t.right,midx:t.x+t.width/2,midy:t.y+t.height/2,tagName:e.tagName.toLowerCase()}}function L(e="element",t=null){if(e==null&&(e="element"),typeof e!="string")throw new TypeError(`type must be a string, got ${typeof e}`);if(e&&!g[e])return console.warn(`Unknown element type: ${e}. Valid types: ${Object.keys(g).join(", ")}`),{elements:[]};let n=[],o=N(window);for(let a of o){let l=b(t||a.document);for(let i=0;i<l.length;i++){let f=l[i];e&&!w(f,e)||n.push({element:f,frame:a})}}let r=[];if(n.length>0){let a=new Set(n.map(i=>i.element)),l=new Set;for(let i=n.length-1;i>=0;i--){let f=n[i],c=f.element;if(!l.has(c)){r.unshift(f);let u=c.parentElement;for(;u;)a.has(u)&&l.add(u),u=u.parentElement}}}return{elements:r.map(a=>{let l=x(a.element),i=a.element.tagName.toLowerCase();return a.frame.isMainFrame?{element:a.element,boundingBox:l,tagName:i,frameIndex:a.frame.frameIndex}:{boundingBox:l,tagName:i,frameIndex:a.frame.frameIndex}})}}function $(e,t=!1,n=null){if(e==null&&(e=""),typeof e!="string")throw new TypeError(`value must be a string, got ${typeof e}`);let o=[],r=N(window);for(let l of r){let i=b(n||l.document);for(let f=0;f<i.length;f++){let c=i[f];E(c,e,t)&&o.push({element:c,frame:l})}}return{elements:o.filter(l=>{let i=l.element;if(B(i,e,t))return!0;for(let c of o)if(c.element!==i&&i.contains(c.element))return!1;return!0}).map(l=>{let i=x(l.element),f=l.element.tagName.toLowerCase();return l.frame.isMainFrame?{element:l.element,boundingBox:i,tagName:f,frameIndex:l.frame.frameIndex}:{boundingBox:i,tagName:f,frameIndex:l.frame.frameIndex}})}}function B(e,t,n=!1){if(t==null||t==="")return!0;let o=y;for(let s=0;s<o.length;s++){let a=o[s],l;try{l=e.getAttribute(a)}catch(i){continue}if(l&&(n?l===t:l.includes(t)))return!0}let r=R(e);return!!(n?r===t:r.includes(t))}function G(e=null,t=null,n=!1,o=null){if(t==null&&(t=""),e!=null){if(typeof e!="string")throw new TypeError(`type must be a string, got ${typeof e}`);if(!g[e])return console.warn(`Unknown element type: ${e}. Valid types: ${Object.keys(g).join(", ")}`),{elements:[]}}if(t!==""&&typeof t!="string")throw new TypeError(`text must be a string, got ${typeof t}`);let r=[],s=N(window);for(let i of s){let f=b(o||i.document);for(let c=0;c<f.length;c++){let u=f[c];e!=null&&!w(u,e)||t!==""&&!E(u,t,n)||r.push({element:u,frame:i})}}return{elements:(t!==""?r.filter(i=>{let f=i.element;if(B(f,t,n))return!0;for(let u of r)if(u.element!==f&&f.contains(u.element))return!1;return!0}):r).map(i=>{let f=x(i.element),c=i.element.tagName.toLowerCase();return i.frame.isMainFrame?{element:i.element,boundingBox:f,tagName:c,frameIndex:i.frame.frameIndex}:{boundingBox:f,tagName:c,frameIndex:i.frame.frameIndex}})}}function C(e){if(e.parentElement)return e.parentElement;try{let t=e.getRootNode();if(t&&t.host)return t.host}catch(t){}return null}function Q(e){let t=C(e);if(!t)return[];if(t.shadowRoot)try{return Array.from(t.shadowRoot.children)}catch(n){return[]}return Array.from(t.children)}function J(e,t){let n=C(e);for(;n;){if(w(n,t))return n;n=C(n)}let o=e.children||[];for(let s of o)if(w(s,t))return s;let r=Q(e);for(let s of r)if(s!==e&&w(s,t))return s;return null}function K(e,t,n=!1,o=null){let r=e!=null&&e!=="",s=t!=null&&t!=="";if(r&&!s)return L(e,o);if(!r&&s)return $(t,n,o);if(r){if(typeof e!="string")throw new TypeError(`elementType must be a string, got ${typeof e}`);if(!g[e])return console.warn(`Unknown element type: ${e}. Valid types: ${Object.keys(g).join(", ")}`),{elements:[]}}if(s&&typeof t!="string")throw new TypeError(`attributeText must be a string, got ${typeof t}`);let a=[],l=N(window);for(let c of l){let u=b(o||c.document);for(let d=0;d<u.length;d++){let m=u[d];r&&!w(m,e)||s&&!E(m,t,n)||a.push({element:m,frame:c})}}if(a.length===0&&r&&s){let c=[];for(let d of l){let m=b(o||d.document);for(let A=0;A<m.length;A++){let D=m[A];E(D,t,n)&&c.push({element:D,frame:d})}}let u=new Set;for(let d of c){let m=J(d.element,e);m&&!u.has(m)&&(u.add(m),a.push({element:m,frame:d.frame}))}}return{elements:(s?a.filter(c=>{let u=c.element;if(B(u,t,n))return!0;for(let m of a)if(m.element!==u&&u.contains(m.element))return!1;return!0}):a).map(c=>{let u=x(c.element),d=c.element.tagName.toLowerCase();return c.frame.isMainFrame?{element:c.element,boundingBox:u,tagName:d,frameIndex:c.frame.frameIndex}:{boundingBox:u,tagName:d,frameIndex:c.frame.frameIndex}})}}function q(e){return e?e&&e.elements&&Array.isArray(e.elements)?e.elements:Array.isArray(e)?e:[e]:[]}function v(e,t="red",n=3){let o=q(e);for(let r=0;r<o.length;r++){let s=o[r],a=s.element?s.element:s;a&&a.style&&(a.style.outline=`${n}px solid ${t}`,a.style.outlineOffset="2px",a.style.boxShadow="0 0 0 2px rgba(255, 255, 255, 0.8)",a.classList.add("elementfinder-highlighted"))}}function ee(e){let t=q(e);for(let n=0;n<t.length;n++){let o=t[n],r=o.element?o.element:o;r&&r.style&&(r.style.outline="",r.style.outlineOffset="",r.style.boxShadow="",r.classList.remove("elementfinder-highlighted"))}}function te(){return Object.keys(g)}function ne(){return[...y]}return V(re);})();
|
package/package.json
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nodebug/browser-element-finder",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.5",
|
|
4
4
|
"description": "Browser Element Finder - Find elements by type and text content",
|
|
5
|
-
"main": "index.js",
|
|
6
|
-
"browser": "index.js",
|
|
7
5
|
"exports": {
|
|
8
6
|
".": {
|
|
9
7
|
"browser": "./index.js",
|
|
10
8
|
"require": "./index.js",
|
|
11
|
-
"import": "./
|
|
9
|
+
"import": "./src/element-finder.js",
|
|
10
|
+
"default": "./index.js"
|
|
11
|
+
},
|
|
12
|
+
"./min": {
|
|
13
|
+
"browser": "./index.min.js",
|
|
14
|
+
"require": "./index.min.js",
|
|
15
|
+
"import": "./index.min.js",
|
|
16
|
+
"default": "./index.min.js"
|
|
12
17
|
},
|
|
13
18
|
"./element-definitions.json": {
|
|
14
19
|
"browser": "./src/element-definitions.json",
|
|
@@ -25,6 +30,7 @@
|
|
|
25
30
|
},
|
|
26
31
|
"files": [
|
|
27
32
|
"index.js",
|
|
33
|
+
"index.min.js",
|
|
28
34
|
"src/element-definitions.json",
|
|
29
35
|
"src/searchable-attributes.json"
|
|
30
36
|
],
|
|
@@ -6,9 +6,11 @@
|
|
|
6
6
|
"checkbox": "(self::input and @type='checkbox') or @role='checkbox'",
|
|
7
7
|
"switch": "(self::input and @type='checkbox') or @role='switch' or (self::button and (contains(@class, 'switch') or @data-state))",
|
|
8
8
|
"slider": "self::input[@type='range'] or @role='slider'",
|
|
9
|
+
"datepicker": "self::input and @type='date'",
|
|
10
|
+
"colorpicker": "self::input and @type='color'",
|
|
9
11
|
"radio": "(self::input and @type='radio') or @role='radio'",
|
|
10
12
|
"dropdown": "(self::select[descendant::option] or @role='combobox' or @role='listbox' or contains(@class, 'dropdown') or contains(@class, 'trigger') or ancestor::*[contains(@class, 'dropdown') or @role='combobox'])",
|
|
11
|
-
"textbox": "self::textarea or (self::input and (@type='text' or @type='password' or @type='search' or @type='email')) or @role='textbox'",
|
|
13
|
+
"textbox": "self::textarea or (self::input and (@type='text' or @type='password' or @type='search' or @type='email' or @type='number' or @type='tel' or @type='url')) or @role='textbox'",
|
|
12
14
|
"file": "self::input and @type='file'",
|
|
13
15
|
"list": "self::ul or self::ol or @role='list'",
|
|
14
16
|
"listitem": "self::li or @role='listitem'",
|
|
@@ -19,6 +21,7 @@
|
|
|
19
21
|
"table": "self::table or @role='table'",
|
|
20
22
|
"row": "self::tr or @role='row'",
|
|
21
23
|
"column": "self::td or self::th or @role='cell' or @role='gridcell' or @role='columnheader'",
|
|
24
|
+
"cell": "self::td or @role='cell' or @role='gridcell'",
|
|
22
25
|
"image": "self::img or @role='img' or @alt",
|
|
23
26
|
"element": "true()"
|
|
24
27
|
}
|