@stdbl/wao
Version:
Optimize web pages for LLM agent interaction and understanding
164 lines (150 loc) • 13.7 kB
JavaScript
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