@runtypelabs/persona 3.22.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1875 +1,23 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1
+ "use strict";var M=Object.defineProperty;var tt=Object.getOwnPropertyDescriptor;var et=Object.getOwnPropertyNames;var nt=Object.prototype.hasOwnProperty;var rt=(s,e,t)=>e in s?M(s,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):s[e]=t;var st=(s,e)=>{for(var t in e)M(s,t,{get:e[t],enumerable:!0})},ot=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of et(e))!nt.call(s,r)&&r!==t&&M(s,r,{get:()=>e[r],enumerable:!(n=tt(e,r))||n.enumerable});return s};var it=s=>ot(M({},"__esModule",{value:!0}),s);var R=(s,e,t)=>rt(s,typeof e!="symbol"?e+"":e,t);var wt={};st(wt,{collectSmartDomContext:()=>Z,createSmartDomReaderContextProvider:()=>$t,smartDomResultToEnriched:()=>k});module.exports=it(wt);var q=Object.defineProperty,at=Object.getOwnPropertyDescriptor,ct=Object.getOwnPropertyNames,B=Object.prototype.hasOwnProperty,T=(s,e)=>()=>(s&&(e=s(s=0)),e),lt=(s,e)=>{let t={};for(var n in s)q(t,n,{get:s[n],enumerable:!0});return e||q(t,Symbol.toStringTag,{value:"Module"}),t},ut=(s,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(var r=ct(e),i=0,a=r.length,o;i<a;i++)o=r[i],!B.call(s,o)&&o!==t&&q(s,o,{get:(c=>e[c]).bind(null,o),enumerable:!(n=at(e,o))||n.enumerable});return s},dt=s=>B.call(s,"module.exports")?s["module.exports"]:ut(q({},"__esModule",{value:!0}),s),ft=void 0,w,z=T((()=>{w=class v{static findMainContent(e){let t=e.querySelector('main, [role="main"]');return t||(e.body?v.detectMainContent(e.body):e.documentElement)}static detectMainContent(e){let t=[];if(v.collectCandidates(e,t,15),t.length===0)return e;t.sort((r,i)=>v.calculateContentScore(i)-v.calculateContentScore(r));let n=t[0];for(let r=1;r<t.length;r++){let i=t[r];!t.some((a,o)=>o!==r&&a.contains(i))&&v.calculateContentScore(i)>v.calculateContentScore(n)&&(n=i)}return n}static collectCandidates(e,t,n){v.calculateContentScore(e)>=n&&t.push(e),Array.from(e.children).forEach(r=>{v.collectCandidates(r,t,n)})}static calculateContentScore(e){var d;let t=0,n=["article","content","main-container","main","main-content","post","entry"],r=["content","main","article","post","entry"];n.forEach(f=>{e.classList.contains(f)&&(t+=10)}),r.forEach(f=>{var h;(h=e.id)!=null&&h.toLowerCase().includes(f)&&(t+=10)});let i=e.tagName.toLowerCase();["article","main","section"].includes(i)&&(t+=8);let a=e.getElementsByTagName("p").length;t+=Math.min(a*2,10);let o=e.querySelectorAll("h1, h2, h3").length;t+=Math.min(o*3,9);let c=((d=e.textContent)==null?void 0:d.trim().length)||0;c>300&&(t+=Math.min(Math.floor(c/300)*2,10));let l=v.calculateLinkDensity(e);l<.3?t+=5:l>.5&&(t-=5),(e.hasAttribute("data-main")||e.hasAttribute("data-content")||e.hasAttribute("itemprop"))&&(t+=8);let u=e.getAttribute("role");return(u==="main"||u==="article")&&(t+=10),e.matches("aside, nav, header, footer, .sidebar, .navigation, .menu, .ad, .advertisement")&&(t-=10),e.getElementsByTagName("form").length>2&&(t-=5),Math.max(0,t)}static calculateLinkDensity(e){var i,a;let t=e.getElementsByTagName("a"),n=0;for(let o of Array.from(t))n+=((i=o.textContent)==null?void 0:i.length)||0;let r=((a=e.textContent)==null?void 0:a.length)||1;return n/r}static isNavigation(e){if(e.tagName.toLowerCase()==="nav"||e.getAttribute("role")==="navigation")return!0;let t=[/nav/i,/menu/i,/sidebar/i,/toolbar/i],n=`${e.className} ${e.id}`.toLowerCase();return t.some(r=>r.test(n))}static isSupplementary(e){if(e.tagName.toLowerCase()==="aside"||e.getAttribute("role")==="complementary")return!0;let t=[/sidebar/i,/widget/i,/related/i,/advertisement/i,/social/i],n=`${e.className} ${e.id}`.toLowerCase();return t.some(r=>r.test(n))}static detectLandmarks(e){let t={navigation:[],main:[],complementary:[],contentinfo:[],banner:[],search:[],form:[],region:[]};for(let[n,r]of Object.entries({navigation:'nav, [role="navigation"]',main:'main, [role="main"]',complementary:'aside, [role="complementary"]',contentinfo:'footer, [role="contentinfo"]',banner:'header, [role="banner"]',search:'[role="search"]',form:'form[aria-label], form[aria-labelledby], [role="form"]',region:'section[aria-label], section[aria-labelledby], [role="region"]'})){let i=e.querySelectorAll(r);t[n]=Array.from(i)}return t}}})),E,P=T((()=>{E=class S{static generateSelectors(e){var p;let t=e.ownerDocument||document,n=[];e.id&&S.isUniqueId(e.id,t)&&n.push({type:"id",value:`#${CSS.escape(e.id)}`,score:100});let r=S.getDataTestId(e);if(r){let m=`[data-testid="${CSS.escape(r)}"]`;n.push({type:"data-testid",value:m,score:90+(S.isUniqueSelectorSafe(m,t)?5:0)})}let i=e.getAttribute("role"),a=e.getAttribute("aria-label");if(i&&a){let m=`[role="${CSS.escape(i)}"][aria-label="${CSS.escape(a)}"]`;n.push({type:"role-aria",value:m,score:85+(S.isUniqueSelectorSafe(m,t)?5:0)})}let o=e.getAttribute("name");if(o){let m=`[name="${CSS.escape(o)}"]`;n.push({type:"name",value:m,score:78+(S.isUniqueSelectorSafe(m,t)?5:0)})}let c=S.generateCSSSelector(e,t),l=(c.match(/:nth-child\(/g)||[]).length*10,u=c.includes(".")?8:0,d=Math.max(0,70+u-l);n.push({type:"class-path",value:c,score:d});let f=S.generateXPath(e,t);n.push({type:"xpath",value:f,score:40});let h=S.generateTextBasedSelector(e);h&&n.push({type:"text",value:h,score:30}),n.sort((m,x)=>x.score-m.score);let g={css:((p=n.find(m=>m.type!=="xpath"&&m.type!=="text"))==null?void 0:p.value)||c,xpath:f,candidates:n};return h&&(g.textBased=h),r&&(g.dataTestId=r),a&&(g.ariaLabel=a),g}static generateCSSSelector(e,t){var a;if(e.id&&S.isUniqueId(e.id,t))return`#${CSS.escape(e.id)}`;let n=S.getDataTestId(e);if(n)return`[data-testid="${CSS.escape(n)}"]`;let r=[],i=e;for(;i&&i.nodeType===Node.ELEMENT_NODE;){let o=i.nodeName.toLowerCase();if(i.id&&S.isUniqueId(i.id,t)){o=`#${CSS.escape(i.id)}`,r.unshift(o);break}let c=S.getMeaningfulClasses(i);c.length>0&&(o+=`.${c.map(u=>CSS.escape(u)).join(".")}`);let l=(a=i.parentElement)==null?void 0:a.children;if(l&&l.length>1){let u=Array.from(l).indexOf(i);(u>0||!S.isUniqueSelector(o,i.parentElement))&&(o+=`:nth-child(${u+1})`)}r.unshift(o),i=i.parentElement}return S.optimizePath(r,e,t)}static generateXPath(e,t){var i;if(e.id&&S.isUniqueId(e.id,t))return`//*[@id="${e.id}"]`;let n=[],r=e;for(;r&&r.nodeType===Node.ELEMENT_NODE;){let a=r.nodeName.toLowerCase();if(r.id&&S.isUniqueId(r.id,t)){n.unshift(`//*[@id="${r.id}"]`);break}let o=a,c=(i=r.parentElement)==null?void 0:i.children;if(c){let l=Array.from(c).filter(u=>u.nodeName.toLowerCase()===a);if(l.length>1){let u=l.indexOf(r)+1;o+=`[${u}]`}}n.unshift(o),r=r.parentElement}return`//${n.join("/")}`}static generateTextBasedSelector(e){var r;let t=(r=e.textContent)==null?void 0:r.trim();if(!t||t.length>50)return;let n=e.nodeName.toLowerCase();if(["button","a","label"].includes(n))return`${n}:contains("${t.replace(/['"\\]/g,"\\$&")}")`}static getDataTestId(e){return e.getAttribute("data-testid")||e.getAttribute("data-test-id")||e.getAttribute("data-test")||e.getAttribute("data-cy")||void 0}static isUniqueId(e,t){return t.querySelectorAll(`#${CSS.escape(e)}`).length===1}static isUniqueSelector(e,t){try{return t.querySelectorAll(e).length===1}catch{return!1}}static isUniqueSelectorSafe(e,t){try{return t.querySelectorAll(e).length===1}catch{return!1}}static getMeaningfulClasses(e){let t=Array.from(e.classList),n=[/^(p|m|w|h|text|bg|border|flex|grid|col|row)-/,/^(xs|sm|md|lg|xl|2xl):/,/^(hover|focus|active|disabled|checked):/,/^js-/,/^is-/,/^has-/];return t.filter(r=>r.length<3?!1:!n.some(i=>i.test(r))).slice(0,2)}static optimizePath(e,t,n){for(let r=0;r<e.length-1;r++){let i=e.slice(r).join(" > ");try{let a=n.querySelectorAll(i);if(a.length===1&&a[0]===t)return i}catch{}}return e.join(" > ")}static getContextPath(e){var a;let t=[],n=e,r=0,i=5;for(;n&&n!==((a=e.ownerDocument)==null?void 0:a.body)&&r<i;){let o=n.nodeName.toLowerCase(),c=o;if(n.id)c=`${o}#${n.id}`;else if(n.className&&typeof n.className=="string"){let u=n.className.split(" ")[0];u&&(c=`${o}.${u}`)}let l=n.getAttribute("role");l&&(c+=`[role="${l}"]`),t.unshift(c),n=n.parentElement,r++}return t}}})),b,_=T((()=>{var s;P(),b=(s=class{static isVisible(t,n){var a,o;let r=t.getBoundingClientRect(),i=n||((o=(a=t.ownerDocument)==null?void 0:a.defaultView)==null?void 0:o.getComputedStyle(t));return i?r.width>0&&r.height>0&&i.display!=="none"&&i.visibility!=="hidden"&&i.opacity!=="0"&&t.offsetParent!==null:!1}static isInViewport(t,n){var a,o,c,l;let r=t.getBoundingClientRect(),i=n||{width:((o=(a=t.ownerDocument)==null?void 0:a.defaultView)==null?void 0:o.innerWidth)||0,height:((l=(c=t.ownerDocument)==null?void 0:c.defaultView)==null?void 0:l.innerHeight)||0};return r.top<i.height&&r.bottom>0&&r.left<i.width&&r.right>0}static passesFilter(t,n){var a,o,c,l,u,d,f,h,g,p;if(!n)return!0;let r=t;if((a=n.excludeSelectors)!=null&&a.length){for(let m of n.excludeSelectors)if(t.matches(m))return!1}if((o=n.includeSelectors)!=null&&o.length){let m=!1;for(let x of n.includeSelectors)if(t.matches(x)){m=!0;break}if(!m)return!1}if((c=n.tags)!=null&&c.length&&!n.tags.includes(t.tagName.toLowerCase()))return!1;let i=((l=r.textContent)==null?void 0:l.toLowerCase())||"";if((u=n.textContains)!=null&&u.length){let m=!1;for(let x of n.textContains)if(i.includes(x.toLowerCase())){m=!0;break}if(!m)return!1}if((d=n.textMatches)!=null&&d.length){let m=!1;for(let x of n.textMatches)if(x.test(i)){m=!0;break}if(!m)return!1}if((f=n.hasAttributes)!=null&&f.length){for(let m of n.hasAttributes)if(!t.hasAttribute(m))return!1}if(n.attributeValues)for(let[m,x]of Object.entries(n.attributeValues)){let C=t.getAttribute(m);if(!C)return!1;if(typeof x=="string"){if(C!==x)return!1}else if(x instanceof RegExp&&!x.test(C))return!1}if((h=n.withinSelectors)!=null&&h.length){let m=!1;for(let x of n.withinSelectors)if(t.closest(x)){m=!0;break}if(!m)return!1}if((g=n.interactionTypes)!=null&&g.length){let m=s.getInteractionInfo(t),x=!1;for(let C of n.interactionTypes)if(m[C]){x=!0;break}if(!x)return!1}if(n.nearText){let m=t.parentElement;if(!m||!((p=m.textContent)!=null&&p.toLowerCase().includes(n.nearText.toLowerCase())))return!1}return!0}static extractElement(t,n,r=0){if(n.maxDepth&&r>n.maxDepth||!n.includeHidden&&!s.isVisible(t)||n.viewportOnly&&!s.isInViewport(t)||!s.passesFilter(t,n.filter))return null;let i=t,a={tag:t.tagName.toLowerCase(),text:s.getElementText(t,n),selector:E.generateSelectors(t),attributes:s.getRelevantAttributes(t,n),context:s.getElementContext(t),interaction:s.getInteractionInfo(t)};if(n.mode==="full"&&s.isSemanticContainer(t)){let o=[];if(n.includeShadowDOM&&i.shadowRoot){let l=s.extractChildren(i.shadowRoot,n,r+1);o.push(...l)}let c=s.extractChildren(t,n,r+1);o.push(...c),o.length>0&&(a.children=o)}return a}static extractChildren(t,n,r){let i=[],a=t.querySelectorAll("*");for(let o of Array.from(a)){if(s.hasExtractedAncestor(o,a))continue;let c=s.extractElement(o,n,r);c&&i.push(c)}return i}static hasExtractedAncestor(t,n){let r=t.parentElement;for(;r;){if(Array.from(n).includes(r))return!0;r=r.parentElement}return!1}static getRelevantAttributes(t,n){var c,l;let r=["id","class","name","type","value","placeholder","href","src","alt","title","action","method","aria-label","aria-describedby","aria-controls","role","disabled","readonly","required","checked","min","max","pattern","step","autocomplete","data-testid","data-test","data-cy"],i={},a=(c=n.attributeTruncateLength)!=null?c:100,o=(l=n.dataAttributeTruncateLength)!=null?l:50;for(let u of r){let d=t.getAttribute(u);d&&(i[u]=d.length>a?`${d.substring(0,a)}...`:d)}for(let u of t.attributes)u.name.startsWith("data-")&&!r.includes(u.name)&&(i[u.name]=u.value.length>o?`${u.value.substring(0,o)}...`:u.value);return i}static getElementContext(t){let n={parentChain:E.getContextPath(t)},r=t.closest("form");r&&(n.nearestForm=E.generateSelectors(r).css);let i=t.closest('section, [role="region"]');i&&(n.nearestSection=E.generateSelectors(i).css);let a=t.closest('main, [role="main"]');a&&(n.nearestMain=E.generateSelectors(a).css);let o=t.closest('nav, [role="navigation"]');return o&&(n.nearestNav=E.generateSelectors(o).css),n}static getInteractionInfo(t){let n=t,r={};(n.onclick||t.getAttribute("onclick")||t.matches('button, a[href], [role="button"], [tabindex]:not([tabindex="-1"])'))&&(r.click=!0),(n.onchange||t.getAttribute("onchange")||t.matches("input, select, textarea"))&&(r.change=!0),(n.onsubmit||t.getAttribute("onsubmit")||t.matches("form"))&&(r.submit=!0),t.matches('a[href], button[type="submit"]')&&(r.nav=!0),(n.hasAttribute("disabled")||n.getAttribute("aria-disabled")==="true")&&(r.disabled=!0),s.isVisible(t)||(r.hidden=!0);let i=t.getAttribute("role");if(i&&(r.role=i),t.matches("input, textarea, select, button")){let a=t.form||t.closest("form");a&&(r.form=E.generateSelectors(a).css)}return r}static getElementText(t,n){var a;if(t.matches("input, textarea")){let o=t;return o.value||o.placeholder||""}if(t.matches("img"))return t.alt||"";let r=((a=t.textContent)==null?void 0:a.trim())||"",i=n==null?void 0:n.textTruncateLength;return i&&r.length>i?`${r.substring(0,i)}...`:r}static isSemanticContainer(t){return t.matches('article, section, nav, aside, main, header, footer, form, table, ul, ol, dl, figure, details, dialog, [role="region"], [role="navigation"], [role="main"], [role="complementary"]')}static getInteractiveElements(t,n){let r=[],i=s.INTERACTIVE_SELECTORS.join(", "),a=t.querySelectorAll(i);for(let o of Array.from(a)){let c=s.extractElement(o,n);c&&r.push(c)}if(n.customSelectors)for(let o of n.customSelectors)try{let c=t.querySelectorAll(o);for(let l of Array.from(c)){let u=s.extractElement(l,n);u&&r.push(u)}}catch{console.warn(`Invalid custom selector: ${o}`)}return r}static getSemanticElements(t,n){let r=[],i=s.SEMANTIC_SELECTORS.join(", "),a=t.querySelectorAll(i);for(let o of Array.from(a)){let c=s.extractElement(o,n);c&&r.push(c)}return r}},R(s,"INTERACTIVE_SELECTORS",["button","a[href]",'input:not([type="hidden"])',"textarea","select",'[role="button"]',"[onclick]",'[contenteditable="true"]',"summary",'[tabindex]:not([tabindex="-1"])']),R(s,"SEMANTIC_SELECTORS",["h1","h2","h3","h4","h5","h6","article","section","nav","aside","main","header","footer","form","table","ul","ol","img[alt]","figure","video","audio",'[role="navigation"]','[role="main"]','[role="complementary"]','[role="contentinfo"]']),s)}));function $(s,e){let t=(s!=null?s:"").trim();if(!e||t.length<=e)return t;let n=["login","log in","sign in","sign up","submit","search","filter","add to cart","next","continue"],r=t.toLowerCase(),i=n.map(l=>({k:l,i:r.indexOf(l)})).find(l=>l.i>-1),a=Math.max(0,Math.floor(e*.66));if(i&&i.i>a){let l=Math.max(12,e-a-5),u=Math.max(0,i.i-Math.floor(l/2)),d=Math.min(t.length,u+l);return`${t.slice(0,a).trimEnd()} \u2026 ${t.slice(u,d).trim()}\u2026`}let o=t.slice(0,e),c=o.lastIndexOf(" ");return`${c>32?o.slice(0,c):o}\u2026`}function ht(s){var e;return((e=s.selector)==null?void 0:e.css)||""}function mt(s){let e=5381;for(let t=0;t<s.length;t++)e=e*33^s.charCodeAt(t);return`sec-${(e>>>0).toString(36)}`}function X(s){switch(s){case"header":return"\u{1F9ED}";case"navigation":return"\u{1F4D1}";case"main":return"\u{1F4C4}";case"sections":return"\u{1F5C2}\uFE0F";case"sidebar":return"\u{1F4DA}";case"footer":return"\u{1F53B}";case"modals":return"\u{1F4AC}";default:return"\u{1F539}"}}function O(s,e){var o,c,l,u,d;let t=$(s.text||((o=s.attributes)==null?void 0:o.ariaLabel),(c=e==null?void 0:e.maxTextLength)!=null?c:80),n=ht(s),r=s.tag.toLowerCase(),i=(l=s.interaction)!=null&&l.submit?"submit":(u=s.interaction)!=null&&u.click?"click":(d=s.interaction)!=null&&d.change?"change":void 0,a=i?` (${i})`:"";return`- ${r.toUpperCase()}: ${t||"(no text)"} \u2192 \`${n}\`${a}`}function gt(s){let e=[];e.push(...s.buttons.map(o=>{var c;return((c=o.selector)==null?void 0:c.css)||""})),e.push(...s.links.map(o=>{var c;return((c=o.selector)==null?void 0:c.css)||""})),e.push(...s.inputs.map(o=>{var c;return((c=o.selector)==null?void 0:c.css)||""})),e.push(...s.clickable.map(o=>{var c;return((c=o.selector)==null?void 0:c.css)||""}));let t=e.length||1,n=e.filter(o=>o.startsWith("#")).length,r=e.filter(o=>/\[data-testid=/.test(o)).length,i=e.filter(o=>/:nth-child\(/.test(o)).length,a=n+r;return`Selector quality: ${Math.round(a/t*100)}% stable (ID/data-testid), ${Math.round(i/t*100)}% structural (:nth-child)`}function pt(s,e){var r,i;let t=[],n=a=>typeof(e==null?void 0:e.maxElements)=="number"?a.slice(0,e.maxElements):a;if(s.buttons.length){t.push("Buttons:");for(let a of n(s.buttons))t.push(O(a,e))}if(s.links.length){t.push("Links:");for(let a of n(s.links))t.push(O(a,e))}if(s.inputs.length){t.push("Inputs:");for(let a of n(s.inputs))t.push(O(a,e))}if(s.clickable.length){t.push("Other Clickable:");for(let a of n(s.clickable))t.push(O(a,e))}if(s.forms.length){t.push("Forms:");for(let a of n(s.forms))t.push(`- FORM: action=${(r=a.action)!=null?r:"-"} method=${(i=a.method)!=null?i:"-"} \u2192 \`${a.selector}\``)}return t.join(`
2
+ `)}function V(s){var a,o;let e=X("region"),t=mt(`${s.selector}|${(a=s.label)!=null?a:""}|${(o=s.role)!=null?o:""}`),n=s.label?` ${s.label}`:"",r=[];s.buttonCount&&r.push(`${s.buttonCount} buttons`),s.linkCount&&r.push(`${s.linkCount} links`),s.inputCount&&r.push(`${s.inputCount} inputs`),s.textPreview&&r.push(`\u201C${$(s.textPreview,80)}\u201D`);let i=r.length?` \u2014 ${r.join(", ")}`:"";return`${e} ${n} \u2192 \`${s.selector}\` [${t}]${i}`}function N(s,e,t="section"){return`<page ${[e!=null&&e.title?`title="${U(e==null?void 0:e.title)}"`:null,e!=null&&e.url?`url="${U(e==null?void 0:e.url)}"`:null].filter(Boolean).join(" ")}>
3
+ <${t}><![CDATA[
4
+ ${s}
5
+ ]]></${t}>
6
+ </page>`}function U(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function W(s){return s.charAt(0).toUpperCase()+s.slice(1)}var G,xt=T((()=>{G=class{static structure(s,e={},t){var a,o,c;let n=[];n.push("# Page Outline"),(t!=null&&t.title||t!=null&&t.url)&&(n.push(`Title: ${(a=t==null?void 0:t.title)!=null?a:""}`.trim()),n.push(`URL: ${(o=t==null?void 0:t.url)!=null?o:""}`.trim())),n.push("");let r=s.regions,i=[["header",r.header],["navigation",r.navigation],["main",r.main],["sections",r.sections],["sidebar",r.sidebar],["footer",r.footer],["modals",r.modals]];for(let[l,u]of i){if(!u)continue;let d=X(l);if(Array.isArray(u)){if(!u.length)continue;n.push(`## ${d} ${W(l)}`);for(let f of u)n.push(V(f))}else n.push(`## ${d} ${W(l)}`),n.push(V(u));n.push("")}if((c=s.suggestions)!=null&&c.length){n.push("## Suggestions");for(let l of s.suggestions)n.push(`- ${l}`);n.push("")}return n.push("Next: choose a region (by selector or [sectionId]) and call dom_extract_region for actionable details."),N(n.join(`
7
+ `),t,"outline")}static region(s,e={},t){var o,c,l;let n=[];n.push("# Region Details"),(t!=null&&t.title||t!=null&&t.url)&&(n.push(`Title: ${(o=t==null?void 0:t.title)!=null?o:""}`.trim()),n.push(`URL: ${(c=t==null?void 0:t.url)!=null?c:""}`.trim())),n.push("");let r=s.interactive;if(s.page){let u=[s.page.hasErrors?"errors: yes":"errors: no",s.page.isLoading?"loading: yes":"loading: no",s.page.hasModals?"modals: yes":"modals: no"];n.push(`Page state: ${u.join(", ")}`)}let i=[],a=u=>u?u.length:0;return i.push(`${a(r.buttons)} buttons`),i.push(`${a(r.links)} links`),i.push(`${a(r.inputs)} inputs`),(l=r.forms)!=null&&l.length&&i.push(`${a(r.forms)} forms`),n.push(`Summary: ${i.join(", ")}`),n.push(gt(r)),n.push(""),n.push(pt(r,e)),n.push(""),n.push("Next: write a script using the most stable selectors above. If selectors look unstable, rerun dom_extract_region with higher detail or call dom_extract_content for text context."),N(n.join(`
8
+ `),t,"section")}static content(s,e={},t){var r,i,a,o,c,l,u,d,f;let n=[];if(n.push("# Content"),n.push(`Selector: \`${s.selector}\``),n.push(""),(r=s.text.headings)!=null&&r.length){n.push("Headings:");for(let h of s.text.headings)n.push(`- H${h.level}: ${$(h.text,(i=e.maxTextLength)!=null?i:120)}`);n.push("")}if((a=s.text.paragraphs)!=null&&a.length){let h=typeof e.maxElements=="number"?e.maxElements:s.text.paragraphs.length;n.push("Paragraphs:");for(let g of s.text.paragraphs.slice(0,h))n.push(`- ${$(g,(o=e.maxTextLength)!=null?o:200)}`);n.push("")}if((c=s.text.lists)!=null&&c.length){n.push("Lists:");for(let h of s.text.lists){n.push(`- ${h.type.toUpperCase()}:`);let g=typeof e.maxElements=="number"?e.maxElements:h.items.length;for(let p of h.items.slice(0,g))n.push(` - ${$(p,(l=e.maxTextLength)!=null?l:120)}`)}n.push("")}if((u=s.tables)!=null&&u.length){n.push("Tables:");for(let h of s.tables){n.push(`- Headers: ${h.headers.join(" | ")}`);let g=typeof e.maxElements=="number"?e.maxElements:h.rows.length;for(let p of h.rows.slice(0,g))n.push(` - ${p.join(" | ")}`)}n.push("")}if((d=s.media)!=null&&d.length){n.push("Media:");let h=typeof e.maxElements=="number"?e.maxElements:s.media.length;for(let g of s.media.slice(0,h))n.push(`- ${g.type.toUpperCase()}: ${(f=g.alt)!=null?f:""} ${g.src?`\u2192 ${g.src}`:""}`.trim());n.push("")}return n.push("Next: if text is insufficient for targeting, call dom_extract_region for interactive selectors."),N(n.join(`
9
+ `),t,"content")}}}));function bt(){if(typeof window!="undefined"){let s=window,e=s.SmartDOMReader;if(typeof e=="function")return e;let t=s.SmartDOMReaderNamespace;if(t&&typeof t.SmartDOMReader=="function")return t.SmartDOMReader}try{if(typeof ft=="function"){let s=(Y(),dt(Et));if(s&&typeof s.SmartDOMReader=="function")return s.SmartDOMReader;if(s&&typeof s.default=="function")return s.default}}catch{}}var K,yt=T((()=>{z(),P(),_(),K=class y{static extractStructure(e){let t={},n=e.querySelector('header, [role="banner"], .header, #header');n&&(t.header=y.analyzeRegion(n));let r=e.querySelectorAll('nav, [role="navigation"], .nav, .navigation');if(r.length>0&&(t.navigation=Array.from(r).map(d=>y.analyzeRegion(d))),e instanceof Document){let d=w.findMainContent(e);if(d){t.main=y.analyzeRegion(d);let f=d.querySelectorAll('section, article, [role="region"]');f.length>0&&(t.sections=Array.from(f).filter(h=>!h.closest("nav, header, footer")).map(h=>y.analyzeRegion(h)))}}else{t.main=y.analyzeRegion(e);let d=e.querySelectorAll('section, article, [role="region"]');d.length>0&&(t.sections=Array.from(d).filter(f=>!f.closest("nav, header, footer")).map(f=>y.analyzeRegion(f)))}let i=e.querySelectorAll('aside, [role="complementary"], .sidebar, #sidebar');i.length>0&&(t.sidebar=Array.from(i).map(d=>y.analyzeRegion(d)));let a=e.querySelector('footer, [role="contentinfo"], .footer, #footer');a&&(t.footer=y.analyzeRegion(a));let o=e.querySelectorAll('[role="dialog"], .modal, .popup, .overlay'),c=Array.from(o).filter(d=>b.isVisible(d));c.length>0&&(t.modals=c.map(d=>y.analyzeRegion(d)));let l=y.extractFormOverview(e),u=y.calculateSummary(e,t,l);return{regions:t,forms:l,summary:u,suggestions:y.generateSuggestions(t,u)}}static extractRegion(e,t,n={},r){let i=t.querySelector(e);if(!i)return null;let a=r!=null?r:bt();if(!a)throw new Error("SmartDOMReader is unavailable. Ensure the Smart DOM Reader module is loaded before calling extractRegion.");return new a(n).extract(i,n)}static extractContent(e,t,n={}){let r=t.querySelector(e);if(!r)return null;let i={selector:e,text:{},metadata:{wordCount:0,hasInteractive:!1}};if(n.includeHeadings!==!1){let c=r.querySelectorAll("h1, h2, h3, h4, h5, h6");i.text.headings=Array.from(c).map(l=>({level:Number.parseInt(l.tagName[1],10),text:y.getTextContent(l,n.maxTextLength)}))}let a=r.querySelectorAll("p");if(a.length>0&&(i.text.paragraphs=Array.from(a).map(c=>y.getTextContent(c,n.maxTextLength)).filter(c=>c.length>0)),n.includeLists!==!1){let c=r.querySelectorAll("ul, ol");i.text.lists=Array.from(c).map(l=>({type:l.tagName.toLowerCase(),items:Array.from(l.querySelectorAll("li")).map(u=>y.getTextContent(u,n.maxTextLength))}))}if(n.includeTables!==!1){let c=r.querySelectorAll("table");i.tables=Array.from(c).map(l=>({headers:Array.from(l.querySelectorAll("th")).map(u=>y.getTextContent(u)),rows:Array.from(l.querySelectorAll("tr")).filter(u=>u.querySelector("td")).map(u=>Array.from(u.querySelectorAll("td")).map(d=>y.getTextContent(d)))}))}if(n.includeMedia!==!1){let c=r.querySelectorAll("img"),l=r.querySelectorAll("video"),u=r.querySelectorAll("audio");i.media=[...Array.from(c).map(d=>{let f={type:"img"},h=d.getAttribute("alt"),g=d.getAttribute("src");return h&&(f.alt=h),g&&(f.src=g),f}),...Array.from(l).map(d=>{let f={type:"video"},h=d.getAttribute("src");return h&&(f.src=h),f}),...Array.from(u).map(d=>{let f={type:"audio"},h=d.getAttribute("src");return h&&(f.src=h),f})]}let o=r.textContent||"";return i.metadata.wordCount=o.trim().split(/\s+/).length,i.metadata.hasInteractive=r.querySelectorAll("button, a, input, textarea, select").length>0,i}static analyzeRegion(e){var x,C,H,j;let t=E.generateSelectors(e).css,n=e.querySelectorAll('button, [role="button"]'),r=e.querySelectorAll("a[href]"),i=e.querySelectorAll("input, textarea, select"),a=e.querySelectorAll("form"),o=e.querySelectorAll("ul, ol"),c=e.querySelectorAll("table"),l=e.querySelectorAll("img, video, audio"),u=n.length+r.length+i.length,d,f=e.getAttribute("aria-label");if(f)d=f;else if(e.getAttribute("aria-labelledby")){let L=e.getAttribute("aria-labelledby");if(L){let F=(x=e.ownerDocument)==null?void 0:x.getElementById(L);F&&(d=(C=F.textContent)==null?void 0:C.trim())}}else{let L=e.querySelector("h1, h2, h3");L&&(d=(H=L.textContent)==null?void 0:H.trim())}let h=((j=e.textContent)==null?void 0:j.trim())||"",g=h.length>50?`${h.substring(0,50)}...`:h,p={selector:t,interactiveCount:u,hasForm:a.length>0,hasList:o.length>0,hasTable:c.length>0,hasMedia:l.length>0};d&&(p.label=d);let m=e.getAttribute("role");return m&&(p.role=m),n.length>0&&(p.buttonCount=n.length),r.length>0&&(p.linkCount=r.length),i.length>0&&(p.inputCount=i.length),g.length>0&&(p.textPreview=g),p}static extractFormOverview(e){let t=e.querySelectorAll("form");return Array.from(t).map(n=>{var g,p,m;let r=n.querySelectorAll("input, textarea, select"),i=E.generateSelectors(n).css,a="unknown";n.closest('header, [role="banner"]')?a="header":n.closest('nav, [role="navigation"]')?a="navigation":n.closest('main, [role="main"]')?a="main":n.closest('aside, [role="complementary"]')?a="sidebar":n.closest('footer, [role="contentinfo"]')&&(a="footer");let o,c=(g=n.getAttribute("id"))==null?void 0:g.toLowerCase(),l=(p=n.getAttribute("class"))==null?void 0:p.toLowerCase(),u=(m=n.getAttribute("action"))==null?void 0:m.toLowerCase(),d=n.querySelector('input[type="email"]'),f=n.querySelector('input[type="password"]');n.querySelector('input[type="search"]')||c!=null&&c.includes("search")||l!=null&&l.includes("search")?o="search":f&&d?o="login":f?o="authentication":c!=null&&c.includes("contact")||l!=null&&l.includes("contact")?o="contact":c!=null&&c.includes("subscribe")||l!=null&&l.includes("subscribe")?o="subscription":(u!=null&&u.includes("checkout")||l!=null&&l.includes("checkout"))&&(o="checkout");let h={selector:i,location:a,inputCount:r.length};return o&&(h.purpose=o),h})}static calculateSummary(e,t,n){var d,f;let r=e.querySelectorAll("button, a[href], input, textarea, select"),i=e.querySelectorAll('section, article, [role="region"]'),a=(((d=t.modals)==null?void 0:d.length)||0)>0,o=[".error",".alert-danger",'[role="alert"]'].some(h=>{let g=e.querySelector(h);return g?b.isVisible(g):!1}),c=[".loading",".spinner",'[aria-busy="true"]'].some(h=>{let g=e.querySelector(h);return g?b.isVisible(g):!1}),l={totalInteractive:r.length,totalForms:n.length,totalSections:i.length,hasModals:a,hasErrors:o,isLoading:c},u=(f=t.main)==null?void 0:f.selector;return u&&(l.mainContentSelector=u),l}static generateSuggestions(e,t){let n=[];return t.hasErrors&&n.push("Page has error indicators - check error messages before interacting"),t.isLoading&&n.push("Page appears to be loading - wait or check loading state"),t.hasModals&&n.push("Modal/dialog is open - may need to interact with or close it first"),e.main&&e.main.interactiveCount>10&&n.push(`Main content has ${e.main.interactiveCount} interactive elements - consider filtering`),t.totalForms>0&&n.push(`Found ${t.totalForms} form(s) on the page`),e.main||n.push("No clear main content area detected - may need to explore regions"),n}static getTextContent(e,t){var r;let n=((r=e.textContent)==null?void 0:r.trim())||"";return t&&n.length>t?`${n.substring(0,t)}...`:n}}})),St=T((()=>{})),Et=lt({ContentDetection:()=>w,MarkdownFormatter:()=>G,ProgressiveExtractor:()=>K,SelectorGenerator:()=>E,SmartDOMReader:()=>A,default:()=>A}),A,Y=T((()=>{z(),P(),_(),xt(),yt(),St(),A=class D{constructor(e={}){R(this,"options");var t;this.options={mode:e.mode||"interactive",maxDepth:e.maxDepth||5,includeHidden:e.includeHidden||!1,includeShadowDOM:(t=e.includeShadowDOM)!=null?t:!0,includeIframes:e.includeIframes||!1,viewportOnly:e.viewportOnly||!1,mainContentOnly:e.mainContentOnly||!1,customSelectors:e.customSelectors||[],...e.attributeTruncateLength!==void 0&&{attributeTruncateLength:e.attributeTruncateLength},...e.dataAttributeTruncateLength!==void 0&&{dataAttributeTruncateLength:e.dataAttributeTruncateLength},...e.textTruncateLength!==void 0&&{textTruncateLength:e.textTruncateLength},...e.filter!==void 0&&{filter:e.filter}}}extract(e=document,t){let n=Date.now(),r=e instanceof Document?e:e.ownerDocument,i={...this.options,...t},a=e instanceof Document?r:e;i.mainContentOnly&&e instanceof Document&&(a=w.findMainContent(r));let o=this.extractPageState(r),c=this.extractLandmarks(r),l=this.extractInteractiveElements(a,i),u={mode:i.mode,timestamp:n,page:o,landmarks:c,interactive:l};if(i.mode==="full"){let d=this.extractSemanticElements(a,i),f=this.extractMetadata(r,a,i);return{...u,semantic:d,metadata:f}}return u}extractPageState(e){var n;let t=this.getFocusedElement(e);return{url:((n=e.location)==null?void 0:n.href)||"",title:e.title||"",hasErrors:this.detectErrors(e),isLoading:this.detectLoading(e),hasModals:this.detectModals(e),...t!==void 0&&{hasFocus:t}}}extractLandmarks(e){let t=w.detectLandmarks(e);return{navigation:this.elementsToSelectors(t.navigation||[]),main:this.elementsToSelectors(t.main||[]),forms:this.elementsToSelectors(t.form||[]),headers:this.elementsToSelectors(t.banner||[]),footers:this.elementsToSelectors(t.contentinfo||[]),articles:this.elementsToSelectors(t.region||[]),sections:this.elementsToSelectors(t.region||[])}}elementsToSelectors(e){return e.map(t=>E.generateSelectors(t).css)}extractInteractiveElements(e,t){let n=[],r=[],i=[],a=[];return e.querySelectorAll('button, [role="button"], input[type="button"], input[type="submit"]').forEach(o=>{if(this.shouldIncludeElement(o,t)){let c=b.extractElement(o,t);c&&n.push(c)}}),e.querySelectorAll("a[href]").forEach(o=>{if(this.shouldIncludeElement(o,t)){let c=b.extractElement(o,t);c&&r.push(c)}}),e.querySelectorAll('input:not([type="button"]):not([type="submit"]), textarea, select').forEach(o=>{if(this.shouldIncludeElement(o,t)){let c=b.extractElement(o,t);c&&i.push(c)}}),t.customSelectors&&t.customSelectors.forEach(o=>{e.querySelectorAll(o).forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&a.push(l)}})}),{buttons:n,links:r,inputs:i,forms:this.extractForms(e,t),clickable:a}}extractForms(e,t){let n=[];return e.querySelectorAll("form").forEach(r=>{if(!this.shouldIncludeElement(r,t))return;let i=[],a=[];r.querySelectorAll('input:not([type="button"]):not([type="submit"]), textarea, select').forEach(u=>{let d=b.extractElement(u,t);d&&i.push(d)}),r.querySelectorAll('button, input[type="button"], input[type="submit"]').forEach(u=>{let d=b.extractElement(u,t);d&&a.push(d)});let o=r.getAttribute("action"),c=r.getAttribute("method"),l={selector:E.generateSelectors(r).css,inputs:i,buttons:a};o&&(l.action=o),c&&(l.method=c),n.push(l)}),n}extractSemanticElements(e,t){let n=[],r=[],i=[],a=[],o=[];return e.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&n.push(l)}}),e.querySelectorAll("img").forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&r.push(l)}}),e.querySelectorAll("table").forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&i.push(l)}}),e.querySelectorAll("ul, ol").forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&a.push(l)}}),e.querySelectorAll('article, [role="article"]').forEach(c=>{if(this.shouldIncludeElement(c,t)){let l=b.extractElement(c,t);l&&o.push(l)}}),{headings:n,images:r,tables:i,lists:a,articles:o}}extractMetadata(e,t,n){let r=t.querySelectorAll("*"),i=t.querySelectorAll("button, a, input, textarea, select, h1, h2, h3, h4, h5, h6, img, table, ul, ol, article").length,a={totalElements:r.length,extractedElements:i};n.mainContentOnly&&t instanceof Element&&(a.mainContent=E.generateSelectors(t).css);let o=e.documentElement.getAttribute("lang");return o&&(a.language=o),a}shouldIncludeElement(e,t){return!(!t.includeHidden&&!b.isVisible(e)||t.viewportOnly&&!b.isInViewport(e)||t.filter&&!b.passesFilter(e,t.filter))}detectErrors(e){return[".error",".alert-danger",'[role="alert"]',".error-message"].some(t=>{let n=e.querySelector(t);return n?b.isVisible(n):!1})}detectLoading(e){return[".loading",".spinner",'[aria-busy="true"]',".loader"].some(t=>{let n=e.querySelector(t);return n?b.isVisible(n):!1})}detectModals(e){return['[role="dialog"]',".modal",".popup",".overlay"].some(t=>{let n=e.querySelector(t);return n?b.isVisible(n):!1})}getFocusedElement(e){let t=e.activeElement;if(t&&t!==e.body)return E.generateSelectors(t).css}static extractInteractive(e,t={}){return new D({...t,mode:"interactive"}).extract(e)}static extractFull(e,t={}){return new D({...t,mode:"full"}).extract(e)}static extractFromElement(e,t="interactive",n={}){return new D({...n,mode:t}).extract(e)}}}));Y();var vt=new Set(["id","data-testid","role-aria","name","class-path","css-path"]);function J(s){let e=s.trim();return e.startsWith("/")||e.startsWith("(")||e.startsWith("./")}function Ct(s){let e=s.selector.candidates;if(e&&e.length>0){let n=null;for(let r of e)vt.has(r.type)&&(!r.value||J(r.value)||(!n||r.score>n.score)&&(n=r));if(n)return n.value}let t=s.selector.css;return t&&!J(t)?t:null}function At(s){var n;let e=s.tag.toLowerCase(),t=(n=s.interaction.role)!=null?n:s.attributes.role;return e==="a"&&(s.interaction.nav||s.attributes.href!=null)?"navigable":e==="input"||e==="select"||e==="textarea"||t==="textbox"||t==="combobox"||t==="listbox"||t==="spinbutton"||s.interaction.change&&!s.interaction.click?"input":e==="button"||t==="button"||s.interaction.click||s.interaction.submit?"clickable":"static"}function Tt(s){let e={...s.attributes},t=s.interaction.role;return t&&!e.role&&(e.role=t),e}function Lt(s,e){var n,r;return e?[s.selector.css,s.selector.xpath,s.context.nearestForm,s.context.nearestSection,s.context.nearestMain,s.context.nearestNav,...(r=(n=s.selector.candidates)==null?void 0:n.map(i=>i.value))!=null?r:[],...s.context.parentChain].some(i=>!!i&&i.includes(e)):!1}function k(s,e={}){var l,u,d;let t=(l=e.includeSemantic)!=null?l:!0,n=(u=e.excludeSelector)!=null?u:".persona-host",r=(d=e.maxTextLength)!=null?d:200,i=[s.interactive.buttons,s.interactive.links,s.interactive.inputs,s.interactive.clickable];t&&s.semantic&&i.push(s.semantic.headings,s.semantic.images,s.semantic.tables,s.semantic.lists,s.semantic.articles);let a=[],o=new Set,c=f=>{var g,p,m;if(Lt(f,n))return!0;let h=Ct(f);if(h&&!o.has(h)&&(o.add(h),a.push({selector:h,tagName:f.tag.toLowerCase(),text:((g=f.text)!=null?g:"").trim().substring(0,r),role:(m=(p=f.interaction.role)!=null?p:f.attributes.role)!=null?m:null,interactivity:At(f),attributes:Tt(f)}),e.maxElements&&a.length>=e.maxElements))return!1;if(f.children){for(let x of f.children)if(!c(x))return!1}return!0};for(let f of i)if(f){for(let h of f)if(!c(h))return a}return a}var I=100;function Q(s,e={}){var i;if(s.length===0)return"No page elements found.";let t=(i=e.mode)!=null?i:"structured",n=[];if(t==="structured"){let a=s.map(o=>o.formattedSummary).filter(o=>!!o&&o.length>0);a.length>0&&n.push(`Structured summaries:
10
+ ${a.map(o=>`- ${o.split(`
11
+ `).join(`
12
+ `)}`).join(`
13
+ `)}`)}let r={clickable:[],navigable:[],input:[],static:[]};for(let a of s)t==="structured"&&a.formattedSummary||r[a.interactivity].push(a);if(r.clickable.length>0){let a=r.clickable.map(o=>`- ${o.selector}: "${o.text.substring(0,I)}" (clickable)`);n.push(`Interactive elements:
14
+ ${a.join(`
15
+ `)}`)}if(r.navigable.length>0){let a=r.navigable.map(o=>`- ${o.selector}${o.attributes.href?`[href="${o.attributes.href}"]`:""}: "${o.text.substring(0,I)}" (navigable)`);n.push(`Navigation links:
16
+ ${a.join(`
17
+ `)}`)}if(r.input.length>0){let a=r.input.map(o=>`- ${o.selector}${o.attributes.type?`[type="${o.attributes.type}"]`:""}: "${o.text.substring(0,I)}" (input)`);n.push(`Form inputs:
18
+ ${a.join(`
19
+ `)}`)}if(r.static.length>0){let a=r.static.map(o=>`- ${o.selector}: "${o.text.substring(0,I)}"`);n.push(`Content:
20
+ ${a.join(`
21
+ `)}`)}return n.join(`
21
22
 
22
- // src/smart-dom-reader.ts
23
- var smart_dom_reader_exports = {};
24
- __export(smart_dom_reader_exports, {
25
- collectSmartDomContext: () => collectSmartDomContext,
26
- createSmartDomReaderContextProvider: () => createSmartDomReaderContextProvider,
27
- smartDomResultToEnriched: () => smartDomResultToEnriched
28
- });
29
- module.exports = __toCommonJS(smart_dom_reader_exports);
30
-
31
- // src/vendor/smart-dom-reader/index.js
32
- var __defProp2 = Object.defineProperty;
33
- var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
34
- var __getOwnPropNames2 = Object.getOwnPropertyNames;
35
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
36
- var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
37
- var __exportAll = (all, no_symbols) => {
38
- let target = {};
39
- for (var name in all) __defProp2(target, name, {
40
- get: all[name],
41
- enumerable: true
42
- });
43
- if (!no_symbols) __defProp2(target, Symbol.toStringTag, { value: "Module" });
44
- return target;
45
- };
46
- var __copyProps2 = (to, from, except, desc) => {
47
- if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames2(from), i = 0, n = keys.length, key; i < n; i++) {
48
- key = keys[i];
49
- if (!__hasOwnProp2.call(to, key) && key !== except) __defProp2(to, key, {
50
- get: ((k) => from[k]).bind(null, key),
51
- enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable
52
- });
53
- }
54
- return to;
55
- };
56
- var __toCommonJS2 = (mod) => __hasOwnProp2.call(mod, "module.exports") ? mod["module.exports"] : __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
57
- var __require = void 0;
58
- var ContentDetection;
59
- var init_content_detection = __esmMin((() => {
60
- ContentDetection = class ContentDetection2 {
61
- /**
62
- * Find the main content area of a page
63
- * Inspired by dom-to-semantic-markdown's approach
64
- */
65
- static findMainContent(doc) {
66
- const mainElement = doc.querySelector('main, [role="main"]');
67
- if (mainElement) return mainElement;
68
- if (!doc.body) return doc.documentElement;
69
- return ContentDetection2.detectMainContent(doc.body);
70
- }
71
- /**
72
- * Detect main content using scoring algorithm
73
- */
74
- static detectMainContent(rootElement) {
75
- const candidates = [];
76
- ContentDetection2.collectCandidates(rootElement, candidates, 15);
77
- if (candidates.length === 0) return rootElement;
78
- candidates.sort((a, b) => ContentDetection2.calculateContentScore(b) - ContentDetection2.calculateContentScore(a));
79
- let bestCandidate = candidates[0];
80
- for (let i = 1; i < candidates.length; i++) {
81
- const candidate = candidates[i];
82
- if (!candidates.some((other, j) => j !== i && other.contains(candidate)) && ContentDetection2.calculateContentScore(candidate) > ContentDetection2.calculateContentScore(bestCandidate)) bestCandidate = candidate;
83
- }
84
- return bestCandidate;
85
- }
86
- /**
87
- * Collect content candidates
88
- */
89
- static collectCandidates(element, candidates, minScore) {
90
- if (ContentDetection2.calculateContentScore(element) >= minScore) candidates.push(element);
91
- Array.from(element.children).forEach((child) => {
92
- ContentDetection2.collectCandidates(child, candidates, minScore);
93
- });
94
- }
95
- /**
96
- * Calculate content score for an element
97
- */
98
- static calculateContentScore(element) {
99
- var _a;
100
- let score = 0;
101
- const semanticClasses = [
102
- "article",
103
- "content",
104
- "main-container",
105
- "main",
106
- "main-content",
107
- "post",
108
- "entry"
109
- ];
110
- const semanticIds = [
111
- "content",
112
- "main",
113
- "article",
114
- "post",
115
- "entry"
116
- ];
117
- semanticClasses.forEach((cls) => {
118
- if (element.classList.contains(cls)) score += 10;
119
- });
120
- semanticIds.forEach((id) => {
121
- var _a2;
122
- if ((_a2 = element.id) == null ? void 0 : _a2.toLowerCase().includes(id)) score += 10;
123
- });
124
- const tag = element.tagName.toLowerCase();
125
- if ([
126
- "article",
127
- "main",
128
- "section"
129
- ].includes(tag)) score += 8;
130
- const paragraphs = element.getElementsByTagName("p").length;
131
- score += Math.min(paragraphs * 2, 10);
132
- const headings = element.querySelectorAll("h1, h2, h3").length;
133
- score += Math.min(headings * 3, 9);
134
- const textLength = ((_a = element.textContent) == null ? void 0 : _a.trim().length) || 0;
135
- if (textLength > 300) score += Math.min(Math.floor(textLength / 300) * 2, 10);
136
- const linkDensity = ContentDetection2.calculateLinkDensity(element);
137
- if (linkDensity < 0.3) score += 5;
138
- else if (linkDensity > 0.5) score -= 5;
139
- if (element.hasAttribute("data-main") || element.hasAttribute("data-content") || element.hasAttribute("itemprop")) score += 8;
140
- const role = element.getAttribute("role");
141
- if (role === "main" || role === "article") score += 10;
142
- if (element.matches("aside, nav, header, footer, .sidebar, .navigation, .menu, .ad, .advertisement")) score -= 10;
143
- if (element.getElementsByTagName("form").length > 2) score -= 5;
144
- return Math.max(0, score);
145
- }
146
- /**
147
- * Calculate link density in an element
148
- */
149
- static calculateLinkDensity(element) {
150
- var _a, _b;
151
- const links = element.getElementsByTagName("a");
152
- let linkTextLength = 0;
153
- for (const link of Array.from(links)) linkTextLength += ((_a = link.textContent) == null ? void 0 : _a.length) || 0;
154
- const totalTextLength = ((_b = element.textContent) == null ? void 0 : _b.length) || 1;
155
- return linkTextLength / totalTextLength;
156
- }
157
- /**
158
- * Check if an element is likely navigation
159
- */
160
- static isNavigation(element) {
161
- if (element.tagName.toLowerCase() === "nav" || element.getAttribute("role") === "navigation") return true;
162
- const navPatterns = [
163
- /nav/i,
164
- /menu/i,
165
- /sidebar/i,
166
- /toolbar/i
167
- ];
168
- const classesAndId = `${element.className} ${element.id}`.toLowerCase();
169
- return navPatterns.some((pattern) => pattern.test(classesAndId));
170
- }
171
- /**
172
- * Check if element is likely supplementary content
173
- */
174
- static isSupplementary(element) {
175
- if (element.tagName.toLowerCase() === "aside" || element.getAttribute("role") === "complementary") return true;
176
- const supplementaryPatterns = [
177
- /sidebar/i,
178
- /widget/i,
179
- /related/i,
180
- /advertisement/i,
181
- /social/i
182
- ];
183
- const classesAndId = `${element.className} ${element.id}`.toLowerCase();
184
- return supplementaryPatterns.some((pattern) => pattern.test(classesAndId));
185
- }
186
- /**
187
- * Detect page landmarks
188
- */
189
- static detectLandmarks(doc) {
190
- const landmarks = {
191
- navigation: [],
192
- main: [],
193
- complementary: [],
194
- contentinfo: [],
195
- banner: [],
196
- search: [],
197
- form: [],
198
- region: []
199
- };
200
- for (const [landmark, selector] of Object.entries({
201
- navigation: 'nav, [role="navigation"]',
202
- main: 'main, [role="main"]',
203
- complementary: 'aside, [role="complementary"]',
204
- contentinfo: 'footer, [role="contentinfo"]',
205
- banner: 'header, [role="banner"]',
206
- search: '[role="search"]',
207
- form: 'form[aria-label], form[aria-labelledby], [role="form"]',
208
- region: 'section[aria-label], section[aria-labelledby], [role="region"]'
209
- })) {
210
- const elements = doc.querySelectorAll(selector);
211
- landmarks[landmark] = Array.from(elements);
212
- }
213
- return landmarks;
214
- }
215
- };
216
- }));
217
- var SelectorGenerator;
218
- var init_selectors = __esmMin((() => {
219
- SelectorGenerator = class SelectorGenerator2 {
220
- /**
221
- * Generate multiple selector strategies for an element
222
- */
223
- static generateSelectors(element) {
224
- var _a;
225
- const doc = element.ownerDocument || document;
226
- const candidates = [];
227
- if (element.id && SelectorGenerator2.isUniqueId(element.id, doc)) candidates.push({
228
- type: "id",
229
- value: `#${CSS.escape(element.id)}`,
230
- score: 100
231
- });
232
- const testId = SelectorGenerator2.getDataTestId(element);
233
- if (testId) {
234
- const v = `[data-testid="${CSS.escape(testId)}"]`;
235
- candidates.push({
236
- type: "data-testid",
237
- value: v,
238
- score: 90 + (SelectorGenerator2.isUniqueSelectorSafe(v, doc) ? 5 : 0)
239
- });
240
- }
241
- const role = element.getAttribute("role");
242
- const aria = element.getAttribute("aria-label");
243
- if (role && aria) {
244
- const v = `[role="${CSS.escape(role)}"][aria-label="${CSS.escape(aria)}"]`;
245
- candidates.push({
246
- type: "role-aria",
247
- value: v,
248
- score: 85 + (SelectorGenerator2.isUniqueSelectorSafe(v, doc) ? 5 : 0)
249
- });
250
- }
251
- const nameAttr = element.getAttribute("name");
252
- if (nameAttr) {
253
- const v = `[name="${CSS.escape(nameAttr)}"]`;
254
- candidates.push({
255
- type: "name",
256
- value: v,
257
- score: 78 + (SelectorGenerator2.isUniqueSelectorSafe(v, doc) ? 5 : 0)
258
- });
259
- }
260
- const pathCss = SelectorGenerator2.generateCSSSelector(element, doc);
261
- const structuralPenalty = (pathCss.match(/:nth-child\(/g) || []).length * 10;
262
- const classBonus = pathCss.includes(".") ? 8 : 0;
263
- const pathScore = Math.max(0, 70 + classBonus - structuralPenalty);
264
- candidates.push({
265
- type: "class-path",
266
- value: pathCss,
267
- score: pathScore
268
- });
269
- const xpath = SelectorGenerator2.generateXPath(element, doc);
270
- candidates.push({
271
- type: "xpath",
272
- value: xpath,
273
- score: 40
274
- });
275
- const textBased = SelectorGenerator2.generateTextBasedSelector(element);
276
- if (textBased) candidates.push({
277
- type: "text",
278
- value: textBased,
279
- score: 30
280
- });
281
- candidates.sort((a, b) => b.score - a.score);
282
- const selector = {
283
- css: ((_a = candidates.find((c) => c.type !== "xpath" && c.type !== "text")) == null ? void 0 : _a.value) || pathCss,
284
- xpath,
285
- candidates
286
- };
287
- if (textBased) selector.textBased = textBased;
288
- if (testId) selector.dataTestId = testId;
289
- if (aria) selector.ariaLabel = aria;
290
- return selector;
291
- }
292
- /**
293
- * Generate a unique CSS selector for an element
294
- */
295
- static generateCSSSelector(element, doc) {
296
- var _a;
297
- if (element.id && SelectorGenerator2.isUniqueId(element.id, doc)) return `#${CSS.escape(element.id)}`;
298
- const testId = SelectorGenerator2.getDataTestId(element);
299
- if (testId) return `[data-testid="${CSS.escape(testId)}"]`;
300
- const path = [];
301
- let current = element;
302
- while (current && current.nodeType === Node.ELEMENT_NODE) {
303
- let selector = current.nodeName.toLowerCase();
304
- if (current.id && SelectorGenerator2.isUniqueId(current.id, doc)) {
305
- selector = `#${CSS.escape(current.id)}`;
306
- path.unshift(selector);
307
- break;
308
- }
309
- const classes = SelectorGenerator2.getMeaningfulClasses(current);
310
- if (classes.length > 0) selector += `.${classes.map((c) => CSS.escape(c)).join(".")}`;
311
- const siblings = (_a = current.parentElement) == null ? void 0 : _a.children;
312
- if (siblings && siblings.length > 1) {
313
- const index = Array.from(siblings).indexOf(current);
314
- if (index > 0 || !SelectorGenerator2.isUniqueSelector(selector, current.parentElement)) selector += `:nth-child(${index + 1})`;
315
- }
316
- path.unshift(selector);
317
- current = current.parentElement;
318
- }
319
- return SelectorGenerator2.optimizePath(path, element, doc);
320
- }
321
- /**
322
- * Generate XPath for an element
323
- */
324
- static generateXPath(element, doc) {
325
- var _a;
326
- if (element.id && SelectorGenerator2.isUniqueId(element.id, doc)) return `//*[@id="${element.id}"]`;
327
- const path = [];
328
- let current = element;
329
- while (current && current.nodeType === Node.ELEMENT_NODE) {
330
- const tagName = current.nodeName.toLowerCase();
331
- if (current.id && SelectorGenerator2.isUniqueId(current.id, doc)) {
332
- path.unshift(`//*[@id="${current.id}"]`);
333
- break;
334
- }
335
- let xpath = tagName;
336
- const siblings = (_a = current.parentElement) == null ? void 0 : _a.children;
337
- if (siblings) {
338
- const sameTagSiblings = Array.from(siblings).filter((s) => s.nodeName.toLowerCase() === tagName);
339
- if (sameTagSiblings.length > 1) {
340
- const index = sameTagSiblings.indexOf(current) + 1;
341
- xpath += `[${index}]`;
342
- }
343
- }
344
- path.unshift(xpath);
345
- current = current.parentElement;
346
- }
347
- return `//${path.join("/")}`;
348
- }
349
- /**
350
- * Generate a text-based selector for buttons and links
351
- */
352
- static generateTextBasedSelector(element) {
353
- var _a;
354
- const text = (_a = element.textContent) == null ? void 0 : _a.trim();
355
- if (!text || text.length > 50) return void 0;
356
- const tag = element.nodeName.toLowerCase();
357
- if ([
358
- "button",
359
- "a",
360
- "label"
361
- ].includes(tag)) return `${tag}:contains("${text.replace(/['"\\]/g, "\\$&")}")`;
362
- }
363
- /**
364
- * Get data-testid or similar attributes
365
- */
366
- static getDataTestId(element) {
367
- return element.getAttribute("data-testid") || element.getAttribute("data-test-id") || element.getAttribute("data-test") || element.getAttribute("data-cy") || void 0;
368
- }
369
- /**
370
- * Check if an ID is unique in the document
371
- */
372
- static isUniqueId(id, doc) {
373
- return doc.querySelectorAll(`#${CSS.escape(id)}`).length === 1;
374
- }
375
- /**
376
- * Check if a selector is unique within a container
377
- */
378
- static isUniqueSelector(selector, container) {
379
- try {
380
- return container.querySelectorAll(selector).length === 1;
381
- } catch {
382
- return false;
383
- }
384
- }
385
- static isUniqueSelectorSafe(selector, doc) {
386
- try {
387
- return doc.querySelectorAll(selector).length === 1;
388
- } catch {
389
- return false;
390
- }
391
- }
392
- /**
393
- * Get meaningful classes (filtering out utility classes)
394
- */
395
- static getMeaningfulClasses(element) {
396
- const classes = Array.from(element.classList);
397
- const utilityPatterns = [
398
- /^(p|m|w|h|text|bg|border|flex|grid|col|row)-/,
399
- /^(xs|sm|md|lg|xl|2xl):/,
400
- /^(hover|focus|active|disabled|checked):/,
401
- /^js-/,
402
- /^is-/,
403
- /^has-/
404
- ];
405
- return classes.filter((cls) => {
406
- if (cls.length < 3) return false;
407
- return !utilityPatterns.some((pattern) => pattern.test(cls));
408
- }).slice(0, 2);
409
- }
410
- /**
411
- * Optimize the selector path by removing unnecessary parts
412
- */
413
- static optimizePath(path, element, doc) {
414
- for (let i = 0; i < path.length - 1; i++) {
415
- const shortPath = path.slice(i).join(" > ");
416
- try {
417
- const matches = doc.querySelectorAll(shortPath);
418
- if (matches.length === 1 && matches[0] === element) return shortPath;
419
- } catch {
420
- }
421
- }
422
- return path.join(" > ");
423
- }
424
- /**
425
- * Get a human-readable path description
426
- */
427
- static getContextPath(element) {
428
- var _a;
429
- const path = [];
430
- let current = element;
431
- let depth = 0;
432
- const maxDepth = 5;
433
- while (current && current !== ((_a = element.ownerDocument) == null ? void 0 : _a.body) && depth < maxDepth) {
434
- const tag = current.nodeName.toLowerCase();
435
- let descriptor = tag;
436
- if (current.id) descriptor = `${tag}#${current.id}`;
437
- else if (current.className && typeof current.className === "string") {
438
- const firstClass = current.className.split(" ")[0];
439
- if (firstClass) descriptor = `${tag}.${firstClass}`;
440
- }
441
- const role = current.getAttribute("role");
442
- if (role) descriptor += `[role="${role}"]`;
443
- path.unshift(descriptor);
444
- current = current.parentElement;
445
- depth++;
446
- }
447
- return path;
448
- }
449
- };
450
- }));
451
- var DOMTraversal;
452
- var init_traversal = __esmMin((() => {
453
- var _a;
454
- init_selectors();
455
- DOMTraversal = (_a = class {
456
- /**
457
- * Check if element is visible
458
- */
459
- static isVisible(element, computedStyle) {
460
- var _a2, _b;
461
- const rect = element.getBoundingClientRect();
462
- const style = computedStyle || ((_b = (_a2 = element.ownerDocument) == null ? void 0 : _a2.defaultView) == null ? void 0 : _b.getComputedStyle(element));
463
- if (!style) return false;
464
- return !!(rect.width > 0 && rect.height > 0 && style.display !== "none" && style.visibility !== "hidden" && style.opacity !== "0" && element.offsetParent !== null);
465
- }
466
- /**
467
- * Check if element is in viewport
468
- */
469
- static isInViewport(element, viewport) {
470
- var _a2, _b, _c, _d;
471
- const rect = element.getBoundingClientRect();
472
- const view = viewport || {
473
- width: ((_b = (_a2 = element.ownerDocument) == null ? void 0 : _a2.defaultView) == null ? void 0 : _b.innerWidth) || 0,
474
- height: ((_d = (_c = element.ownerDocument) == null ? void 0 : _c.defaultView) == null ? void 0 : _d.innerHeight) || 0
475
- };
476
- return rect.top < view.height && rect.bottom > 0 && rect.left < view.width && rect.right > 0;
477
- }
478
- /**
479
- * Check if element passes filter criteria
480
- */
481
- static passesFilter(element, filter) {
482
- var _a2, _b, _c, _d, _e, _f, _g, _h, _i, _j;
483
- if (!filter) return true;
484
- const htmlElement = element;
485
- if ((_a2 = filter.excludeSelectors) == null ? void 0 : _a2.length) {
486
- for (const selector of filter.excludeSelectors) if (element.matches(selector)) return false;
487
- }
488
- if ((_b = filter.includeSelectors) == null ? void 0 : _b.length) {
489
- let matches = false;
490
- for (const selector of filter.includeSelectors) if (element.matches(selector)) {
491
- matches = true;
492
- break;
493
- }
494
- if (!matches) return false;
495
- }
496
- if (((_c = filter.tags) == null ? void 0 : _c.length) && !filter.tags.includes(element.tagName.toLowerCase())) return false;
497
- const textContent = ((_d = htmlElement.textContent) == null ? void 0 : _d.toLowerCase()) || "";
498
- if ((_e = filter.textContains) == null ? void 0 : _e.length) {
499
- let hasText = false;
500
- for (const text of filter.textContains) if (textContent.includes(text.toLowerCase())) {
501
- hasText = true;
502
- break;
503
- }
504
- if (!hasText) return false;
505
- }
506
- if ((_f = filter.textMatches) == null ? void 0 : _f.length) {
507
- let matches = false;
508
- for (const pattern of filter.textMatches) if (pattern.test(textContent)) {
509
- matches = true;
510
- break;
511
- }
512
- if (!matches) return false;
513
- }
514
- if ((_g = filter.hasAttributes) == null ? void 0 : _g.length) {
515
- for (const attr of filter.hasAttributes) if (!element.hasAttribute(attr)) return false;
516
- }
517
- if (filter.attributeValues) for (const [attr, value] of Object.entries(filter.attributeValues)) {
518
- const attrValue = element.getAttribute(attr);
519
- if (!attrValue) return false;
520
- if (typeof value === "string") {
521
- if (attrValue !== value) return false;
522
- } else if (value instanceof RegExp) {
523
- if (!value.test(attrValue)) return false;
524
- }
525
- }
526
- if ((_h = filter.withinSelectors) == null ? void 0 : _h.length) {
527
- let isWithin = false;
528
- for (const selector of filter.withinSelectors) if (element.closest(selector)) {
529
- isWithin = true;
530
- break;
531
- }
532
- if (!isWithin) return false;
533
- }
534
- if ((_i = filter.interactionTypes) == null ? void 0 : _i.length) {
535
- const interaction = _a.getInteractionInfo(element);
536
- let hasInteraction = false;
537
- for (const type of filter.interactionTypes) if (interaction[type]) {
538
- hasInteraction = true;
539
- break;
540
- }
541
- if (!hasInteraction) return false;
542
- }
543
- if (filter.nearText) {
544
- const parent = element.parentElement;
545
- if (!parent || !((_j = parent.textContent) == null ? void 0 : _j.toLowerCase().includes(filter.nearText.toLowerCase()))) return false;
546
- }
547
- return true;
548
- }
549
- /**
550
- * Extract element information
551
- */
552
- static extractElement(element, options, depth = 0) {
553
- if (options.maxDepth && depth > options.maxDepth) return null;
554
- if (!options.includeHidden && !_a.isVisible(element)) return null;
555
- if (options.viewportOnly && !_a.isInViewport(element)) return null;
556
- if (!_a.passesFilter(element, options.filter)) return null;
557
- const htmlElement = element;
558
- const extracted = {
559
- tag: element.tagName.toLowerCase(),
560
- text: _a.getElementText(element, options),
561
- selector: SelectorGenerator.generateSelectors(element),
562
- attributes: _a.getRelevantAttributes(element, options),
563
- context: _a.getElementContext(element),
564
- interaction: _a.getInteractionInfo(element)
565
- };
566
- if (options.mode === "full" && _a.isSemanticContainer(element)) {
567
- const children = [];
568
- if (options.includeShadowDOM && htmlElement.shadowRoot) {
569
- const shadowChildren = _a.extractChildren(htmlElement.shadowRoot, options, depth + 1);
570
- children.push(...shadowChildren);
571
- }
572
- const regularChildren = _a.extractChildren(element, options, depth + 1);
573
- children.push(...regularChildren);
574
- if (children.length > 0) extracted.children = children;
575
- }
576
- return extracted;
577
- }
578
- /**
579
- * Extract children elements
580
- */
581
- static extractChildren(container, options, depth) {
582
- const children = [];
583
- const elements = container.querySelectorAll("*");
584
- for (const child of Array.from(elements)) {
585
- if (_a.hasExtractedAncestor(child, elements)) continue;
586
- const extracted = _a.extractElement(child, options, depth);
587
- if (extracted) children.push(extracted);
588
- }
589
- return children;
590
- }
591
- /**
592
- * Check if element has an ancestor that was already extracted
593
- */
594
- static hasExtractedAncestor(element, extractedElements) {
595
- let parent = element.parentElement;
596
- while (parent) {
597
- if (Array.from(extractedElements).includes(parent)) return true;
598
- parent = parent.parentElement;
599
- }
600
- return false;
601
- }
602
- /**
603
- * Get relevant attributes for an element
604
- */
605
- static getRelevantAttributes(element, options) {
606
- var _a2, _b;
607
- const relevant = [
608
- "id",
609
- "class",
610
- "name",
611
- "type",
612
- "value",
613
- "placeholder",
614
- "href",
615
- "src",
616
- "alt",
617
- "title",
618
- "action",
619
- "method",
620
- "aria-label",
621
- "aria-describedby",
622
- "aria-controls",
623
- "role",
624
- "disabled",
625
- "readonly",
626
- "required",
627
- "checked",
628
- "min",
629
- "max",
630
- "pattern",
631
- "step",
632
- "autocomplete",
633
- "data-testid",
634
- "data-test",
635
- "data-cy"
636
- ];
637
- const attributes = {};
638
- const attrTruncate = (_a2 = options.attributeTruncateLength) != null ? _a2 : 100;
639
- const dataAttrTruncate = (_b = options.dataAttributeTruncateLength) != null ? _b : 50;
640
- for (const attr of relevant) {
641
- const value = element.getAttribute(attr);
642
- if (value) attributes[attr] = value.length > attrTruncate ? `${value.substring(0, attrTruncate)}...` : value;
643
- }
644
- for (const attr of element.attributes) if (attr.name.startsWith("data-") && !relevant.includes(attr.name)) attributes[attr.name] = attr.value.length > dataAttrTruncate ? `${attr.value.substring(0, dataAttrTruncate)}...` : attr.value;
645
- return attributes;
646
- }
647
- /**
648
- * Get element context information
649
- */
650
- static getElementContext(element) {
651
- const context = { parentChain: SelectorGenerator.getContextPath(element) };
652
- const form = element.closest("form");
653
- if (form) context.nearestForm = SelectorGenerator.generateSelectors(form).css;
654
- const section = element.closest('section, [role="region"]');
655
- if (section) context.nearestSection = SelectorGenerator.generateSelectors(section).css;
656
- const main = element.closest('main, [role="main"]');
657
- if (main) context.nearestMain = SelectorGenerator.generateSelectors(main).css;
658
- const nav = element.closest('nav, [role="navigation"]');
659
- if (nav) context.nearestNav = SelectorGenerator.generateSelectors(nav).css;
660
- return context;
661
- }
662
- /**
663
- * Get interaction information for an element (compact format)
664
- */
665
- static getInteractionInfo(element) {
666
- const htmlElement = element;
667
- const interaction = {};
668
- if (!!(htmlElement.onclick || element.getAttribute("onclick") || element.matches('button, a[href], [role="button"], [tabindex]:not([tabindex="-1"])'))) interaction.click = true;
669
- if (!!(htmlElement.onchange || element.getAttribute("onchange") || element.matches("input, select, textarea"))) interaction.change = true;
670
- if (!!(htmlElement.onsubmit || element.getAttribute("onsubmit") || element.matches("form"))) interaction.submit = true;
671
- if (element.matches('a[href], button[type="submit"]')) interaction.nav = true;
672
- if (htmlElement.hasAttribute("disabled") || htmlElement.getAttribute("aria-disabled") === "true") interaction.disabled = true;
673
- if (!_a.isVisible(element)) interaction.hidden = true;
674
- const ariaRole = element.getAttribute("role");
675
- if (ariaRole) interaction.role = ariaRole;
676
- if (element.matches("input, textarea, select, button")) {
677
- const form = element.form || element.closest("form");
678
- if (form) interaction.form = SelectorGenerator.generateSelectors(form).css;
679
- }
680
- return interaction;
681
- }
682
- /**
683
- * Get text content of an element (limited length)
684
- */
685
- static getElementText(element, options) {
686
- var _a2;
687
- if (element.matches("input, textarea")) {
688
- const input = element;
689
- return input.value || input.placeholder || "";
690
- }
691
- if (element.matches("img")) return element.alt || "";
692
- const text = ((_a2 = element.textContent) == null ? void 0 : _a2.trim()) || "";
693
- const maxLength = options == null ? void 0 : options.textTruncateLength;
694
- if (maxLength && text.length > maxLength) return `${text.substring(0, maxLength)}...`;
695
- return text;
696
- }
697
- /**
698
- * Check if element is a semantic container
699
- */
700
- static isSemanticContainer(element) {
701
- return element.matches('article, section, nav, aside, main, header, footer, form, table, ul, ol, dl, figure, details, dialog, [role="region"], [role="navigation"], [role="main"], [role="complementary"]');
702
- }
703
- /**
704
- * Get interactive elements
705
- */
706
- static getInteractiveElements(container, options) {
707
- const elements = [];
708
- const selector = _a.INTERACTIVE_SELECTORS.join(", ");
709
- const found = container.querySelectorAll(selector);
710
- for (const element of Array.from(found)) {
711
- const extracted = _a.extractElement(element, options);
712
- if (extracted) elements.push(extracted);
713
- }
714
- if (options.customSelectors) for (const customSelector of options.customSelectors) try {
715
- const customFound = container.querySelectorAll(customSelector);
716
- for (const element of Array.from(customFound)) {
717
- const extracted = _a.extractElement(element, options);
718
- if (extracted) elements.push(extracted);
719
- }
720
- } catch (_e) {
721
- console.warn(`Invalid custom selector: ${customSelector}`);
722
- }
723
- return elements;
724
- }
725
- /**
726
- * Get semantic elements (for full mode)
727
- */
728
- static getSemanticElements(container, options) {
729
- const elements = [];
730
- const selector = _a.SEMANTIC_SELECTORS.join(", ");
731
- const found = container.querySelectorAll(selector);
732
- for (const element of Array.from(found)) {
733
- const extracted = _a.extractElement(element, options);
734
- if (extracted) elements.push(extracted);
735
- }
736
- return elements;
737
- }
738
- }, __publicField(_a, "INTERACTIVE_SELECTORS", [
739
- "button",
740
- "a[href]",
741
- 'input:not([type="hidden"])',
742
- "textarea",
743
- "select",
744
- '[role="button"]',
745
- "[onclick]",
746
- '[contenteditable="true"]',
747
- "summary",
748
- '[tabindex]:not([tabindex="-1"])'
749
- ]), __publicField(_a, "SEMANTIC_SELECTORS", [
750
- "h1",
751
- "h2",
752
- "h3",
753
- "h4",
754
- "h5",
755
- "h6",
756
- "article",
757
- "section",
758
- "nav",
759
- "aside",
760
- "main",
761
- "header",
762
- "footer",
763
- "form",
764
- "table",
765
- "ul",
766
- "ol",
767
- "img[alt]",
768
- "figure",
769
- "video",
770
- "audio",
771
- '[role="navigation"]',
772
- '[role="main"]',
773
- '[role="complementary"]',
774
- '[role="contentinfo"]'
775
- ]), _a);
776
- }));
777
- function truncate(text, len) {
778
- const t = (text != null ? text : "").trim();
779
- if (!len || t.length <= len) return t;
780
- const keywords = [
781
- "login",
782
- "log in",
783
- "sign in",
784
- "sign up",
785
- "submit",
786
- "search",
787
- "filter",
788
- "add to cart",
789
- "next",
790
- "continue"
791
- ];
792
- const lower = t.toLowerCase();
793
- const hit = keywords.map((k) => ({
794
- k,
795
- i: lower.indexOf(k)
796
- })).find((x) => x.i > -1);
797
- const head = Math.max(0, Math.floor(len * 0.66));
798
- if (hit && hit.i > head) {
799
- const tailWindow = Math.max(12, len - head - 5);
800
- const start = Math.max(0, hit.i - Math.floor(tailWindow / 2));
801
- const end = Math.min(t.length, start + tailWindow);
802
- return `${t.slice(0, head).trimEnd()} \u2026 ${t.slice(start, end).trim()}\u2026`;
803
- }
804
- const slice = t.slice(0, len);
805
- const lastSpace = slice.lastIndexOf(" ");
806
- return `${lastSpace > 32 ? slice.slice(0, lastSpace) : slice}\u2026`;
807
- }
808
- function bestSelector(el) {
809
- var _a;
810
- return ((_a = el.selector) == null ? void 0 : _a.css) || "";
811
- }
812
- function hashId(input) {
813
- let h = 5381;
814
- for (let i = 0; i < input.length; i++) h = h * 33 ^ input.charCodeAt(i);
815
- return `sec-${(h >>> 0).toString(36)}`;
816
- }
817
- function iconForRegion(key) {
818
- switch (key) {
819
- case "header":
820
- return "\u{1F9ED}";
821
- case "navigation":
822
- return "\u{1F4D1}";
823
- case "main":
824
- return "\u{1F4C4}";
825
- case "sections":
826
- return "\u{1F5C2}\uFE0F";
827
- case "sidebar":
828
- return "\u{1F4DA}";
829
- case "footer":
830
- return "\u{1F53B}";
831
- case "modals":
832
- return "\u{1F4AC}";
833
- default:
834
- return "\u{1F539}";
835
- }
836
- }
837
- function elementLine(el, opts) {
838
- var _a, _b, _c, _d, _e;
839
- const txt = truncate(el.text || ((_a = el.attributes) == null ? void 0 : _a.ariaLabel), (_b = opts == null ? void 0 : opts.maxTextLength) != null ? _b : 80);
840
- const sel = bestSelector(el);
841
- const tag = el.tag.toLowerCase();
842
- const action = ((_c = el.interaction) == null ? void 0 : _c.submit) ? "submit" : ((_d = el.interaction) == null ? void 0 : _d.click) ? "click" : ((_e = el.interaction) == null ? void 0 : _e.change) ? "change" : void 0;
843
- const actionText = action ? ` (${action})` : "";
844
- return `- ${tag.toUpperCase()}: ${txt || "(no text)"} \u2192 \`${sel}\`${actionText}`;
845
- }
846
- function selectorQualitySummary(inter) {
847
- const all = [];
848
- all.push(...inter.buttons.map((e) => {
849
- var _a;
850
- return ((_a = e.selector) == null ? void 0 : _a.css) || "";
851
- }));
852
- all.push(...inter.links.map((e) => {
853
- var _a;
854
- return ((_a = e.selector) == null ? void 0 : _a.css) || "";
855
- }));
856
- all.push(...inter.inputs.map((e) => {
857
- var _a;
858
- return ((_a = e.selector) == null ? void 0 : _a.css) || "";
859
- }));
860
- all.push(...inter.clickable.map((e) => {
861
- var _a;
862
- return ((_a = e.selector) == null ? void 0 : _a.css) || "";
863
- }));
864
- const total = all.length || 1;
865
- const idCount = all.filter((s) => s.startsWith("#")).length;
866
- const testIdCount = all.filter((s) => /\[data-testid=/.test(s)).length;
867
- const nthCount = all.filter((s) => /:nth-child\(/.test(s)).length;
868
- const stable = idCount + testIdCount;
869
- return `Selector quality: ${Math.round(stable / total * 100)}% stable (ID/data-testid), ${Math.round(nthCount / total * 100)}% structural (:nth-child)`;
870
- }
871
- function renderInteractive(inter, opts) {
872
- var _a, _b;
873
- const parts = [];
874
- const limit = (arr) => typeof (opts == null ? void 0 : opts.maxElements) === "number" ? arr.slice(0, opts.maxElements) : arr;
875
- if (inter.buttons.length) {
876
- parts.push("Buttons:");
877
- for (const el of limit(inter.buttons)) parts.push(elementLine(el, opts));
878
- }
879
- if (inter.links.length) {
880
- parts.push("Links:");
881
- for (const el of limit(inter.links)) parts.push(elementLine(el, opts));
882
- }
883
- if (inter.inputs.length) {
884
- parts.push("Inputs:");
885
- for (const el of limit(inter.inputs)) parts.push(elementLine(el, opts));
886
- }
887
- if (inter.clickable.length) {
888
- parts.push("Other Clickable:");
889
- for (const el of limit(inter.clickable)) parts.push(elementLine(el, opts));
890
- }
891
- if (inter.forms.length) {
892
- parts.push("Forms:");
893
- for (const f of limit(inter.forms)) parts.push(`- FORM: action=${(_a = f.action) != null ? _a : "-"} method=${(_b = f.method) != null ? _b : "-"} \u2192 \`${f.selector}\``);
894
- }
895
- return parts.join("\n");
896
- }
897
- function renderRegionInfo(region) {
898
- var _a, _b;
899
- const icon = iconForRegion("region");
900
- const id = hashId(`${region.selector}|${(_a = region.label) != null ? _a : ""}|${(_b = region.role) != null ? _b : ""}`);
901
- const label = region.label ? ` ${region.label}` : "";
902
- const stats = [];
903
- if (region.buttonCount) stats.push(`${region.buttonCount} buttons`);
904
- if (region.linkCount) stats.push(`${region.linkCount} links`);
905
- if (region.inputCount) stats.push(`${region.inputCount} inputs`);
906
- if (region.textPreview) stats.push(`\u201C${truncate(region.textPreview, 80)}\u201D`);
907
- const statsLine = stats.length ? ` \u2014 ${stats.join(", ")}` : "";
908
- return `${icon} ${label} \u2192 \`${region.selector}\` [${id}]${statsLine}`;
909
- }
910
- function wrapXml(body, meta, type = "section") {
911
- return `<page ${[(meta == null ? void 0 : meta.title) ? `title="${escapeXml(meta == null ? void 0 : meta.title)}"` : null, (meta == null ? void 0 : meta.url) ? `url="${escapeXml(meta == null ? void 0 : meta.url)}"` : null].filter(Boolean).join(" ")}>
912
- <${type}><![CDATA[
913
- ${body}
914
- ]]></${type}>
915
- </page>`;
916
- }
917
- function escapeXml(s) {
918
- return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
919
- }
920
- function capitalize(s) {
921
- return s.charAt(0).toUpperCase() + s.slice(1);
922
- }
923
- var MarkdownFormatter;
924
- var init_markdown_formatter = __esmMin((() => {
925
- MarkdownFormatter = class {
926
- static structure(overview, _opts = {}, meta) {
927
- var _a, _b, _c;
928
- const lines = [];
929
- lines.push("# Page Outline");
930
- if ((meta == null ? void 0 : meta.title) || (meta == null ? void 0 : meta.url)) {
931
- lines.push(`Title: ${(_a = meta == null ? void 0 : meta.title) != null ? _a : ""}`.trim());
932
- lines.push(`URL: ${(_b = meta == null ? void 0 : meta.url) != null ? _b : ""}`.trim());
933
- }
934
- lines.push("");
935
- const regions = overview.regions;
936
- const entries = [
937
- ["header", regions.header],
938
- ["navigation", regions.navigation],
939
- ["main", regions.main],
940
- ["sections", regions.sections],
941
- ["sidebar", regions.sidebar],
942
- ["footer", regions.footer],
943
- ["modals", regions.modals]
944
- ];
945
- for (const [key, value] of entries) {
946
- if (!value) continue;
947
- const icon = iconForRegion(key);
948
- if (Array.isArray(value)) {
949
- if (!value.length) continue;
950
- lines.push(`## ${icon} ${capitalize(key)}`);
951
- for (const region of value) lines.push(renderRegionInfo(region));
952
- } else {
953
- lines.push(`## ${icon} ${capitalize(key)}`);
954
- lines.push(renderRegionInfo(value));
955
- }
956
- lines.push("");
957
- }
958
- if ((_c = overview.suggestions) == null ? void 0 : _c.length) {
959
- lines.push("## Suggestions");
960
- for (const s of overview.suggestions) lines.push(`- ${s}`);
961
- lines.push("");
962
- }
963
- lines.push("Next: choose a region (by selector or [sectionId]) and call dom_extract_region for actionable details.");
964
- return wrapXml(lines.join("\n"), meta, "outline");
965
- }
966
- static region(result, opts = {}, meta) {
967
- var _a, _b, _c;
968
- const lines = [];
969
- lines.push("# Region Details");
970
- if ((meta == null ? void 0 : meta.title) || (meta == null ? void 0 : meta.url)) {
971
- lines.push(`Title: ${(_a = meta == null ? void 0 : meta.title) != null ? _a : ""}`.trim());
972
- lines.push(`URL: ${(_b = meta == null ? void 0 : meta.url) != null ? _b : ""}`.trim());
973
- }
974
- lines.push("");
975
- const inter = result.interactive;
976
- if (result.page) {
977
- const ps = [
978
- result.page.hasErrors ? "errors: yes" : "errors: no",
979
- result.page.isLoading ? "loading: yes" : "loading: no",
980
- result.page.hasModals ? "modals: yes" : "modals: no"
981
- ];
982
- lines.push(`Page state: ${ps.join(", ")}`);
983
- }
984
- const summary = [];
985
- const count = (arr) => arr ? arr.length : 0;
986
- summary.push(`${count(inter.buttons)} buttons`);
987
- summary.push(`${count(inter.links)} links`);
988
- summary.push(`${count(inter.inputs)} inputs`);
989
- if ((_c = inter.forms) == null ? void 0 : _c.length) summary.push(`${count(inter.forms)} forms`);
990
- lines.push(`Summary: ${summary.join(", ")}`);
991
- lines.push(selectorQualitySummary(inter));
992
- lines.push("");
993
- lines.push(renderInteractive(inter, opts));
994
- lines.push("");
995
- lines.push("Next: write a script using the most stable selectors above. If selectors look unstable, rerun dom_extract_region with higher detail or call dom_extract_content for text context.");
996
- return wrapXml(lines.join("\n"), meta, "section");
997
- }
998
- static content(content, opts = {}, meta) {
999
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
1000
- const lines = [];
1001
- lines.push("# Content");
1002
- lines.push(`Selector: \`${content.selector}\``);
1003
- lines.push("");
1004
- if ((_a = content.text.headings) == null ? void 0 : _a.length) {
1005
- lines.push("Headings:");
1006
- for (const h of content.text.headings) lines.push(`- H${h.level}: ${truncate(h.text, (_b = opts.maxTextLength) != null ? _b : 120)}`);
1007
- lines.push("");
1008
- }
1009
- if ((_c = content.text.paragraphs) == null ? void 0 : _c.length) {
1010
- const limit = typeof opts.maxElements === "number" ? opts.maxElements : content.text.paragraphs.length;
1011
- lines.push("Paragraphs:");
1012
- for (const p of content.text.paragraphs.slice(0, limit)) lines.push(`- ${truncate(p, (_d = opts.maxTextLength) != null ? _d : 200)}`);
1013
- lines.push("");
1014
- }
1015
- if ((_e = content.text.lists) == null ? void 0 : _e.length) {
1016
- lines.push("Lists:");
1017
- for (const list of content.text.lists) {
1018
- lines.push(`- ${list.type.toUpperCase()}:`);
1019
- const limit = typeof opts.maxElements === "number" ? opts.maxElements : list.items.length;
1020
- for (const item of list.items.slice(0, limit)) lines.push(` - ${truncate(item, (_f = opts.maxTextLength) != null ? _f : 120)}`);
1021
- }
1022
- lines.push("");
1023
- }
1024
- if ((_g = content.tables) == null ? void 0 : _g.length) {
1025
- lines.push("Tables:");
1026
- for (const t of content.tables) {
1027
- lines.push(`- Headers: ${t.headers.join(" | ")}`);
1028
- const limit = typeof opts.maxElements === "number" ? opts.maxElements : t.rows.length;
1029
- for (const row of t.rows.slice(0, limit)) lines.push(` - ${row.join(" | ")}`);
1030
- }
1031
- lines.push("");
1032
- }
1033
- if ((_h = content.media) == null ? void 0 : _h.length) {
1034
- lines.push("Media:");
1035
- const limit = typeof opts.maxElements === "number" ? opts.maxElements : content.media.length;
1036
- for (const m of content.media.slice(0, limit)) lines.push(`- ${m.type.toUpperCase()}: ${(_i = m.alt) != null ? _i : ""} ${m.src ? `\u2192 ${m.src}` : ""}`.trim());
1037
- lines.push("");
1038
- }
1039
- lines.push("Next: if text is insufficient for targeting, call dom_extract_region for interactive selectors.");
1040
- return wrapXml(lines.join("\n"), meta, "content");
1041
- }
1042
- };
1043
- }));
1044
- function resolveSmartDomReader() {
1045
- if (typeof window !== "undefined") {
1046
- const globalWindow = window;
1047
- const direct = globalWindow.SmartDOMReader;
1048
- if (typeof direct === "function") return direct;
1049
- const namespace = globalWindow.SmartDOMReaderNamespace;
1050
- if (namespace && typeof namespace.SmartDOMReader === "function") return namespace.SmartDOMReader;
1051
- }
1052
- try {
1053
- if (typeof __require === "function") {
1054
- const moduleExports = (init_src(), __toCommonJS2(src_exports));
1055
- if (moduleExports && typeof moduleExports.SmartDOMReader === "function") return moduleExports.SmartDOMReader;
1056
- if (moduleExports && typeof moduleExports.default === "function") return moduleExports.default;
1057
- }
1058
- } catch {
1059
- }
1060
- }
1061
- var ProgressiveExtractor;
1062
- var init_progressive = __esmMin((() => {
1063
- init_content_detection();
1064
- init_selectors();
1065
- init_traversal();
1066
- ProgressiveExtractor = class ProgressiveExtractor2 {
1067
- /**
1068
- * Step 1: Extract high-level structural overview
1069
- * This provides a "map" of the page for the AI to understand structure
1070
- */
1071
- static extractStructure(root) {
1072
- const regions = {};
1073
- const header = root.querySelector('header, [role="banner"], .header, #header');
1074
- if (header) regions.header = ProgressiveExtractor2.analyzeRegion(header);
1075
- const navs = root.querySelectorAll('nav, [role="navigation"], .nav, .navigation');
1076
- if (navs.length > 0) regions.navigation = Array.from(navs).map((nav) => ProgressiveExtractor2.analyzeRegion(nav));
1077
- if (root instanceof Document) {
1078
- const main = ContentDetection.findMainContent(root);
1079
- if (main) {
1080
- regions.main = ProgressiveExtractor2.analyzeRegion(main);
1081
- const sections = main.querySelectorAll('section, article, [role="region"]');
1082
- if (sections.length > 0) regions.sections = Array.from(sections).filter((section) => !section.closest("nav, header, footer")).map((section) => ProgressiveExtractor2.analyzeRegion(section));
1083
- }
1084
- } else {
1085
- regions.main = ProgressiveExtractor2.analyzeRegion(root);
1086
- const sections = root.querySelectorAll('section, article, [role="region"]');
1087
- if (sections.length > 0) regions.sections = Array.from(sections).filter((section) => !section.closest("nav, header, footer")).map((section) => ProgressiveExtractor2.analyzeRegion(section));
1088
- }
1089
- const sidebars = root.querySelectorAll('aside, [role="complementary"], .sidebar, #sidebar');
1090
- if (sidebars.length > 0) regions.sidebar = Array.from(sidebars).map((sidebar) => ProgressiveExtractor2.analyzeRegion(sidebar));
1091
- const footer = root.querySelector('footer, [role="contentinfo"], .footer, #footer');
1092
- if (footer) regions.footer = ProgressiveExtractor2.analyzeRegion(footer);
1093
- const modals = root.querySelectorAll('[role="dialog"], .modal, .popup, .overlay');
1094
- const visibleModals = Array.from(modals).filter((modal) => DOMTraversal.isVisible(modal));
1095
- if (visibleModals.length > 0) regions.modals = visibleModals.map((modal) => ProgressiveExtractor2.analyzeRegion(modal));
1096
- const forms = ProgressiveExtractor2.extractFormOverview(root);
1097
- const summary = ProgressiveExtractor2.calculateSummary(root, regions, forms);
1098
- return {
1099
- regions,
1100
- forms,
1101
- summary,
1102
- suggestions: ProgressiveExtractor2.generateSuggestions(regions, summary)
1103
- };
1104
- }
1105
- /**
1106
- * Step 2: Extract detailed information from a specific region
1107
- */
1108
- static extractRegion(selector, doc, options = {}, smartDomReaderCtor) {
1109
- const element = doc.querySelector(selector);
1110
- if (!element) return null;
1111
- const SmartDOMReaderCtor = smartDomReaderCtor != null ? smartDomReaderCtor : resolveSmartDomReader();
1112
- if (!SmartDOMReaderCtor) throw new Error("SmartDOMReader is unavailable. Ensure the Smart DOM Reader module is loaded before calling extractRegion.");
1113
- return new SmartDOMReaderCtor(options).extract(element, options);
1114
- }
1115
- /**
1116
- * Step 3: Extract readable content from a region
1117
- */
1118
- static extractContent(selector, doc, options = {}) {
1119
- const element = doc.querySelector(selector);
1120
- if (!element) return null;
1121
- const result = {
1122
- selector,
1123
- text: {},
1124
- metadata: {
1125
- wordCount: 0,
1126
- hasInteractive: false
1127
- }
1128
- };
1129
- if (options.includeHeadings !== false) {
1130
- const headings = element.querySelectorAll("h1, h2, h3, h4, h5, h6");
1131
- result.text.headings = Array.from(headings).map((h) => ({
1132
- level: Number.parseInt(h.tagName[1], 10),
1133
- text: ProgressiveExtractor2.getTextContent(h, options.maxTextLength)
1134
- }));
1135
- }
1136
- const paragraphs = element.querySelectorAll("p");
1137
- if (paragraphs.length > 0) result.text.paragraphs = Array.from(paragraphs).map((p) => ProgressiveExtractor2.getTextContent(p, options.maxTextLength)).filter((text) => text.length > 0);
1138
- if (options.includeLists !== false) {
1139
- const lists = element.querySelectorAll("ul, ol");
1140
- result.text.lists = Array.from(lists).map((list) => ({
1141
- type: list.tagName.toLowerCase(),
1142
- items: Array.from(list.querySelectorAll("li")).map((li) => ProgressiveExtractor2.getTextContent(li, options.maxTextLength))
1143
- }));
1144
- }
1145
- if (options.includeTables !== false) {
1146
- const tables = element.querySelectorAll("table");
1147
- result.tables = Array.from(tables).map((table) => {
1148
- return {
1149
- headers: Array.from(table.querySelectorAll("th")).map((th) => ProgressiveExtractor2.getTextContent(th)),
1150
- rows: Array.from(table.querySelectorAll("tr")).filter((tr) => tr.querySelector("td")).map((tr) => Array.from(tr.querySelectorAll("td")).map((td) => ProgressiveExtractor2.getTextContent(td)))
1151
- };
1152
- });
1153
- }
1154
- if (options.includeMedia !== false) {
1155
- const images = element.querySelectorAll("img");
1156
- const videos = element.querySelectorAll("video");
1157
- const audios = element.querySelectorAll("audio");
1158
- result.media = [
1159
- ...Array.from(images).map((img) => {
1160
- const item = { type: "img" };
1161
- const alt = img.getAttribute("alt");
1162
- const src = img.getAttribute("src");
1163
- if (alt) item.alt = alt;
1164
- if (src) item.src = src;
1165
- return item;
1166
- }),
1167
- ...Array.from(videos).map((video) => {
1168
- const item = { type: "video" };
1169
- const src = video.getAttribute("src");
1170
- if (src) item.src = src;
1171
- return item;
1172
- }),
1173
- ...Array.from(audios).map((audio) => {
1174
- const item = { type: "audio" };
1175
- const src = audio.getAttribute("src");
1176
- if (src) item.src = src;
1177
- return item;
1178
- })
1179
- ];
1180
- }
1181
- const allText = element.textContent || "";
1182
- result.metadata.wordCount = allText.trim().split(/\s+/).length;
1183
- result.metadata.hasInteractive = element.querySelectorAll("button, a, input, textarea, select").length > 0;
1184
- return result;
1185
- }
1186
- /**
1187
- * Analyze a region and extract summary information
1188
- */
1189
- static analyzeRegion(element) {
1190
- var _a, _b, _c, _d;
1191
- const selector = SelectorGenerator.generateSelectors(element).css;
1192
- const buttons = element.querySelectorAll('button, [role="button"]');
1193
- const links = element.querySelectorAll("a[href]");
1194
- const inputs = element.querySelectorAll("input, textarea, select");
1195
- const forms = element.querySelectorAll("form");
1196
- const lists = element.querySelectorAll("ul, ol");
1197
- const tables = element.querySelectorAll("table");
1198
- const media = element.querySelectorAll("img, video, audio");
1199
- const interactiveCount = buttons.length + links.length + inputs.length;
1200
- let label;
1201
- const ariaLabel = element.getAttribute("aria-label");
1202
- if (ariaLabel) label = ariaLabel;
1203
- else if (element.getAttribute("aria-labelledby")) {
1204
- const labelId = element.getAttribute("aria-labelledby");
1205
- if (labelId) {
1206
- const labelElement = (_a = element.ownerDocument) == null ? void 0 : _a.getElementById(labelId);
1207
- if (labelElement) label = (_b = labelElement.textContent) == null ? void 0 : _b.trim();
1208
- }
1209
- } else {
1210
- const heading = element.querySelector("h1, h2, h3");
1211
- if (heading) label = (_c = heading.textContent) == null ? void 0 : _c.trim();
1212
- }
1213
- const textContent = ((_d = element.textContent) == null ? void 0 : _d.trim()) || "";
1214
- const textPreview = textContent.length > 50 ? `${textContent.substring(0, 50)}...` : textContent;
1215
- const regionInfo = {
1216
- selector,
1217
- interactiveCount,
1218
- hasForm: forms.length > 0,
1219
- hasList: lists.length > 0,
1220
- hasTable: tables.length > 0,
1221
- hasMedia: media.length > 0
1222
- };
1223
- if (label) regionInfo.label = label;
1224
- const role = element.getAttribute("role");
1225
- if (role) regionInfo.role = role;
1226
- if (buttons.length > 0) regionInfo.buttonCount = buttons.length;
1227
- if (links.length > 0) regionInfo.linkCount = links.length;
1228
- if (inputs.length > 0) regionInfo.inputCount = inputs.length;
1229
- if (textPreview.length > 0) regionInfo.textPreview = textPreview;
1230
- return regionInfo;
1231
- }
1232
- /**
1233
- * Extract overview of forms on the page
1234
- */
1235
- static extractFormOverview(root) {
1236
- const forms = root.querySelectorAll("form");
1237
- return Array.from(forms).map((form) => {
1238
- var _a, _b, _c;
1239
- const inputs = form.querySelectorAll("input, textarea, select");
1240
- const selector = SelectorGenerator.generateSelectors(form).css;
1241
- let location = "unknown";
1242
- if (form.closest('header, [role="banner"]')) location = "header";
1243
- else if (form.closest('nav, [role="navigation"]')) location = "navigation";
1244
- else if (form.closest('main, [role="main"]')) location = "main";
1245
- else if (form.closest('aside, [role="complementary"]')) location = "sidebar";
1246
- else if (form.closest('footer, [role="contentinfo"]')) location = "footer";
1247
- let purpose;
1248
- const formId = (_a = form.getAttribute("id")) == null ? void 0 : _a.toLowerCase();
1249
- const formClass = (_b = form.getAttribute("class")) == null ? void 0 : _b.toLowerCase();
1250
- const formAction = (_c = form.getAttribute("action")) == null ? void 0 : _c.toLowerCase();
1251
- const hasEmail = form.querySelector('input[type="email"]');
1252
- const hasPassword = form.querySelector('input[type="password"]');
1253
- if (form.querySelector('input[type="search"]') || (formId == null ? void 0 : formId.includes("search")) || (formClass == null ? void 0 : formClass.includes("search"))) purpose = "search";
1254
- else if (hasPassword && hasEmail) purpose = "login";
1255
- else if (hasPassword) purpose = "authentication";
1256
- else if ((formId == null ? void 0 : formId.includes("contact")) || (formClass == null ? void 0 : formClass.includes("contact"))) purpose = "contact";
1257
- else if ((formId == null ? void 0 : formId.includes("subscribe")) || (formClass == null ? void 0 : formClass.includes("subscribe"))) purpose = "subscription";
1258
- else if ((formAction == null ? void 0 : formAction.includes("checkout")) || (formClass == null ? void 0 : formClass.includes("checkout"))) purpose = "checkout";
1259
- const formOverview = {
1260
- selector,
1261
- location,
1262
- inputCount: inputs.length
1263
- };
1264
- if (purpose) formOverview.purpose = purpose;
1265
- return formOverview;
1266
- });
1267
- }
1268
- /**
1269
- * Calculate summary statistics
1270
- */
1271
- static calculateSummary(root, regions, forms) {
1272
- var _a, _b;
1273
- const allInteractive = root.querySelectorAll("button, a[href], input, textarea, select");
1274
- const allSections = root.querySelectorAll('section, article, [role="region"]');
1275
- const hasModals = (((_a = regions.modals) == null ? void 0 : _a.length) || 0) > 0;
1276
- const hasErrors = [
1277
- ".error",
1278
- ".alert-danger",
1279
- '[role="alert"]'
1280
- ].some((sel) => {
1281
- const element = root.querySelector(sel);
1282
- return element ? DOMTraversal.isVisible(element) : false;
1283
- });
1284
- const isLoading = [
1285
- ".loading",
1286
- ".spinner",
1287
- '[aria-busy="true"]'
1288
- ].some((sel) => {
1289
- const element = root.querySelector(sel);
1290
- return element ? DOMTraversal.isVisible(element) : false;
1291
- });
1292
- const summary = {
1293
- totalInteractive: allInteractive.length,
1294
- totalForms: forms.length,
1295
- totalSections: allSections.length,
1296
- hasModals,
1297
- hasErrors,
1298
- isLoading
1299
- };
1300
- const mainContentSelector = (_b = regions.main) == null ? void 0 : _b.selector;
1301
- if (mainContentSelector) summary.mainContentSelector = mainContentSelector;
1302
- return summary;
1303
- }
1304
- /**
1305
- * Generate AI-friendly suggestions
1306
- */
1307
- static generateSuggestions(regions, summary) {
1308
- const suggestions = [];
1309
- if (summary.hasErrors) suggestions.push("Page has error indicators - check error messages before interacting");
1310
- if (summary.isLoading) suggestions.push("Page appears to be loading - wait or check loading state");
1311
- if (summary.hasModals) suggestions.push("Modal/dialog is open - may need to interact with or close it first");
1312
- if (regions.main && regions.main.interactiveCount > 10) suggestions.push(`Main content has ${regions.main.interactiveCount} interactive elements - consider filtering`);
1313
- if (summary.totalForms > 0) suggestions.push(`Found ${summary.totalForms} form(s) on the page`);
1314
- if (!regions.main) suggestions.push("No clear main content area detected - may need to explore regions");
1315
- return suggestions;
1316
- }
1317
- /**
1318
- * Get text content with optional truncation
1319
- */
1320
- static getTextContent(element, maxLength) {
1321
- var _a;
1322
- const text = ((_a = element.textContent) == null ? void 0 : _a.trim()) || "";
1323
- if (maxLength && text.length > maxLength) return `${text.substring(0, maxLength)}...`;
1324
- return text;
1325
- }
1326
- };
1327
- }));
1328
- var init_types = __esmMin((() => {
1329
- }));
1330
- var src_exports = /* @__PURE__ */ __exportAll({
1331
- ContentDetection: () => ContentDetection,
1332
- MarkdownFormatter: () => MarkdownFormatter,
1333
- ProgressiveExtractor: () => ProgressiveExtractor,
1334
- SelectorGenerator: () => SelectorGenerator,
1335
- SmartDOMReader: () => SmartDOMReader,
1336
- default: () => SmartDOMReader
1337
- });
1338
- var SmartDOMReader;
1339
- var init_src = __esmMin((() => {
1340
- init_content_detection();
1341
- init_selectors();
1342
- init_traversal();
1343
- init_markdown_formatter();
1344
- init_progressive();
1345
- init_types();
1346
- SmartDOMReader = class SmartDOMReader2 {
1347
- constructor(options = {}) {
1348
- __publicField(this, "options");
1349
- var _a;
1350
- this.options = {
1351
- mode: options.mode || "interactive",
1352
- maxDepth: options.maxDepth || 5,
1353
- includeHidden: options.includeHidden || false,
1354
- includeShadowDOM: (_a = options.includeShadowDOM) != null ? _a : true,
1355
- includeIframes: options.includeIframes || false,
1356
- viewportOnly: options.viewportOnly || false,
1357
- mainContentOnly: options.mainContentOnly || false,
1358
- customSelectors: options.customSelectors || [],
1359
- ...options.attributeTruncateLength !== void 0 && { attributeTruncateLength: options.attributeTruncateLength },
1360
- ...options.dataAttributeTruncateLength !== void 0 && { dataAttributeTruncateLength: options.dataAttributeTruncateLength },
1361
- ...options.textTruncateLength !== void 0 && { textTruncateLength: options.textTruncateLength },
1362
- ...options.filter !== void 0 && { filter: options.filter }
1363
- };
1364
- }
1365
- /**
1366
- * Main extraction method - extracts all data in one pass
1367
- * @param rootElement The document or element to extract from
1368
- * @param runtimeOptions Options to override constructor options
1369
- */
1370
- extract(rootElement = document, runtimeOptions) {
1371
- const startTime = Date.now();
1372
- const doc = rootElement instanceof Document ? rootElement : rootElement.ownerDocument;
1373
- const options = {
1374
- ...this.options,
1375
- ...runtimeOptions
1376
- };
1377
- let container = rootElement instanceof Document ? doc : rootElement;
1378
- if (options.mainContentOnly && rootElement instanceof Document) container = ContentDetection.findMainContent(doc);
1379
- const pageState = this.extractPageState(doc);
1380
- const landmarks = this.extractLandmarks(doc);
1381
- const interactive = this.extractInteractiveElements(container, options);
1382
- const result = {
1383
- mode: options.mode,
1384
- timestamp: startTime,
1385
- page: pageState,
1386
- landmarks,
1387
- interactive
1388
- };
1389
- if (options.mode === "full") {
1390
- const semantic = this.extractSemanticElements(container, options);
1391
- const metadata = this.extractMetadata(doc, container, options);
1392
- return {
1393
- ...result,
1394
- semantic,
1395
- metadata
1396
- };
1397
- }
1398
- return result;
1399
- }
1400
- /**
1401
- * Extract page state information
1402
- */
1403
- extractPageState(doc) {
1404
- var _a;
1405
- const hasFocus = this.getFocusedElement(doc);
1406
- return {
1407
- url: ((_a = doc.location) == null ? void 0 : _a.href) || "",
1408
- title: doc.title || "",
1409
- hasErrors: this.detectErrors(doc),
1410
- isLoading: this.detectLoading(doc),
1411
- hasModals: this.detectModals(doc),
1412
- ...hasFocus !== void 0 && { hasFocus }
1413
- };
1414
- }
1415
- /**
1416
- * Extract page landmarks
1417
- */
1418
- extractLandmarks(doc) {
1419
- const detected = ContentDetection.detectLandmarks(doc);
1420
- return {
1421
- navigation: this.elementsToSelectors(detected.navigation || []),
1422
- main: this.elementsToSelectors(detected.main || []),
1423
- forms: this.elementsToSelectors(detected.form || []),
1424
- headers: this.elementsToSelectors(detected.banner || []),
1425
- footers: this.elementsToSelectors(detected.contentinfo || []),
1426
- articles: this.elementsToSelectors(detected.region || []),
1427
- sections: this.elementsToSelectors(detected.region || [])
1428
- };
1429
- }
1430
- /**
1431
- * Convert elements to selector strings
1432
- */
1433
- elementsToSelectors(elements) {
1434
- return elements.map((el) => SelectorGenerator.generateSelectors(el).css);
1435
- }
1436
- /**
1437
- * Extract interactive elements
1438
- */
1439
- extractInteractiveElements(container, options) {
1440
- const buttons = [];
1441
- const links = [];
1442
- const inputs = [];
1443
- const clickable = [];
1444
- container.querySelectorAll('button, [role="button"], input[type="button"], input[type="submit"]').forEach((el) => {
1445
- if (this.shouldIncludeElement(el, options)) {
1446
- const extracted = DOMTraversal.extractElement(el, options);
1447
- if (extracted) buttons.push(extracted);
1448
- }
1449
- });
1450
- container.querySelectorAll("a[href]").forEach((el) => {
1451
- if (this.shouldIncludeElement(el, options)) {
1452
- const extracted = DOMTraversal.extractElement(el, options);
1453
- if (extracted) links.push(extracted);
1454
- }
1455
- });
1456
- container.querySelectorAll('input:not([type="button"]):not([type="submit"]), textarea, select').forEach((el) => {
1457
- if (this.shouldIncludeElement(el, options)) {
1458
- const extracted = DOMTraversal.extractElement(el, options);
1459
- if (extracted) inputs.push(extracted);
1460
- }
1461
- });
1462
- if (options.customSelectors) options.customSelectors.forEach((selector) => {
1463
- container.querySelectorAll(selector).forEach((el) => {
1464
- if (this.shouldIncludeElement(el, options)) {
1465
- const extracted = DOMTraversal.extractElement(el, options);
1466
- if (extracted) clickable.push(extracted);
1467
- }
1468
- });
1469
- });
1470
- return {
1471
- buttons,
1472
- links,
1473
- inputs,
1474
- forms: this.extractForms(container, options),
1475
- clickable
1476
- };
1477
- }
1478
- /**
1479
- * Extract form information
1480
- */
1481
- extractForms(container, options) {
1482
- const forms = [];
1483
- container.querySelectorAll("form").forEach((form) => {
1484
- if (!this.shouldIncludeElement(form, options)) return;
1485
- const formInputs = [];
1486
- const formButtons = [];
1487
- form.querySelectorAll('input:not([type="button"]):not([type="submit"]), textarea, select').forEach((input) => {
1488
- const extracted = DOMTraversal.extractElement(input, options);
1489
- if (extracted) formInputs.push(extracted);
1490
- });
1491
- form.querySelectorAll('button, input[type="button"], input[type="submit"]').forEach((button) => {
1492
- const extracted = DOMTraversal.extractElement(button, options);
1493
- if (extracted) formButtons.push(extracted);
1494
- });
1495
- const action = form.getAttribute("action");
1496
- const method = form.getAttribute("method");
1497
- const formInfo = {
1498
- selector: SelectorGenerator.generateSelectors(form).css,
1499
- inputs: formInputs,
1500
- buttons: formButtons
1501
- };
1502
- if (action) formInfo.action = action;
1503
- if (method) formInfo.method = method;
1504
- forms.push(formInfo);
1505
- });
1506
- return forms;
1507
- }
1508
- /**
1509
- * Extract semantic elements (full mode only)
1510
- */
1511
- extractSemanticElements(container, options) {
1512
- const headings = [];
1513
- const images = [];
1514
- const tables = [];
1515
- const lists = [];
1516
- const articles = [];
1517
- container.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach((el) => {
1518
- if (this.shouldIncludeElement(el, options)) {
1519
- const extracted = DOMTraversal.extractElement(el, options);
1520
- if (extracted) headings.push(extracted);
1521
- }
1522
- });
1523
- container.querySelectorAll("img").forEach((el) => {
1524
- if (this.shouldIncludeElement(el, options)) {
1525
- const extracted = DOMTraversal.extractElement(el, options);
1526
- if (extracted) images.push(extracted);
1527
- }
1528
- });
1529
- container.querySelectorAll("table").forEach((el) => {
1530
- if (this.shouldIncludeElement(el, options)) {
1531
- const extracted = DOMTraversal.extractElement(el, options);
1532
- if (extracted) tables.push(extracted);
1533
- }
1534
- });
1535
- container.querySelectorAll("ul, ol").forEach((el) => {
1536
- if (this.shouldIncludeElement(el, options)) {
1537
- const extracted = DOMTraversal.extractElement(el, options);
1538
- if (extracted) lists.push(extracted);
1539
- }
1540
- });
1541
- container.querySelectorAll('article, [role="article"]').forEach((el) => {
1542
- if (this.shouldIncludeElement(el, options)) {
1543
- const extracted = DOMTraversal.extractElement(el, options);
1544
- if (extracted) articles.push(extracted);
1545
- }
1546
- });
1547
- return {
1548
- headings,
1549
- images,
1550
- tables,
1551
- lists,
1552
- articles
1553
- };
1554
- }
1555
- /**
1556
- * Extract metadata
1557
- */
1558
- extractMetadata(doc, container, options) {
1559
- const allElements = container.querySelectorAll("*");
1560
- const extractedElements = container.querySelectorAll("button, a, input, textarea, select, h1, h2, h3, h4, h5, h6, img, table, ul, ol, article").length;
1561
- const metadata = {
1562
- totalElements: allElements.length,
1563
- extractedElements
1564
- };
1565
- if (options.mainContentOnly && container instanceof Element) metadata.mainContent = SelectorGenerator.generateSelectors(container).css;
1566
- const language = doc.documentElement.getAttribute("lang");
1567
- if (language) metadata.language = language;
1568
- return metadata;
1569
- }
1570
- /**
1571
- * Check if element should be included based on options
1572
- */
1573
- shouldIncludeElement(element, options) {
1574
- if (!options.includeHidden && !DOMTraversal.isVisible(element)) return false;
1575
- if (options.viewportOnly && !DOMTraversal.isInViewport(element)) return false;
1576
- if (options.filter && !DOMTraversal.passesFilter(element, options.filter)) return false;
1577
- return true;
1578
- }
1579
- /**
1580
- * Detect errors on the page
1581
- */
1582
- detectErrors(doc) {
1583
- return [
1584
- ".error",
1585
- ".alert-danger",
1586
- '[role="alert"]',
1587
- ".error-message"
1588
- ].some((sel) => {
1589
- const element = doc.querySelector(sel);
1590
- return element ? DOMTraversal.isVisible(element) : false;
1591
- });
1592
- }
1593
- /**
1594
- * Detect if page is loading
1595
- */
1596
- detectLoading(doc) {
1597
- return [
1598
- ".loading",
1599
- ".spinner",
1600
- '[aria-busy="true"]',
1601
- ".loader"
1602
- ].some((sel) => {
1603
- const element = doc.querySelector(sel);
1604
- return element ? DOMTraversal.isVisible(element) : false;
1605
- });
1606
- }
1607
- /**
1608
- * Detect modal dialogs
1609
- */
1610
- detectModals(doc) {
1611
- return [
1612
- '[role="dialog"]',
1613
- ".modal",
1614
- ".popup",
1615
- ".overlay"
1616
- ].some((sel) => {
1617
- const element = doc.querySelector(sel);
1618
- return element ? DOMTraversal.isVisible(element) : false;
1619
- });
1620
- }
1621
- /**
1622
- * Get currently focused element
1623
- */
1624
- getFocusedElement(doc) {
1625
- const focused = doc.activeElement;
1626
- if (focused && focused !== doc.body) return SelectorGenerator.generateSelectors(focused).css;
1627
- }
1628
- /**
1629
- * Quick extraction for interactive elements only
1630
- * @param doc The document to extract from
1631
- * @param options Extraction options
1632
- */
1633
- static extractInteractive(doc, options = {}) {
1634
- return new SmartDOMReader2({
1635
- ...options,
1636
- mode: "interactive"
1637
- }).extract(doc);
1638
- }
1639
- /**
1640
- * Quick extraction for full content
1641
- * @param doc The document to extract from
1642
- * @param options Extraction options
1643
- */
1644
- static extractFull(doc, options = {}) {
1645
- return new SmartDOMReader2({
1646
- ...options,
1647
- mode: "full"
1648
- }).extract(doc);
1649
- }
1650
- /**
1651
- * Extract from a specific element
1652
- * @param element The element to extract from
1653
- * @param mode The extraction mode
1654
- * @param options Additional options
1655
- */
1656
- static extractFromElement(element, mode = "interactive", options = {}) {
1657
- return new SmartDOMReader2({
1658
- ...options,
1659
- mode
1660
- }).extract(element);
1661
- }
1662
- };
1663
- }));
1664
- init_src();
1665
-
1666
- // src/utils/smart-dom-adapter.ts
1667
- var PLAIN_CSS_CANDIDATE_TYPES = /* @__PURE__ */ new Set(["id", "data-testid", "role-aria", "name", "class-path", "css-path"]);
1668
- function looksLikeXPath(value) {
1669
- const v = value.trim();
1670
- return v.startsWith("/") || v.startsWith("(") || v.startsWith("./");
1671
- }
1672
- function bestPlainCssSelector(el) {
1673
- const candidates = el.selector.candidates;
1674
- if (candidates && candidates.length > 0) {
1675
- let best = null;
1676
- for (const c of candidates) {
1677
- if (!PLAIN_CSS_CANDIDATE_TYPES.has(c.type)) continue;
1678
- if (!c.value || looksLikeXPath(c.value)) continue;
1679
- if (!best || c.score > best.score) best = c;
1680
- }
1681
- if (best) return best.value;
1682
- }
1683
- const css = el.selector.css;
1684
- if (css && !looksLikeXPath(css)) return css;
1685
- return null;
1686
- }
1687
- function classifyInteractivity(el) {
1688
- var _a;
1689
- const tag = el.tag.toLowerCase();
1690
- const role = (_a = el.interaction.role) != null ? _a : el.attributes.role;
1691
- if (tag === "a" && (el.interaction.nav || el.attributes.href != null)) {
1692
- return "navigable";
1693
- }
1694
- if (tag === "input" || tag === "select" || tag === "textarea") return "input";
1695
- if (role === "textbox" || role === "combobox" || role === "listbox" || role === "spinbutton") {
1696
- return "input";
1697
- }
1698
- if (el.interaction.change && !el.interaction.click) return "input";
1699
- if (tag === "button" || role === "button" || el.interaction.click || el.interaction.submit) {
1700
- return "clickable";
1701
- }
1702
- return "static";
1703
- }
1704
- function collectAttributes(el) {
1705
- const attrs = { ...el.attributes };
1706
- const role = el.interaction.role;
1707
- if (role && !attrs.role) attrs.role = role;
1708
- return attrs;
1709
- }
1710
- function isExcluded(el, excludeSelector) {
1711
- var _a, _b;
1712
- if (!excludeSelector) return false;
1713
- const haystacks = [
1714
- el.selector.css,
1715
- el.selector.xpath,
1716
- el.context.nearestForm,
1717
- el.context.nearestSection,
1718
- el.context.nearestMain,
1719
- el.context.nearestNav,
1720
- ...(_b = (_a = el.selector.candidates) == null ? void 0 : _a.map((c) => c.value)) != null ? _b : [],
1721
- ...el.context.parentChain
1722
- ];
1723
- return haystacks.some((h) => !!h && h.includes(excludeSelector));
1724
- }
1725
- function smartDomResultToEnriched(result, opts = {}) {
1726
- var _a, _b, _c;
1727
- const includeSemantic = (_a = opts.includeSemantic) != null ? _a : true;
1728
- const excludeSelector = (_b = opts.excludeSelector) != null ? _b : ".persona-host";
1729
- const maxTextLength = (_c = opts.maxTextLength) != null ? _c : 200;
1730
- const groups = [
1731
- result.interactive.buttons,
1732
- result.interactive.links,
1733
- result.interactive.inputs,
1734
- result.interactive.clickable
1735
- ];
1736
- if (includeSemantic && result.semantic) {
1737
- groups.push(
1738
- result.semantic.headings,
1739
- result.semantic.images,
1740
- result.semantic.tables,
1741
- result.semantic.lists,
1742
- result.semantic.articles
1743
- );
1744
- }
1745
- const out = [];
1746
- const seen = /* @__PURE__ */ new Set();
1747
- const visit = (el) => {
1748
- var _a2, _b2, _c2;
1749
- if (isExcluded(el, excludeSelector)) return true;
1750
- const selector = bestPlainCssSelector(el);
1751
- if (selector && !seen.has(selector)) {
1752
- seen.add(selector);
1753
- out.push({
1754
- selector,
1755
- tagName: el.tag.toLowerCase(),
1756
- text: ((_a2 = el.text) != null ? _a2 : "").trim().substring(0, maxTextLength),
1757
- role: (_c2 = (_b2 = el.interaction.role) != null ? _b2 : el.attributes.role) != null ? _c2 : null,
1758
- interactivity: classifyInteractivity(el),
1759
- attributes: collectAttributes(el)
1760
- });
1761
- if (opts.maxElements && out.length >= opts.maxElements) return false;
1762
- }
1763
- if (el.children) {
1764
- for (const child of el.children) {
1765
- if (!visit(child)) return false;
1766
- }
1767
- }
1768
- return true;
1769
- };
1770
- for (const group of groups) {
1771
- if (!group) continue;
1772
- for (const el of group) {
1773
- if (!visit(el)) return out;
1774
- }
1775
- }
1776
- return out;
1777
- }
1778
-
1779
- // src/utils/dom-context.ts
1780
- var TEXT_PREVIEW_LEN = 100;
1781
- function formatEnrichedContext(elements, options = {}) {
1782
- var _a;
1783
- if (elements.length === 0) {
1784
- return "No page elements found.";
1785
- }
1786
- const mode = (_a = options.mode) != null ? _a : "structured";
1787
- const sections = [];
1788
- if (mode === "structured") {
1789
- const summaries = elements.map((el) => el.formattedSummary).filter((s) => !!s && s.length > 0);
1790
- if (summaries.length > 0) {
1791
- sections.push(
1792
- `Structured summaries:
1793
- ${summaries.map((s) => `- ${s.split("\n").join("\n ")}`).join("\n")}`
1794
- );
1795
- }
1796
- }
1797
- const groups = {
1798
- clickable: [],
1799
- navigable: [],
1800
- input: [],
1801
- static: []
1802
- };
1803
- for (const el of elements) {
1804
- if (mode === "structured" && el.formattedSummary) continue;
1805
- groups[el.interactivity].push(el);
1806
- }
1807
- if (groups.clickable.length > 0) {
1808
- const lines = groups.clickable.map(
1809
- (el) => `- ${el.selector}: "${el.text.substring(0, TEXT_PREVIEW_LEN)}" (clickable)`
1810
- );
1811
- sections.push(`Interactive elements:
1812
- ${lines.join("\n")}`);
1813
- }
1814
- if (groups.navigable.length > 0) {
1815
- const lines = groups.navigable.map(
1816
- (el) => `- ${el.selector}${el.attributes.href ? `[href="${el.attributes.href}"]` : ""}: "${el.text.substring(0, TEXT_PREVIEW_LEN)}" (navigable)`
1817
- );
1818
- sections.push(`Navigation links:
1819
- ${lines.join("\n")}`);
1820
- }
1821
- if (groups.input.length > 0) {
1822
- const lines = groups.input.map(
1823
- (el) => `- ${el.selector}${el.attributes.type ? `[type="${el.attributes.type}"]` : ""}: "${el.text.substring(0, TEXT_PREVIEW_LEN)}" (input)`
1824
- );
1825
- sections.push(`Form inputs:
1826
- ${lines.join("\n")}`);
1827
- }
1828
- if (groups.static.length > 0) {
1829
- const lines = groups.static.map(
1830
- (el) => `- ${el.selector}: "${el.text.substring(0, TEXT_PREVIEW_LEN)}"`
1831
- );
1832
- sections.push(`Content:
1833
- ${lines.join("\n")}`);
1834
- }
1835
- return sections.join("\n\n");
1836
- }
1837
-
1838
- // src/smart-dom-reader.ts
1839
- function collectSmartDomContext(opts = {}) {
1840
- var _a, _b, _c;
1841
- const mode = (_a = opts.mode) != null ? _a : "interactive";
1842
- let result;
1843
- if (opts.root) {
1844
- result = SmartDOMReader.extractFromElement(
1845
- opts.root,
1846
- mode,
1847
- opts.extractionOptions
1848
- );
1849
- } else {
1850
- const doc = (_b = opts.document) != null ? _b : typeof document !== "undefined" ? document : void 0;
1851
- if (!doc) return [];
1852
- result = mode === "full" ? SmartDOMReader.extractFull(doc, opts.extractionOptions) : SmartDOMReader.extractInteractive(doc, opts.extractionOptions);
1853
- }
1854
- return smartDomResultToEnriched(result, {
1855
- includeSemantic: (_c = opts.includeSemantic) != null ? _c : mode === "full",
1856
- excludeSelector: opts.excludeSelector,
1857
- maxTextLength: opts.maxTextLength,
1858
- maxElements: opts.maxElements
1859
- });
1860
- }
1861
- function createSmartDomReaderContextProvider(opts = {}) {
1862
- var _a;
1863
- const contextKey = (_a = opts.contextKey) != null ? _a : "pageContext";
1864
- return () => {
1865
- const elements = collectSmartDomContext(opts);
1866
- if (elements.length === 0) return {};
1867
- return { [contextKey]: formatEnrichedContext(elements) };
1868
- };
1869
- }
1870
- // Annotate the CommonJS export names for ESM import in node:
1871
- 0 && (module.exports = {
1872
- collectSmartDomContext,
1873
- createSmartDomReaderContextProvider,
1874
- smartDomResultToEnriched
1875
- });
23
+ `)}function Z(s={}){var n,r,i;let e=(n=s.mode)!=null?n:"interactive",t;if(s.root)t=A.extractFromElement(s.root,e,s.extractionOptions);else{let a=(r=s.document)!=null?r:typeof document!="undefined"?document:void 0;if(!a)return[];t=e==="full"?A.extractFull(a,s.extractionOptions):A.extractInteractive(a,s.extractionOptions)}return k(t,{includeSemantic:(i=s.includeSemantic)!=null?i:e==="full",excludeSelector:s.excludeSelector,maxTextLength:s.maxTextLength,maxElements:s.maxElements})}function $t(s={}){var t;let e=(t=s.contextKey)!=null?t:"pageContext";return()=>{let n=Z(s);return n.length===0?{}:{[e]:Q(n)}}}0&&(module.exports={collectSmartDomContext,createSmartDomReaderContextProvider,smartDomResultToEnriched});