UNPKG

@stdbl/wao

Version:

Optimize web pages for LLM agent interaction and understanding

164 lines (150 loc) 13.7 kB
var d=e=>{console.log(`LLM Optimization Library: ${e}`)},w=e=>document.createComment(e);var c={originalDOM:document.body,optimizedElements:[],interactionMappings:[],isActive:!1,pageStructure:void 0,dataFlows:[],accessibility:{ariaLabels:{},tabOrder:[],colorContrast:{}}},S=()=>{let e=document.createElement("style");e.id="wao-styles",e.textContent=` .wao-optimized-element { border: 2px solid #3498db; padding: 8px; margin: 4px; background-color: #f8f9fa; border-radius: 4px; position: relative; display: block; } .wao-description { font-family: monospace; margin-bottom: 6px; color: #2c3e50; display: block; } .wao-tag { background-color: #3498db; color: white; padding: 2px 6px; border-radius: 3px; font-size: 12px; font-family: monospace; position: absolute; top: -10px; right: 5px; } .wao-interaction { margin-top: 6px; font-style: italic; color: #e74c3c; font-size: 12px; border-top: 1px dashed #ccc; padding-top: 4px; } .wao-toggle { position: fixed; bottom: 20px; right: 20px; z-index: 10000; padding: 8px 16px; background-color: #3498db; color: white; border: none; border-radius: 4px; cursor: pointer; font-weight: bold; box-shadow: 0 2px 5px rgba(0,0,0,0.2); } .wao-role { position: absolute; top: -10px; left: 5px; background-color: #27ae60; color: white; padding: 2px 6px; border-radius: 3px; font-size: 12px; font-family: monospace; } .wao-importance-primary { border-color: #e74c3c !important; border-width: 3px !important; } .wao-importance-secondary { border-color: #f39c12 !important; } .wao-importance-tertiary { border-color: #95a5a6 !important; border-style: dashed !important; } .wao-data-flow { position: relative; border: 1px dashed #9b59b6; margin: 10px 0; padding: 8px; background-color: rgba(155, 89, 182, 0.1); } .wao-data-flow::before { content: attr(data-description); font-size: 12px; color: #9b59b6; position: absolute; top: -10px; left: 10px; background: white; padding: 0 5px; } .wao-page-structure { position: fixed; top: 20px; right: 20px; background: rgba(52, 152, 219, 0.9); color: white; padding: 10px; border-radius: 4px; font-family: monospace; font-size: 12px; z-index: 10000; max-width: 300px; max-height: 300px; overflow: auto; } body[data-wao-active="true"] { filter: grayscale(0.3); background-color: #f0f0f0 !important; } .wao-accessibility-issue { outline: 3px solid #c0392b !important; position: relative; } .wao-accessibility-issue::after { content: "\u26A0\uFE0F"; position: absolute; top: 0; right: 0; background: #c0392b; color: white; padding: 2px; } `,document.head.appendChild(e)},L=()=>{let e=w(` LLM Agent Instructions: - To activate this optimization library, set 'data-wao-active="true"' on the body element - For visual descriptions, call 'window.WAO.describeElementVisually(selector, description, elementType)' - To map interactions, call 'window.WAO.defineInteraction(selector, interactionType, methodName)' - To describe page structure, call 'window.WAO.describePage(pageInfo)' - To analyze page semantics, call 'window.WAO.extractSemanticStructure()' - To describe data flows, call 'window.WAO.describeDataFlow(flow)' - To analyze accessibility, call 'window.WAO.analyzeAccessibility()' - To highlight element roles, call 'window.WAO.highlightElementRole(selector, role)' - To deactivate, call 'window.WAO.deactivateOptimizer()' `);document.body.prepend(e),new MutationObserver(o=>{o.forEach(t=>{if(t.attributeName==="data-wao-active"){let n=document.body,a=n.getAttribute("data-wao-active")==="true";a&&!c.isActive?g(n):!a&&c.isActive&&b()}})}).observe(document.body,{attributes:!0})},m=()=>c.isActive,g=e=>{m()?d("Optimizer already active"):(c.originalDOM=e.cloneNode(!0),c.isActive=!0,document.body.setAttribute("data-wao-active","true"),S(),z(),T(),d("Optimizer activated"))},b=()=>{if(c.isActive){c.optimizedElements.forEach(N);let e=document.getElementById("wao-styles");e&&e.remove();let i=document.querySelector(".wao-toggle");i&&i.remove(),document.body.removeAttribute("data-wao-active"),M(),c.optimizedElements=[],c.interactionMappings=[],c.isActive=!1,d("Optimizer deactivated")}else d("Optimizer is not active")},h=(e,i,o,t)=>{if(!m())return;let n={elementSelector:e,interactionType:i,methodName:o,expectedOutcome:t};c.interactionMappings.push(n);let a=document.querySelector(e);if(a){let r=a.closest(".wao-optimized-element");if(r){let s=r.querySelector(".wao-interaction");s||(s=document.createElement("div"),s.className="wao-interaction",r.appendChild(s));let l=`${i} \u2192 ${o}`;s.textContent+=l+(t?` (${t})`:"")+" "}}},p=e=>{let i=e.target;c.interactionMappings.forEach(o=>{let t=i.closest(o.elementSelector);if(t&&o.interactionType===e.type){d(`Interaction triggered: ${o.methodName} on ${o.elementSelector}`);let n=window[o.methodName];if(typeof n=="function")try{n(t)}catch(a){d(`Error executing method ${o.methodName}: ${a}`)}}})},z=()=>{let e=document.querySelector(".wao-toggle");e&&e.remove();let i=document.createElement("button");i.className="wao-toggle",i.textContent=c.isActive?"Deactivate Optimization":"Activate Optimization",i.addEventListener("click",()=>{c.isActive?b():g(document.body),i.textContent=c.isActive?"Deactivate Optimization":"Activate Optimization"}),document.body.appendChild(i)},T=()=>{document.addEventListener("click",p),document.addEventListener("mouseover",p),document.addEventListener("focus",p,!0)},M=()=>{document.removeEventListener("click",p),document.removeEventListener("mouseover",p),document.removeEventListener("focus",p,!0)},f=(e,i,o,t)=>{if(!m())return;let n=document.querySelector(e);if(!n){d(`Element not found: ${e}`);return}if(n.closest(".wao-optimized-element")){d(`Element already optimized: ${e}`);return}let a=document.createElement("div");a.className="wao-optimized-element",a.setAttribute("data-original-selector",e),t?.importance&&a.classList.add(`wao-importance-${t.importance}`);let r=document.createElement("div");if(r.className="wao-description",r.textContent=i,t?.dataContext){let l=document.createElement("div");l.style.fontSize="12px",l.style.fontStyle="italic",l.textContent=`Data: ${t.dataContext}`,r.appendChild(l)}let s=document.createElement("span");if(s.className="wao-tag",s.textContent=`<${o}>`,t?.role){let l=document.createElement("span");l.className="wao-role",l.textContent=t.role,a.appendChild(l)}a.appendChild(s),a.appendChild(r),n.parentNode?.replaceChild(a,n),c.optimizedElements.push({selector:e,description:i,originalHTML:n.outerHTML,role:t?.role,importance:t?.importance,dataContext:t?.dataContext})},N=e=>{let i=document.querySelector(`.wao-optimized-element[data-original-selector="${e.selector}"]`);if(i){let o=document.createElement("div");if(e.originalHTML){o.innerHTML=e.originalHTML;let t=o.firstElementChild;t&&i.parentNode?.replaceChild(t,i)}}},y=e=>{if(!m())return;c.pageStructure={...c.pageStructure,...e};let i=document.querySelector(".wao-page-structure");i||(i=document.createElement("div"),i.className="wao-page-structure",document.body.appendChild(i));let o="<h3>Page Structure</h3>";if(e.title&&(o+=`<div><strong>Title:</strong> ${e.title}</div>`),e.mainContent){o+=`<div><strong>Main:</strong> ${e.mainContent}</div>`;let t=document.querySelector(e.mainContent);t&&!t.classList.contains("wao-optimized-element")&&(t.setAttribute("data-wao-role","main-content"),t.setAttribute("style","border: 2px dashed #3498db !important; padding: 8px;"))}if(e.navigation&&(o+="<div><strong>Navigation:</strong></div><ul>",(Array.isArray(e.navigation)?e.navigation:[e.navigation]).forEach(n=>{o+=`<li>${n}</li>`;let a=document.querySelector(n);a&&!a.classList.contains("wao-optimized-element")&&(a.setAttribute("data-wao-role","navigation"),a.setAttribute("style","border: 2px dashed #2ecc71 !important; padding: 4px;"))}),o+="</ul>"),e.sidebar&&(o+="<div><strong>Sidebars:</strong></div><ul>",(Array.isArray(e.sidebar)?e.sidebar:[e.sidebar]).forEach(n=>{o+=`<li>${n}</li>`;let a=document.querySelector(n);a&&!a.classList.contains("wao-optimized-element")&&(a.setAttribute("data-wao-role","sidebar"),a.setAttribute("style","border: 2px dashed #f39c12 !important; padding: 4px;"))}),o+="</ul>"),e.footer){o+=`<div><strong>Footer:</strong> ${e.footer}</div>`;let t=document.querySelector(e.footer);t&&!t.classList.contains("wao-optimized-element")&&(t.setAttribute("data-wao-role","footer"),t.setAttribute("style","border: 2px dashed #9b59b6 !important; padding: 4px;"))}i.innerHTML=o},x=e=>{if(!m())return;c.dataFlows||(c.dataFlows=[]),c.dataFlows.push(e);let i=document.querySelector(e.source),o=document.querySelector(e.destination);if(i&&o){let t=document.createElement("div");t.className="wao-data-flow",t.setAttribute("data-description",e.description??""),t.innerHTML=` <div><strong>From:</strong> ${e.source} (${e.dataType})</div> <div style="text-align: center;">\u2193</div> <div><strong>To:</strong> ${e.destination}</div> `,o.parentNode?.insertBefore(t,o.nextSibling)}},E=()=>{if(!m())return;let e={ariaLabels:{},tabOrder:[],colorContrast:{}};document.querySelectorAll('button, a, input, select, textarea, [role="button"], [tabindex]').forEach(a=>{let r=a,s=u(r),l=r.getAttribute("aria-label"),v=r.getAttribute("aria-labelledby");!l&&!v&&r.tagName!=="INPUT"&&(r.classList.add("wao-accessibility-issue"),e.colorContrast[s]="Missing ARIA label"),l&&(e.ariaLabels[s]=l),(r.tabIndex>=0||r.tagName==="A"||r.tagName==="BUTTON"||r.tagName==="INPUT"||r.tagName==="SELECT"||r.tagName==="TEXTAREA")&&e.tabOrder.push(s)}),c.accessibility=e;let o=document.querySelector(".wao-accessibility-report");o||(o=document.createElement("div"),o.className="wao-accessibility-report",o.setAttribute("style",` position: fixed; left: 20px; top: 20px; background: rgba(44, 62, 80, 0.9); color: white; padding: 15px; border-radius: 4px; font-family: monospace; z-index: 10000; max-width: 300px; max-height: 300px; overflow: auto; `),document.body.appendChild(o));let t="<h3>Accessibility Report</h3>";t+=`<div><strong>Tab Order (${e.tabOrder.length} elements):</strong></div><ol>`,e.tabOrder.slice(0,10).forEach(a=>{t+=`<li>${a}</li>`}),e.tabOrder.length>10&&(t+=`<li>... and ${e.tabOrder.length-10} more</li>`),t+="</ol>";let n=Object.keys(e.colorContrast).length;t+=`<div><strong>Issues (${n}):</strong></div>`,n>0&&(t+="<ul>",Object.entries(e.colorContrast).slice(0,5).forEach(([a,r])=>{t+=`<li>${a}: ${r}</li>`}),n>5&&(t+=`<li>... and ${n-5} more</li>`),t+="</ul>"),o.innerHTML=t},A=()=>{if(!m())return;let e={title:document.title,navigation:[],sidebar:[]},i=document.querySelector("main")||document.querySelector('[role="main"]')||document.querySelector("#main");i&&(e.mainContent=u(i)),document.querySelectorAll('nav, [role="navigation"], header ul, .nav, .navbar').forEach(r=>{Array.isArray(e.navigation)&&e.navigation.push(u(r))});let t=document.querySelector("footer")||document.querySelector(".footer")||document.querySelector("#footer");t&&(e.footer=u(t)),document.querySelectorAll('aside, .sidebar, [role="complementary"]').forEach(r=>{Array.isArray(e.sidebar)&&e.sidebar.push(u(r))}),y(e),document.querySelectorAll("h1, h2, h3, h4, h5, h6").forEach(r=>{let s=parseInt(r.tagName.charAt(1)),l=r.textContent||"",v=u(r);f(v,`Heading: ${l}`,r.tagName.toLowerCase(),{role:"heading-level-"+s,importance:s<=2?"primary":s<=4?"secondary":"tertiary"})})},C=(e,i)=>{if(!m())return;let o=document.querySelector(e);if(!o){d(`Element not found: ${e}`);return}let t=o.closest(".wao-optimized-element");if(t){let s=t.querySelector(".wao-role");s||(s=document.createElement("span"),s.className="wao-role",t.appendChild(s)),s.textContent=i;return}let n=document.createElement("div");n.className="wao-optimized-element",n.setAttribute("data-original-selector",e);let a=document.createElement("span");a.className="wao-role",a.textContent=i;let r=o.cloneNode(!0);n.appendChild(a),n.appendChild(r),o.parentNode?.replaceChild(n,o),c.optimizedElements.push({selector:e,description:`Element with role: ${i}`,originalHTML:o.outerHTML,role:i})},u=e=>{if(e.id)return`#${e.id}`;if(e.className&&typeof e.className=="string"){let t=e.className.trim().split(/\s+/);if(t.length>0){let n=`.${t.join(".")}`;if(document.querySelectorAll(n).length===1)return n}}let o=Array.from(document.querySelectorAll(e.tagName)).indexOf(e);return`${e.tagName.toLowerCase()}:nth-of-type(${o+1})`},O=()=>{L(),document.body.getAttribute("data-wao-active")==="true"&&g(document.body),window.WAO={activateOptimizer:g,deactivateOptimizer:b,describeElementVisually:f,defineInteraction:h,isActivated:m,describePage:y,describeDataFlow:x,analyzeAccessibility:E,extractSemanticStructure:A,highlightElementRole:C}};O();export{g as activateOptimizer,E as analyzeAccessibility,b as deactivateOptimizer,h as defineInteraction,x as describeDataFlow,f as describeElementVisually,y as describePage,A as extractSemanticStructure,C as highlightElementRole,m as isActivated}; //# sourceMappingURL=index.mjs.map