@wcag-checkr/ci 1.0.0-rc.331 → 1.0.0-rc.332
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/offscreen-BAvM-6sh.js +1 -0
- package/dist/assets/service-worker.ts-B7jEQy1y.js +2 -0
- package/dist/manifest.json +2 -2
- package/dist/offscreen/offscreen.html +1 -1
- package/dist/service-worker-loader.js +1 -1
- package/package.json +1 -1
- package/dist/assets/offscreen-DzTrgQhD.js +0 -1
- package/dist/assets/service-worker.ts-CoPDhMzc.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import"./modulepreload-polyfill-B5Qt9EMX.js";import{_ as V}from"./preload-helper-D7HrI6pR.js";const X=new Set(["Document","Part","Art","Sect","Div","BlockQuote","Caption","TOC","TOCI","Index","NonStruct","Private","H","H1","H2","H3","H4","H5","H6","P","L","LI","Lbl","LBody","Table","TR","TH","TD","THead","TBody","TFoot","Span","Quote","Note","Reference","BibEntry","Code","Link","Annot","Ruby","RB","RT","RP","Warichu","WT","WP","Figure","Formula","Form"]);function Z(){const t=new Map;let r=0;return{ruleAggregates:t,figureAltCandidates:[],get lastHeading(){return r},set lastHeading(e){r=e},bumpRule(e,i){let o=t.get(e);o||(o={count:0,pages:new Set},t.set(e,o)),o.count++,o.pages.add(i)},setLastHeadingLevel(e){r=e},getLastHeading(){return r}}}function K(t,r,n){if(!t||typeof t!="object")return;const e=t.role;if(e&&!X.has(e)&&n.bumpRule("pdf-non-standard-role",r),e==="Figure"){const i=(t.alt??"").trim();i?n.figureAltCandidates.push({pageNum:r,alt:i}):n.bumpRule("pdf-figure-missing-alt",r)}if(e&&/^H[1-6]$/.test(e)){const i=parseInt(e.slice(1),10),o=n.getLastHeading();o>0&&i>o+1&&n.bumpRule("pdf-heading-skip",r),n.setLastHeadingLevel(i)}if(e==="Table"&&!Y(t,"TH")&&n.bumpRule("pdf-table-no-header",r),e==="L"){const i=t.children??[],o=i.some(s=>s&&s.role&&s.role!=="LI"&&s.role!=="Caption");(i.length===0||o)&&n.bumpRule("pdf-list-malformed",r)}for(const i of t.children??[])K(i,r,n)}function Y(t,r){if(!t)return!1;if(t.role===r)return!0;for(const n of t.children??[])if(Y(n,r))return!0;return!1}function ee(t){if(!t)return 0;const r=t.filter(e=>e.subtype==="Widget");let n=0;for(const e of r){const i=(e.alternativeText??"").trim(),o=(e.fieldName??"").trim(),s=/^(field|text\s*box|check\s*box|radio|button)\s*\d*$/i.test(o);!i&&(!o||s)&&n++}return n}function te(t,r){if(!t)return[];const n=[];for(const e of t){if(e.subtype!=="Widget")continue;const i=(e.alternativeText??"").trim();i&&n.push({pageNum:r,fieldType:(e.fieldType??"").trim()||"unknown",fieldName:(e.fieldName??"").trim(),tooltip:i})}return n}function re(t){const r=[],n={"pdf-figure-missing-alt":{ruleId:"pdf-figure-missing-alt",impact:"serious",wcagCriterion:"1.1.1",describe:e=>({description:`${e.count} Figure tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) have no alt text. Screen-reader users hear nothing for these images. PDF/UA-1 §7.4.`,failureSummary:"Open the PDF in Acrobat → Accessibility → Reading Order → click each Figure → Edit Alternate Text. Or, in source: add alt text to each image in Word/InDesign/PowerPoint before exporting."})},"pdf-heading-skip":{ruleId:"pdf-heading-skip",impact:"moderate",wcagCriterion:"1.3.1",describe:e=>({description:`Heading levels skip (e.g. H1 → H3 without H2). Detected ${e.count} skip${e.count===1?"":"s"} across ${e.pages.size} page${e.pages.size===1?"":"s"}. Screen-reader users hear the section hierarchy as broken.`,failureSummary:"Re-tag the headings sequentially. In Acrobat → Accessibility → Reading Order, change the offending tag to the correct heading level. In source documents use Heading 1 → Heading 2 → Heading 3 styles consistently."})},"pdf-table-no-header":{ruleId:"pdf-table-no-header",impact:"serious",wcagCriterion:"1.3.1",describe:e=>({description:`${e.count} Table tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) have no TH (header) cells. Screen-reader table-navigation mode cannot announce headers when reading cells.`,failureSummary:"Open the PDF in Acrobat → Accessibility → Reading Order → select the table → Table Editor. Mark the first row (or first column) as headers. In source documents (Word: Table Tools → Layout → Repeat Header Rows; PowerPoint: tables need to be tagged as data tables)."})},"pdf-list-malformed":{ruleId:"pdf-list-malformed",impact:"moderate",wcagCriterion:"1.3.1",describe:e=>({description:`${e.count} List tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) are malformed — L tags should contain LI children with optional Lbl + LBody. PDF/UA-1 §7.8.`,failureSummary:'Re-tag the lists in Acrobat → Accessibility → Reading Order, or recreate the PDF from a source document that produces proper list tagging (bullet/numbered lists in Word/Pages/Google Docs export correctly when "tagged PDF" is enabled).'})},"pdf-non-standard-role":{ruleId:"pdf-non-standard-role",impact:"minor",wcagCriterion:"1.3.1",describe:e=>{const i=Array.from(e.pages).slice(0,3).join(", ");return{description:`${e.count} structure-tree node${e.count===1?"":"s"} use non-standard tag roles (sample pages: ${i}). PDF/UA-1 §7.3 requires a RoleMap entry in StructTreeRoot mapping each custom role to a standard one.`,failureSummary:"Either replace the non-standard tags with PDF/UA standard ones (Document/Part/Art/Sect/Div/H1-H6/P/L/LI/Table/TR/TH/TD/Figure/Form/etc.), or add RoleMap entries in StructTreeRoot mapping each custom name to a standard equivalent."}}},"pdf-untagged-content":{ruleId:"pdf-untagged-content",impact:"critical",wcagCriterion:"1.3.1",describe:e=>({description:`${e.pages.size} page${e.pages.size===1?"":"s"} have no structure tree (untagged content). Screen-reader users get no reading order on these pages — content may be read in random visual-position order or skipped entirely.`,failureSummary:"Re-tag the document end-to-end. In Acrobat → Accessibility → Autotag Document is a starting point but rarely produces good results — re-export from the source document with tagging enabled, then refine in Acrobat's Reading Order tool."})}};for(const[e,i]of t.ruleAggregates){const o=n[e];if(!o)continue;const{description:s,failureSummary:p}=o.describe(i);r.push({ruleId:o.ruleId,impact:o.impact,wcagCriterion:o.wcagCriterion,description:s,failureSummary:p})}return r}function ne(t,r){return t===0?null:{ruleId:"pdf-field-no-name",impact:"serious",wcagCriterion:"4.1.2",description:`${t} form field${t===1?"":"s"} across ${r} page${r===1?"":"s"} have no accessible name (no /TU alternate text + no descriptive /T field name). Screen-reader users hear nothing or hear the field type generically ("text field", "check box").`,failureSummary:'In Acrobat: open the Tools → Prepare Form panel → right-click each field → Properties → General tab → fill in the "Tooltip" (this becomes the PDF /TU). Or rename the /T field name to something descriptive ("First name", "Total amount due"). PDF/UA-1 §7.15.'}}function oe(t,r,n){return r===0||n||t>0?null:{ruleId:"pdf-image-only",impact:"critical",wcagCriterion:"1.1.1",description:`PDF has no extractable text on any of its ${r} page${r===1?"":"s"} — appears to be a scanned document with no OCR layer. Screen-reader users hear silence; keyboard search returns no hits; copy/paste yields nothing.`,failureSummary:'Run OCR on the PDF before distributing it. Acrobat Pro → Tools → Scan & OCR → "Recognize Text". Free options: ocrmypdf (CLI), Google Drive (upload → open as Google Doc), or Tesseract. After OCR, re-tag the document (Acrobat → Accessibility → Autotag Document, then refine in Reading Order) so the recognized text gets a proper structure tree.'}}function ie(t,r,n){if(r===0)return null;const e=n!=null&&isFinite(n)?n.toFixed(2):"?";return{ruleId:"pdf-text-low-contrast",impact:"serious",wcagCriterion:"1.4.3",description:`${r} text run${r===1?"":"s"} across ${t} page${t===1?"":"s"} fall below the WCAG 1.4.3 AA contrast threshold (4.5:1 for normal text, 3:1 for large text). Worst observed ratio: ${e}:1. Low-vision readers cannot reliably read this text against its background.`,failureSummary:"Rebuild the source document with stronger contrast — typically darken the text or lighten the background. For brand color palettes, use a contrast checker (https://webaim.org/resources/contrastchecker/) to pick a compliant pair. Re-export the PDF with the new colors. Note: this check samples rendered pixels, so even if the source uses semantic colors, what the reader sees IS the verdict."}}function se(t,r){return t===0?null:{ruleId:"pdf-reading-order-mismatch",impact:"serious",wcagCriterion:"1.3.2",description:`${t} place${t===1?"":"s"} across ${r} page${r===1?"":"s"} where the content-stream reading order jumps backward (significant upward y-motion). Screen-reader users will hear the text in an order that doesn't match the visual layout. PDF/UA-1 §7.10 / WCAG 1.3.2.`,failureSummary:'Most common cause: multi-column layouts that were drawn column-by-column in the source document instead of being tagged with a proper reading order. Fix in Acrobat: Tools → Accessibility → Reading Order → "Show Order Panel" → drag the order entries into the correct sequence. In source documents (Word, InDesign), use proper linked text frames / column flow so the export-to-PDF preserves a top-down read.'}}function ae(t,r){return t<=5||r?null:{ruleId:"pdf-no-bookmarks",impact:"moderate",wcagCriterion:"2.4.5",description:`Multi-page PDF (${t} pages) has no bookmarks / outline. Keyboard and AT users cannot navigate the document structure without scrolling page-by-page.`,failureSummary:'Add bookmarks to the PDF in Acrobat (View → Show/Hide → Navigation Panes → Bookmarks, then add entries for each section heading). Or re-export from the source document with "Generate bookmarks" enabled (Word: Save As PDF → Options → Create bookmarks using: Headings).'}}function J({r:t,g:r,b:n}){const e=i=>{const o=i/255;return o<=.03928?o/12.92:Math.pow((o+.055)/1.055,2.4)};return .2126*e(t)+.7152*e(r)+.0722*e(n)}function ce(t,r){const n=J(t),e=J(r),i=Math.max(n,e),o=Math.min(n,e);return(i+.05)/(o+.05)}function le(t,r){return!isFinite(t)||t<=0?!1:!!(r&&t>=14*1.333||t>=18*1.333)}function de(t){return t?3:4.5}let U=null;function ue(){return U||(U=(async()=>{try{const t=(await V(async()=>{const{default:n}=await import("./pdf.worker-B4IDxXWI.js");return{default:n}},[])).default,r=await V(()=>import("./pdf-DfaD4CCm.js"),[]);return r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.workerSrc=t),r}catch(t){return{error:t instanceof Error?t.message:String(t)}}})()),U}async function fe(t,r){let n;try{n=await fetch(t)}catch(o){return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`Network error fetching PDF: ${o instanceof Error?o.message:String(o)}`}}if(!n.ok)return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`Fetch failed with HTTP ${n.status}`};const e=n.headers.get("content-length");if(e&&parseInt(e,10)>r)return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`PDF exceeds size cap (${e} bytes > ${r}). Skipped — audit it manually via the CLI: \`wcagcheckr-ci pdf ${t}\`.`};const i=await n.arrayBuffer();return i.byteLength>r?{ok:!1,source:t,findings:[],pageCount:null,fatalError:`PDF exceeds size cap (${i.byteLength} bytes > ${r}). Skipped.`}:pe(new Uint8Array(i),t)}async function ge(t,r){const n={failingRuns:0,worstRatio:null,textItems:0,itemsSkippedTooSmall:0,itemsSkippedOutOfBounds:0,itemsSkippedBgOnly:0,itemsSampled:0,bestObservedRatio:null},e=r.OPS;if(!e)return n;let i;try{i=await t.getOperatorList()}catch(m){return n.renderError=`getOperatorList threw: ${m instanceof Error?m.message:String(m)}`,n}let o={r:0,g:0,b:0},s=12,p=!1;const F=[],S={r:255,g:255,b:255},$=.2126*S.r+.7152*S.g+.0722*S.b,A=i.fnArray,x=i.argsArray,v=A.length;for(let m=0;m<v;m++){const b=A[m],k=x[m]??[];if(b===e.save)F.push({fillColor:{...o},fontSize:s,fontIsBold:p});else if(b===e.restore){const l=F.pop();l&&(o=l.fillColor,s=l.fontSize,p=l.fontIsBold)}else if(b===e.setFillRGBColor){const l=Number(k[0])|0,h=Number(k[1])|0,R=Number(k[2])|0;isFinite(l)&&isFinite(h)&&isFinite(R)&&(o={r:l,g:h,b:R})}else if(b===e.setFillGray){const l=Number(k[0]);if(isFinite(l)){const h=Math.max(0,Math.min(255,Math.round(l*255)));o={r:h,g:h,b:h}}}else if(b===e.setFont){const l=Number(k[1]);isFinite(l)&&l>0&&(s=l);const h=String(k[0]??"");p=/-?(Bold|Black|Heavy)/i.test(h)}else if(b===e.showText||b===e.showSpacedText||b===e.nextLineShowText||b===e.nextLineSetSpacingShowText){n.textItems++;const l=.2126*o.r+.7152*o.g+.0722*o.b;if(Math.abs(l-$)<1){n.itemsSkippedBgOnly++;continue}n.itemsSampled++;const h=le(s,p),R=de(h),y=ce(o,S);(n.bestObservedRatio===null||y>n.bestObservedRatio)&&(n.bestObservedRatio=y),y<R&&(n.failingRuns++,(n.worstRatio===null||y<n.worstRatio)&&(n.worstRatio=y))}}return n}async function pe(t,r){var q,Q;const n=await ue();if("error"in n)return{ok:!1,source:r,findings:[],pageCount:null,fatalError:`pdfjs failed to load in offscreen document: ${n.error}`};const e=n;let i;try{i=await e.getDocument({data:t,verbosity:0,disableFontFace:!0,useSystemFonts:!1}).promise}catch(u){return{ok:!0,source:r,findings:[{ruleId:"pdf-structure-tree-unparseable",impact:"serious",wcagCriterion:"1.3.1",description:`pdfjs could not open the PDF: ${u instanceof Error?u.message:String(u)}. Usually means encrypted, malformed, or non-standard structure.`,failureSummary:"Try opening the PDF in a recent Acrobat Reader — if it opens there but fails the extension audit, the PDF uses uncommon encoding pdfjs cannot handle. If it fails everywhere the source document needs to be regenerated."}],pageCount:null}}const o=i.numPages;let s=!1;try{const u=await i.getOutline();s=Array.isArray(u)&&u.length>0}catch{}const p=Z();let F=0,S=0,$=0,A=0,x=0,v=0,m=null;const b=[];let k=0,l=0;const h=[],R=[];for(let u=1;u<=o;u++){let P;try{P=await i.getPage(u)}catch{continue}let I=null;try{I=await P.getStructTree()}catch{}I?K(I,u,p):p.bumpRule("pdf-untagged-content",u);try{const a=await P.getAnnotations();if((a??[]).filter(d=>d.subtype==="Widget").length>0){S++,F+=ee(a);for(const d of te(a,u))R.push(d)}}catch{}let c=null,E;try{c=await P.getTextContent();const a=(c==null?void 0:c.items)??[];let f=0;for(const d of a)f+=((d==null?void 0:d.str)??"").length;$+=f}catch(a){A++,E=a instanceof Error?a.message:String(a)}if(c!=null&&c.items&&c.items.length>0){const a=[];for(const f of c.items){const d=f.transform;if(!d||d.length<6)continue;const C=Math.abs(d[3]??0);C>0&&(f.str??"").trim()&&a.push(C)}if(a.length>=2){const f=new Map;for(const g of a){const w=Math.round(g*2)/2;f.set(w,(f.get(w)??0)+1)}let d=1/0,C=-1;for(const[g,w]of f)(w>C||w===C&&g<d)&&(C=w,d=g);const T=d*1.2;for(let g=0;g<c.items.length;g++){const w=c.items[g],D=w.transform;if(!D||D.length<6)continue;const H=Math.abs(D[3]??0),_=(w.str??"").trim();if(!_||H<T||_.length>200)continue;let O="";for(let L=g+1;L<c.items.length&&O.length<800;L++){const M=(((q=c.items[L])==null?void 0:q.str)??"").trim();if(!M)continue;const B=(Q=c.items[L])==null?void 0:Q.transform;if(B&&B.length>=6&&Math.abs(B[3]??0)>=T&&M.length<200)break;O+=(O?" ":"")+M}O.length!==0&&h.push({pageNum:u,headingText:_,sectionContent:O.slice(0,800)})}}}if(c!=null&&c.items&&c.items.length>=2){let a=0;for(let f=1;f<c.items.length;f++){const d=c.items[f-1],C=c.items[f],T=d.transform,g=C.transform;if(!T||T.length<6||!g||g.length<6||!(C.str??"").trim()||!(d.str??"").trim())continue;const w=T[5],D=g[5],H=Math.abs(g[3])||12;D-w>2*H&&a++}a>0&&(k+=a,l++)}try{const a=await ge(P,e);b.push({page:u,...a,...E?{textContentError:E}:{}}),a.failingRuns>0&&(x+=a.failingRuns,v++,a.worstRatio!==null&&(m===null||a.worstRatio<m)&&(m=a.worstRatio))}catch{}}const y=re(p),N=ne(F,S);N&&y.push(N);const W=ae(o,s);W&&y.push(W);const z=oe($,o,A===o);z&&y.push(z);const G=ie(v,x,m);G&&y.push(G);const j=se(k,l);return j&&y.push(j),{ok:!0,source:r,findings:y,pageCount:o,perPageContrast:b,aiCandidates:{figureAltTexts:p.figureAltCandidates,headings:h,formLabels:R}}}chrome.runtime.onMessage.addListener((t,r,n)=>{const e=t;if(!e||e.type!=="OFFSCREEN_PDF_AUDIT_REQUEST")return!1;const i=typeof e.url=="string"?e.url:"",o=typeof e.maxBytes=="number"?e.maxBytes:16*1024*1024;return(async()=>{let s;try{s=await fe(i,o)}catch(F){s={ok:!1,source:i,findings:[],pageCount:null,fatalError:`Offscreen audit threw: ${F instanceof Error?F.message:String(F)}`}}const p={type:"OFFSCREEN_PDF_AUDIT_RESPONSE",ok:s.ok,source:s.source,findings:s.findings,pageCount:s.pageCount,...s.fatalError?{fatalError:s.fatalError}:{},...s.perPageContrast?{_perPageContrast:s.perPageContrast}:{},...s.aiCandidates?{aiCandidates:s.aiCandidates}:{}};n(p)})(),!0});
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ai-usage-log-D5enikfX.js","assets/crash-reporter-Bu2p8K-p.js","assets/scheduled-audit-runner-QcMYcqgA.js","assets/preload-helper-D7HrI6pR.js","assets/diff-DIBMr3fQ.js"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{_ as G}from"./preload-helper-D7HrI6pR.js";import{ag as ne,ah as X,ai as N,aj as L,g as oe,C as se,ak as ie,al as ce,am as le,an as de,ao as ue,ap as fe,aq as ge,ar as pe,as as he,at as Ee,au as me,av as Te,aw as Se,ax as we,ay as ye,aa as Re,az as Ae,aA as Ie,aB as Ce,aC as _e,aD as be,aE as Pe,q as P,aF as k,aG as ve,aH as Ue,aI as Y,aJ as ke,aK as Oe}from"./scheduled-audit-runner-QcMYcqgA.js";import{v as A,T as H,w as _,j as xe}from"./ai-usage-log-D5enikfX.js";import{c as m,o as g,f as Ne,g as Le,i as De,h as $e,d as z,e as Fe}from"./crash-reporter-Bu2p8K-p.js";import{m as V}from"./diff-DIBMr3fQ.js";const x="tierConfig:cache",Me=60*60*1e3,Ge=24*60*60*1e3,He=7*24*60*60*1e3;async function Ve(){return(await chrome.storage.local.get(x))[x]??null}async function We(e){await chrome.storage.local.set({[x]:e})}function je(e,t=Date.now()){const r=t-e.fetchedAt;return r<Me?"fresh":r<Ge?"stale":r<He?"grace":"expired"}function Be(e,t){const r={...e},a=p=>{if(typeof p=="number")return p===-1?1/0:p},n=p=>typeof p=="boolean"?p:void 0,s=p=>{if(p==="all"||p==="configurable"||p==="default-only")return p},i=a(t.maxComponents);i!==void 0&&(r.maxComponents=i);const c=a(t.maxBaselines);c!==void 0&&(r.maxBaselines=c);const d=s(t.stateMatrix);d!==void 0&&(r.stateMatrix=d);const l=n(t.storybookAutoIterate);l!==void 0&&(r.storybookAutoIterate=l);const o=n(t.exportJson);o!==void 0&&(r.exportJson=o);const u=n(t.exportSarif);u!==void 0&&(r.exportSarif=u);const h=n(t.exportJunit);h!==void 0&&(r.exportJunit=h);const v=n(t.cloudSync);v!==void 0&&(r.cloudSync=v);const E=n(t.forensicAnchoring);E!==void 0&&(r.forensicAnchoring=E);const S=n(t.autoExportAuditReports);S!==void 0&&(r.autoExportAuditReports=S);const w=n(t.pdfAudit);return w!==void 0&&(r.pdfAudit=w),r}function Ke(e,t){var a;if(e==="trial")return((a=t.trial)==null?void 0:a.features)??null;const r=t.plans.find(n=>n.code===e||n.code.startsWith(e+"-"));return(r==null?void 0:r.features)??null}const I=m("tier-config-client"),Qe="wcagcheckr",qe=`https://api.wcagcheckr.com/v1/products/${Qe}/tier-config`,Xe=1e4,W="tier-config-refresh",Ye=60,ze=["trial","free","solo","team"];function J(e){const t={};for(const r of ze){const a=Ke(r,e);t[r]=a?Be(H[r],a):{...H[r]}}return t}async function Je(){const e=await Ve();if(!e){A(null);return}if(je(e)==="expired"){I.warn("cached tier-config is expired (>7d); using hardcoded defaults"),A(null);return}A(J(e.config))}async function Z(){try{const e=await fetch(qe,{signal:AbortSignal.timeout(Xe),headers:{accept:"application/json"}});if(!e.ok)throw new Error(`http ${e.status}`);const t=await e.json();await We({fetchedAt:Date.now(),config:t}),A(J(t));const r=t.wcagTargetVersion;if(r==="2.1"||r==="2.2")try{await chrome.storage.local.set({wcagTargetVersion:r}),ne(r)}catch(a){I.warn("failed to persist wcagTargetVersion",a)}I.info("tier-config refreshed from server")}catch(e){I.warn("tier-config refresh failed; keeping prior cache",e)}}function Ze(){chrome.alarms.create(W,{periodInMinutes:Ye}),chrome.alarms.onAlarm.addListener(e=>{e.name===W&&Z()})}const et=m("support-messenger"),tt="https://api.wcagcheckr.com/v1/products/wcagcheckr/support",O="support:rate-window",rt=5,at=10*60*1e3,nt=2,ot="wcagcheckr",j="storybook:lastDetected";async function st(e){if(!e)return;const t=await chrome.runtime.getPlatformInfo(),a=(await chrome.storage.local.get(j))[j];return{extensionVersion:chrome.runtime.getManifest().version,platform:t,storybookDetected:a!=null&&a.detected?a.version??"detected":"none",licenseTier:await X(),logTail:Ne(Le())}}async function it(e=Date.now()){const r=((await chrome.storage.local.get(O))[O]??[]).filter(a=>e-a<at);return r.length>=rt?!1:(r.push(e),await chrome.storage.local.set({[O]:r}),!0)}async function ee(e,t=0){try{const r=await fetch(tt,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();if(!a.success)throw new Error(a.error??"server returned success=false");return{ticketRef:a.ticketRef??""}}catch(r){if(t<nt){const a=(t+1)*1e3;return await new Promise(n=>setTimeout(n,a)),ee(e,t+1)}throw r}}function ct(){return g("SUPPORT_MESSAGE_REQUEST",async e=>{if(!await it())return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:V("NETWORK","Rate limit reached. Try again in 10 minutes.",!0)};try{const t=await st(e.includeContext);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!0,ticketRef:(await ee({productSlug:ot,subject:e.subject,body:e.body,replyEmail:e.replyEmail,context:t,extensionVersion:chrome.runtime.getManifest().version,timestamp:new Date().toISOString()})).ticketRef}}catch(t){et.error("send failed",t);const r=t instanceof Error?t.message:String(t);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:V("NETWORK",r,!0)}}})}const te=m("ai-color-suggester");async function lt(e,t,r=[]){if(!t.enabled||e.length===0)return{results:[],totalCostUsd:0,capExceeded:!1};const a=N(t);if(!a.ok)return{results:[],totalCostUsd:0,capExceeded:!1};const n=a.client,s=L(t.costCapUsd),i=[];for(const c of e){if(!s.canCharge())break;try{const d=await n.suggestColorFix({foreground:c.foreground,background:c.background,fontSize:c.fontSize,fontWeight:c.fontWeight,targetLevel:c.targetLevel,paletteHints:r});s.recordCharge(d.costUsd),d.verdict==="suggested"&&d.candidates.length>0&&i.push({matchKey:c.matchKey,suggestions:d.candidates,reasoning:d.reasoning,costUsd:d.costUsd})}catch(d){te.warn(`color-fix suggestion failed for ${c.matchKey}`,d)}}return{results:i,totalCostUsd:s.state.spentUsd,capExceeded:s.state.exceeded}}async function dt(){const e=await chrome.storage.local.get("aiConfig");return _(e.aiConfig)}function ut(){return g("AI_COLOR_SUGGEST_REQUEST",async e=>{const t=await dt();if(!t.enabled)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!t.apiKey)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{results:r,totalCostUsd:a,capExceeded:n}=await lt(e.inputs,t,e.paletteHints);return{type:"AI_COLOR_SUGGEST_RESPONSE",results:r,totalCostUsd:a,capExceeded:n}}catch(r){return te.warn("color-suggest handler failed",r),{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:r instanceof Error?r.message:String(r)}}})}function B(e){if(!e)return null;const t=e.match(/rgba?\(\s*([0-9.]+)\s*,?\s*([0-9.]+)\s*,?\s*([0-9.]+)(?:\s*[,/]\s*([0-9.]+))?\s*\)/i);return t?{r:Math.round(parseFloat(t[1])),g:Math.round(parseFloat(t[2])),b:Math.round(parseFloat(t[3])),a:t[4]!==void 0?parseFloat(t[4]):1}:null}function K(e){const t=r=>{const a=r/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)};return .2126*t(e.r)+.7152*t(e.g)+.0722*t(e.b)}function ft(e,t){const r=K(e),a=K(t),n=Math.max(r,a),s=Math.min(r,a);return(n+.05)/(s+.05)}function gt(e,t){const r=Math.max(0,Math.min(1,e.a));return{r:Math.round(e.r*r+t.r*(1-r)),g:Math.round(e.g*r+t.g*(1-r)),b:Math.round(e.b*r+t.b*(1-r))}}function pt(e,t){var M;if(e!=="color-contrast"&&e!=="color-contrast-enhanced")return null;const r=t.styles;if(!r)return null;const a=((M=r.effectiveBackground)==null?void 0:M.color)??r.background,n=r.foreground;if(!n||!a)return null;const s=B(n),i=B(a);if(!s||!i||i.a<.999)return null;const c=s.a<.999?gt(s,i):{r:s.r,g:s.g,b:s.b},d=ft(c,i),l=r.fontSize??16,o=r.fontWeight??400,u=l>=24||l>=18.5&&o>=700,E=e==="color-contrast-enhanced"?u?4.5:7:u?3:4.5,S=d>=E?"pass":"fail",w=U=>`rgb(${U.r}, ${U.g}, ${U.b})`,p=`Deterministic WCAG contrast measurement (no AI guessing, no pixel sampling). Foreground ${w(c)}${s.a<.999?` (originally rgba with alpha=${s.a}, composited over background)`:""} against background ${w(i)} yields contrast ratio ${d.toFixed(2)}:1. Text is ${l}px at font-weight ${o}; ${u?"qualifies as large text (threshold 3:1 for AA)":"normal text (threshold 4.5:1 for AA)"}. ${S==="pass"?`Passes AA at ${E}:1.`:`Falls below the ${E}:1 threshold.`}`;return{verdict:S,ratio:d,threshold:E,reasoning:p}}async function ht(e,t,r){var c,d,l,o,u;const a=JSON.stringify({ruleId:e,selector:t,styles:{fg:((c=r.styles)==null?void 0:c.foreground)??null,bg:((d=r.styles)==null?void 0:d.background)??null,fs:((l=r.styles)==null?void 0:l.fontSize)??null,fw:((o=r.styles)==null?void 0:o.fontWeight)??null,ts:((u=r.styles)==null?void 0:u.textSample)??null},failureSummary:r.failureSummary??null}),n=new TextEncoder().encode(a),s=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(s)).map(h=>h.toString(16).padStart(2,"0")).join("")}const C=m("ai-incomplete-resolver");function Q(e,t){if(!e)return t;const r=e.toLowerCase(),a=/verdict\s+corrected\s+to\s+pass|verdict:\s*pass\s+\(corrected\)/i,n=/verdict\s+corrected\s+to\s+fail|verdict:\s*fail\s+\(corrected\)/i,s=y(r,a),i=y(r,n);if(s>i&&s>=0)return"pass";if(i>s&&i>=0)return"fail";const c=/actually\s+passes|in\s+fact\s+passes|passes\s+AA/gi,d=/actually\s+fails|in\s+fact\s+fails|fails\s+AA/gi,l=y(r,c),o=y(r,d);return l<0&&o<0?t:l>o&&l/r.length>=.5?"pass":o>l&&o/r.length>=.5?"fail":t}function y(e,t){let r=-1;const a=t.flags.includes("g")?t.flags:t.flags+"g",n=new RegExp(t.source,a);let s;for(;(s=n.exec(e))!==null;)r=s.index,s.index===n.lastIndex&&n.lastIndex++;return r}async function Et(){const e=await chrome.storage.local.get("aiConfig");return _(e.aiConfig)}async function mt(e){if(!e.aiConfig.enabled||e.elements.length===0)return{resolutions:[],totalCostUsd:0};const t=N(e.aiConfig);if(!t.ok)return{resolutions:[],totalCostUsd:0};const r=t.client,a=L(e.aiConfig.costCapUsd),n=[],s=await oe(e.pageUrl),i=new Map;for(const c of s)i.set(`${c.ruleId}::${c.selector}`,c);for(const c of e.elements){if(!a.canCharge())break;const d=await ht(e.ruleId,c.selector,c),l=i.get(`${e.ruleId}::${c.selector}`),o=pt(e.ruleId,c);if(o){C.info(`Deterministic verdict for ${e.ruleId} on ${c.selector}: ${o.verdict} (${o.ratio.toFixed(2)}:1 vs ${o.threshold}:1) — math overrides cache + AI`),n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:c.selector,verdict:o.verdict,reasoning:o.reasoning,resolvedAt:new Date().toISOString(),costUsd:0,wcagCriterion:e.wcagCriterion,inputHash:d});continue}if(l&&l.inputHash===d&&l.verdict!=="uncertain"){C.info(`Reusing cached resolution for ${e.ruleId} on ${c.selector} (hash match, verdict=${l.verdict})`);const u=Q(l.reasoning,l.verdict);n.push({...l,verdict:u,resolvedAt:new Date().toISOString(),costUsd:0,inputHash:d});continue}try{const u=await r.resolveAxeIncomplete({ruleId:e.ruleId,element:c,pageUrl:e.pageUrl,targetLevel:e.targetLevel});a.recordCharge(u.costUsd);const h=Q(u.reasoning,u.verdict);n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:c.selector,verdict:h,reasoning:u.reasoning,resolvedAt:new Date().toISOString(),costUsd:u.costUsd,wcagCriterion:e.wcagCriterion,inputHash:d})}catch(u){C.warn(`resolveAxeIncomplete failed for ${c.selector}`,u)}}return n.length>0&&await se(n),{resolutions:n,totalCostUsd:a.state.spentUsd}}function Tt(){return g("AI_RESOLVE_INCOMPLETE_REQUEST",async e=>{const t=await Et();if(!t.enabled)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!t.apiKey)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{resolutions:r,totalCostUsd:a}=await mt({ruleId:e.ruleId,pageUrl:e.pageUrl,wcagCriterion:e.wcagCriterion,elements:e.elements,targetLevel:e.targetLevel,aiConfig:t});return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:r,totalCostUsd:a}}catch(r){return C.warn("ai-incomplete-resolver failed",r),{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:r instanceof Error?r.message:"Unknown error during AI resolution."}}})}function St(){return g("INTERACTIVE_AUDIT_REQUEST",async e=>{try{switch(e.criterionId){case"2.4.3":{const t=await fe({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.1.2":{const t=await ue({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.4.7":{const t=await de({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"1.4.11":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first; 1.4.11 needs the page screenshot."};const n=await le({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"1.3.2":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first, then the 1.3.2 walkthrough can judge its reading-order findings."};const n=await ce({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"2.5.3":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=await ie({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl,results:r==null?void 0:r.results});return a.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:a.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:a.error}}default:return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:`Interactive audit for criterion ${e.criterionId} not yet implemented.`}}}catch(t){return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}})}async function wt(){var t;if(typeof chrome>"u"||!((t=chrome.storage)!=null&&t.local))return _(void 0);const e=await chrome.storage.local.get("aiConfig");return _(e.aiConfig)}async function yt(e){const t=await wt();if(!t.enabled||!t.apiKey)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[]};const r=N(t);if(!r.ok)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[`AI client unavailable: ${r.reason}`]};const a=r.client,n=L(t.costCapUsd),s=[],i=[],c=Math.max(1,t.maxCandidatesPerCheck??10);if(t.enabledChecks.altText){const d=e.figureAltTexts.slice(0,c);for(const l of d){if(!n.canCharge())break;try{const o=await a.judgeGenericLinkText({linkText:l.alt,surroundingText:`(This is an alt text on a PDF Figure tag, page ${l.pageNum}.)`});n.recordCharge(o.costUsd),o.verdict==="fail"&&o.confidence>=.6&&s.push({ruleId:"pdf-alt-text-not-descriptive",impact:"moderate",wcagCriterion:"1.1.1",description:`Figure on page ${l.pageNum} has alt text "${l.alt}" that doesn't describe the figure's content. ${o.reasoning} A screen-reader user hears the literal alt and gets no useful information about what the figure shows.`,failureSummary:'Replace generic alt text with a description of what the figure actually shows. For data charts: include the key data point. For decorative images: use alt="" so the screen reader skips them. PDF/UA-1 §7.4 / WCAG 1.1.1.'})}catch(o){i.push(`alt-text page ${l.pageNum}: ${o instanceof Error?o.message:String(o)}`)}}}else i.push("altText AI check disabled in user settings");if(t.enabledChecks.altText&&e.formLabels&&e.formLabels.length>0){const d=o=>{switch(o){case"Tx":return"text input";case"Btn":return"button / checkbox / radio";case"Ch":return"choice / dropdown";case"Sig":return"signature field";default:return o||"unknown"}},l=e.formLabels.slice(0,c);for(const o of l){if(!n.canCharge())break;try{const u=await a.judgeGenericLinkText({linkText:o.tooltip,surroundingText:`(This is the screen-reader tooltip for a PDF form field on page ${o.pageNum}. Field type: ${d(o.fieldType)}. Internal field name: "${o.fieldName||"(none)"}".)`});n.recordCharge(u.costUsd),u.verdict==="fail"&&u.confidence>=.6&&s.push({ruleId:"pdf-form-label-not-descriptive",impact:"serious",wcagCriterion:"3.3.2",description:`Form field on page ${o.pageNum} (${d(o.fieldType)}) has tooltip "${o.tooltip}" that doesn't convey what the user should enter. ${u.reasoning} Screen-reader users hear the tooltip as the field's accessible name; generic tooltips fail to identify the field's purpose.`,failureSummary:'Replace the generic tooltip with one that names what the field is for. "Field 1" → "Mailing address." "Text input" → "Email address." In Acrobat: Tools → Prepare Form → right-click field → Properties → General → Tooltip. WCAG 3.3.2 (Labels or Instructions) requires labels that describe purpose, not just type.'})}catch(u){i.push(`form-label page ${o.pageNum}: ${u instanceof Error?u.message:String(u)}`)}}}if(t.enabledChecks.headings&&e.headings&&e.headings.length>0){const d=e.headings.slice(0,c);for(const l of d){if(!n.canCharge())break;try{const o=await a.judgeHeading({headingText:l.headingText,sectionContent:l.sectionContent});n.recordCharge(o.costUsd),o.verdict==="fail"&&o.confidence>=.6&&s.push({ruleId:"pdf-heading-not-descriptive",impact:"moderate",wcagCriterion:"2.4.6",description:`Heading on page ${l.pageNum} "${l.headingText}" doesn't describe the content of its section. ${o.reasoning} Screen-reader users navigating by heading hear titles that don't help them locate the section they want.`,failureSummary:`Rewrite the heading to describe what the section is about. "Section 1" → "Q3 financial summary." "More info" → "How to apply for benefits." Generic, recycled, or placeholder heading text wastes the SR user's heading-navigation feature.`})}catch(o){i.push(`heading page ${l.pageNum}: ${o instanceof Error?o.message:String(o)}`)}}}return{findings:s,totalCostUsd:n.state.spentUsd,capExceeded:n.state.exceeded,errors:i}}function Rt(e){return g("PDF_AUDIT_REQUEST",async t=>{const r=await e();if(!xe(r,"pdfAudit"))return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF accessibility audit is not enabled on the ${r} tier. Upgrade or contact your admin to enable the pdfAudit feature.`};try{const a=await ge(t.url,{maxBytes:t.maxBytes});let n=[];if(a.aiCandidates)try{n=(await yt(a.aiCandidates)).findings}catch{}return{type:"PDF_AUDIT_RESPONSE",ok:a.ok,source:a.source,findings:[...a.findings,...n],pageCount:a.pageCount,...a.fatalError?{fatalError:a.fatalError}:{},...a._perPageContrast?{_perPageContrast:a._perPageContrast}:{},...a.aiCandidates?{aiCandidates:a.aiCandidates}:{}}}catch(a){return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF audit handler threw: ${a instanceof Error?a.message:String(a)}`}}})}const At=m("ax-tree-snapshot"),It="1.3";function Ct(e){var r,a,n;const t=[];for(const s of e.properties??[]){const i=(r=s.value)==null?void 0:r.value;i!==void 0&&(typeof i=="string"||typeof i=="number"||typeof i=="boolean"||i===null)&&t.push({name:s.name,value:i})}return{nodeId:e.nodeId,parentId:e.parentId,childIds:e.childIds??[],role:typeof((a=e.role)==null?void 0:a.value)=="string"?e.role.value:"unknown",name:typeof((n=e.name)==null?void 0:n.value)=="string"?e.name.value:"",ignored:!!e.ignored,properties:t,backendDomNodeId:e.backendDOMNodeId}}async function _t(e){let t=!1;try{try{await chrome.debugger.attach({tabId:e},It),t=!0}catch(n){if(!(n instanceof Error?n.message:String(n)).includes("Another debugger"))throw At.warn("chrome.debugger.attach failed",n),n}await chrome.debugger.sendCommand({tabId:e},"Accessibility.enable");const r=await chrome.debugger.sendCommand({tabId:e},"Accessibility.getFullAXTree");return((r==null?void 0:r.nodes)??[]).map(Ct)}finally{if(t)try{await chrome.debugger.detach({tabId:e})}catch{}}}const re=m("perf-throttle"),bt="1.3",Pt={none:{label:"No throttling",network:null,cpuRate:1},"3g-slow":{label:"Slow 3G",network:{offline:!1,latency:400,downloadThroughput:500*1024/8,uploadThroughput:500*1024/8},cpuRate:6},"3g-fast":{label:"Fast 3G",network:{offline:!1,latency:150,downloadThroughput:1.5*1024*1024/8,uploadThroughput:750*1024/8},cpuRate:4},"4g":{label:"4G LTE",network:{offline:!1,latency:20,downloadThroughput:4*1024*1024/8,uploadThroughput:3*1024*1024/8},cpuRate:2},"cpu-2x":{label:"CPU 2× slowdown (no network throttle)",network:null,cpuRate:2},"cpu-4x":{label:"CPU 4× slowdown (no network throttle)",network:null,cpuRate:4}};async function vt(e){try{return await chrome.debugger.attach({tabId:e},bt),!0}catch(t){if((t instanceof Error?t.message:String(t)).includes("Another debugger"))return!1;throw t}}async function Ut(e,t){const r=Pt[t];await vt(e),await chrome.debugger.sendCommand({tabId:e},"Network.enable"),r.network?await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",r.network):await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:r.cpuRate}),re.info(`applied ${t} (label="${r.label}", cpu×${r.cpuRate})`)}async function kt(e){try{await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:1})}catch(t){re.debug("throttle reset commands failed (debugger may not be attached)",t)}}const f=m("service-worker");De("service-worker");pe();var R,q;(q=(R=chrome.sidePanel)==null?void 0:R.setPanelBehavior)==null||q.call(R,{openPanelOnActionClick:!0}).catch(e=>f.warn("setPanelBehavior failed",e));he();Ee();me();Te().catch(e=>f.warn("initial cloud pull failed",e));(async()=>(await Se(),await Je(),Z(),we(),ye(),Re()))();chrome.alarms.onAlarm.addListener(e=>{const t=Ae(e.name);t!==null&&Ie(t).catch(r=>f.warn(`scheduled audit ${t} threw at top level`,r))});Ze();Ce();_e();ct();ut();be();Tt();St();Rt(X);self.addEventListener("unhandledrejection",e=>{const t=e.reason;$e(t instanceof Error?t:new Error(String(t)))});let b=!1;chrome.runtime.onConnect.addListener(e=>{if(e.name==="audit-keepalive"){f.debug("keepalive connected"),e.onDisconnect.addListener(async()=>{f.debug("keepalive disconnected"),await Pe()});return}if(e.name==="sidepanel-tracker"){b=!0,f.debug("chrome.sidePanel opened"),e.onDisconnect.addListener(async()=>{b=!1,f.debug("chrome.sidePanel closed — restoring in-page overlay"),await $()});return}});let D=!1;const T={isCanceled:()=>D};async function ae(){const e=await P();if(e)try{await z(e,{type:"SIDEBAR_HIDE_REQUEST"})}catch(t){f.warn("sidebar hide failed",t)}}async function $(){const e=await P();if(e)try{await z(e,{type:"SIDEBAR_SHOW_REQUEST"})}catch(t){f.warn("sidebar show failed",t)}}g("START_AUDIT",async e=>{D=!1,await ae();const t=await P();let r;const a={verifyFixesOnly:e.verifyFixesOnly};if(e.mode==="single-element"){if(!e.scope)throw new Error("START_AUDIT single-element requires scope");r=k(e.scope,T,e.frameId,e.matrixOverride,a)}else if(e.mode==="full-page")r=k("html",T,0,e.matrixOverride,a);else if(e.mode==="quick-scan"){const{QUICK_SCAN_MATRIX_SETTINGS:n}=await G(async()=>{const{QUICK_SCAN_MATRIX_SETTINGS:s}=await import("./ai-usage-log-D5enikfX.js").then(i=>i.I);return{QUICK_SCAN_MATRIX_SETTINGS:s}},__vite__mapDeps([0,1]));r=k(e.scope??"html",T,e.frameId??0,n,a)}else if(e.mode==="all-frames")r=ve(T);else if(e.mode==="parallel-scan"){const{runParallelScan:n}=await G(async()=>{const{runParallelScan:s}=await import("./scheduled-audit-runner-QcMYcqgA.js").then(i=>i.aU);return{runParallelScan:s}},__vite__mapDeps([2,3,1,0,4]));r=n(T)}else r=Ue(T);r.catch(n=>{f.error("audit failed",n);const s=n instanceof Error?n.message:String(n),i=/no audit target tab/i.test(s);Fe({type:"AUDIT_FAILED_EVENT",error:{code:i?"RESTRICTED_URL":"UNKNOWN",message:i?"No audit target tab found. Open a regular http(s) page (not chrome:// or about:blank) and try again.":`Audit failed: ${s}`,recoverable:!0}})}).finally(()=>{t!=null&&Y(t).catch(n=>f.debug("post-audit debugger release failed (best-effort)",n)),b||$()})});g("CANCEL_AUDIT",async()=>{D=!0,f.info("cancel requested")});let F=!1;const Ot={isCanceled:()=>F};g("START_SITE_CRAWL",async e=>{F=!1,await ae();const t=await P();ke(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex,verifyFixesOnly:e.verifyFixesOnly},Ot).catch(r=>f.error("site crawl failed",r)).finally(()=>{t!=null&&Y(t).catch(r=>f.debug("post-crawl debugger release failed (best-effort)",r)),b||$()})});g("CANCEL_SITE_CRAWL",async()=>{F=!0,f.info("site crawl cancel requested")});g("REGRADE_SITE_CRAWL",async()=>{try{const e=await Oe();return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:e.ok,...e.reason?{reason:e.reason}:{}}}catch(e){return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:!1,reason:e instanceof Error?e.message:String(e)}}});g("OPEN_SETTINGS",()=>{chrome.runtime.openOptionsPage()});g("PERF_THROTTLE_APPLY_REQUEST",async e=>{try{return await Ut(e.tabId,e.profile),{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("PERF_THROTTLE_CLEAR_REQUEST",async e=>{try{return await kt(e.tabId),{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("AX_TREE_SNAPSHOT_REQUEST",async e=>{try{return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!0,nodes:await _t(e.tabId)}}catch(t){return f.warn("ax-tree snapshot failed",t),{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});f.info("service worker ready");
|
package/dist/manifest.json
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "wcagcheckr",
|
|
4
4
|
"description": "Audit components across hover, focus, dark mode, forced colors, RTL — every state your users actually encounter. Per-component baselines surface only NEW violations.",
|
|
5
|
-
"version": "1.0.0.
|
|
6
|
-
"version_name": "1.0.0-rc.
|
|
5
|
+
"version": "1.0.0.332",
|
|
6
|
+
"version_name": "1.0.0-rc.332",
|
|
7
7
|
"author": "Locustware",
|
|
8
8
|
"homepage_url": "https://wcagcheckr.com",
|
|
9
9
|
"icons": {
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<title>wcagcheckr offscreen worker</title>
|
|
6
|
-
<script type="module" crossorigin src="/assets/offscreen-
|
|
6
|
+
<script type="module" crossorigin src="/assets/offscreen-BAvM-6sh.js"></script>
|
|
7
7
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-D7HrI6pR.js">
|
|
9
9
|
</head>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import './assets/service-worker.ts-
|
|
1
|
+
import './assets/service-worker.ts-B7jEQy1y.js';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcag-checkr/ci",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.332",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Headless wcagcheckr accessibility audit runner for CI/CD pipelines. Drives the wcagcheckr Chrome extension via Playwright, runs full-page audits across the state matrix (108 combinations: hover, focus, dark mode, RTL, breakpoints), outputs JSON / SARIF / JUnit, exits with severity-aware codes.",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import"./modulepreload-polyfill-B5Qt9EMX.js";import{_ as Q}from"./preload-helper-D7HrI6pR.js";const Y=new Set(["Document","Part","Art","Sect","Div","BlockQuote","Caption","TOC","TOCI","Index","NonStruct","Private","H","H1","H2","H3","H4","H5","H6","P","L","LI","Lbl","LBody","Table","TR","TH","TD","THead","TBody","TFoot","Span","Quote","Note","Reference","BibEntry","Code","Link","Annot","Ruby","RB","RT","RP","Warichu","WT","WP","Figure","Formula","Form"]);function X(){const t=new Map;let r=0;return{ruleAggregates:t,figureAltCandidates:[],get lastHeading(){return r},set lastHeading(e){r=e},bumpRule(e,i){let o=t.get(e);o||(o={count:0,pages:new Set},t.set(e,o)),o.count++,o.pages.add(i)},setLastHeadingLevel(e){r=e},getLastHeading(){return r}}}function J(t,r,n){if(!t||typeof t!="object")return;const e=t.role;if(e&&!Y.has(e)&&n.bumpRule("pdf-non-standard-role",r),e==="Figure"){const i=(t.alt??"").trim();i?n.figureAltCandidates.push({pageNum:r,alt:i}):n.bumpRule("pdf-figure-missing-alt",r)}if(e&&/^H[1-6]$/.test(e)){const i=parseInt(e.slice(1),10),o=n.getLastHeading();o>0&&i>o+1&&n.bumpRule("pdf-heading-skip",r),n.setLastHeadingLevel(i)}if(e==="Table"&&!K(t,"TH")&&n.bumpRule("pdf-table-no-header",r),e==="L"){const i=t.children??[],o=i.some(s=>s&&s.role&&s.role!=="LI"&&s.role!=="Caption");(i.length===0||o)&&n.bumpRule("pdf-list-malformed",r)}for(const i of t.children??[])J(i,r,n)}function K(t,r){if(!t)return!1;if(t.role===r)return!0;for(const n of t.children??[])if(K(n,r))return!0;return!1}function Z(t){if(!t)return 0;const r=t.filter(e=>e.subtype==="Widget");let n=0;for(const e of r){const i=(e.alternativeText??"").trim(),o=(e.fieldName??"").trim(),s=/^(field|text\s*box|check\s*box|radio|button)\s*\d*$/i.test(o);!i&&(!o||s)&&n++}return n}function ee(t){const r=[],n={"pdf-figure-missing-alt":{ruleId:"pdf-figure-missing-alt",impact:"serious",wcagCriterion:"1.1.1",describe:e=>({description:`${e.count} Figure tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) have no alt text. Screen-reader users hear nothing for these images. PDF/UA-1 §7.4.`,failureSummary:"Open the PDF in Acrobat → Accessibility → Reading Order → click each Figure → Edit Alternate Text. Or, in source: add alt text to each image in Word/InDesign/PowerPoint before exporting."})},"pdf-heading-skip":{ruleId:"pdf-heading-skip",impact:"moderate",wcagCriterion:"1.3.1",describe:e=>({description:`Heading levels skip (e.g. H1 → H3 without H2). Detected ${e.count} skip${e.count===1?"":"s"} across ${e.pages.size} page${e.pages.size===1?"":"s"}. Screen-reader users hear the section hierarchy as broken.`,failureSummary:"Re-tag the headings sequentially. In Acrobat → Accessibility → Reading Order, change the offending tag to the correct heading level. In source documents use Heading 1 → Heading 2 → Heading 3 styles consistently."})},"pdf-table-no-header":{ruleId:"pdf-table-no-header",impact:"serious",wcagCriterion:"1.3.1",describe:e=>({description:`${e.count} Table tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) have no TH (header) cells. Screen-reader table-navigation mode cannot announce headers when reading cells.`,failureSummary:"Open the PDF in Acrobat → Accessibility → Reading Order → select the table → Table Editor. Mark the first row (or first column) as headers. In source documents (Word: Table Tools → Layout → Repeat Header Rows; PowerPoint: tables need to be tagged as data tables)."})},"pdf-list-malformed":{ruleId:"pdf-list-malformed",impact:"moderate",wcagCriterion:"1.3.1",describe:e=>({description:`${e.count} List tag${e.count===1?"":"s"} (across ${e.pages.size} page${e.pages.size===1?"":"s"}) are malformed — L tags should contain LI children with optional Lbl + LBody. PDF/UA-1 §7.8.`,failureSummary:'Re-tag the lists in Acrobat → Accessibility → Reading Order, or recreate the PDF from a source document that produces proper list tagging (bullet/numbered lists in Word/Pages/Google Docs export correctly when "tagged PDF" is enabled).'})},"pdf-non-standard-role":{ruleId:"pdf-non-standard-role",impact:"minor",wcagCriterion:"1.3.1",describe:e=>{const i=Array.from(e.pages).slice(0,3).join(", ");return{description:`${e.count} structure-tree node${e.count===1?"":"s"} use non-standard tag roles (sample pages: ${i}). PDF/UA-1 §7.3 requires a RoleMap entry in StructTreeRoot mapping each custom role to a standard one.`,failureSummary:"Either replace the non-standard tags with PDF/UA standard ones (Document/Part/Art/Sect/Div/H1-H6/P/L/LI/Table/TR/TH/TD/Figure/Form/etc.), or add RoleMap entries in StructTreeRoot mapping each custom name to a standard equivalent."}}},"pdf-untagged-content":{ruleId:"pdf-untagged-content",impact:"critical",wcagCriterion:"1.3.1",describe:e=>({description:`${e.pages.size} page${e.pages.size===1?"":"s"} have no structure tree (untagged content). Screen-reader users get no reading order on these pages — content may be read in random visual-position order or skipped entirely.`,failureSummary:"Re-tag the document end-to-end. In Acrobat → Accessibility → Autotag Document is a starting point but rarely produces good results — re-export from the source document with tagging enabled, then refine in Acrobat's Reading Order tool."})}};for(const[e,i]of t.ruleAggregates){const o=n[e];if(!o)continue;const{description:s,failureSummary:p}=o.describe(i);r.push({ruleId:o.ruleId,impact:o.impact,wcagCriterion:o.wcagCriterion,description:s,failureSummary:p})}return r}function te(t,r){return t===0?null:{ruleId:"pdf-field-no-name",impact:"serious",wcagCriterion:"4.1.2",description:`${t} form field${t===1?"":"s"} across ${r} page${r===1?"":"s"} have no accessible name (no /TU alternate text + no descriptive /T field name). Screen-reader users hear nothing or hear the field type generically ("text field", "check box").`,failureSummary:'In Acrobat: open the Tools → Prepare Form panel → right-click each field → Properties → General tab → fill in the "Tooltip" (this becomes the PDF /TU). Or rename the /T field name to something descriptive ("First name", "Total amount due"). PDF/UA-1 §7.15.'}}function re(t,r,n){return r===0||n||t>0?null:{ruleId:"pdf-image-only",impact:"critical",wcagCriterion:"1.1.1",description:`PDF has no extractable text on any of its ${r} page${r===1?"":"s"} — appears to be a scanned document with no OCR layer. Screen-reader users hear silence; keyboard search returns no hits; copy/paste yields nothing.`,failureSummary:'Run OCR on the PDF before distributing it. Acrobat Pro → Tools → Scan & OCR → "Recognize Text". Free options: ocrmypdf (CLI), Google Drive (upload → open as Google Doc), or Tesseract. After OCR, re-tag the document (Acrobat → Accessibility → Autotag Document, then refine in Reading Order) so the recognized text gets a proper structure tree.'}}function ne(t,r,n){if(r===0)return null;const e=n!=null&&isFinite(n)?n.toFixed(2):"?";return{ruleId:"pdf-text-low-contrast",impact:"serious",wcagCriterion:"1.4.3",description:`${r} text run${r===1?"":"s"} across ${t} page${t===1?"":"s"} fall below the WCAG 1.4.3 AA contrast threshold (4.5:1 for normal text, 3:1 for large text). Worst observed ratio: ${e}:1. Low-vision readers cannot reliably read this text against its background.`,failureSummary:"Rebuild the source document with stronger contrast — typically darken the text or lighten the background. For brand color palettes, use a contrast checker (https://webaim.org/resources/contrastchecker/) to pick a compliant pair. Re-export the PDF with the new colors. Note: this check samples rendered pixels, so even if the source uses semantic colors, what the reader sees IS the verdict."}}function oe(t,r){return t===0?null:{ruleId:"pdf-reading-order-mismatch",impact:"serious",wcagCriterion:"1.3.2",description:`${t} place${t===1?"":"s"} across ${r} page${r===1?"":"s"} where the content-stream reading order jumps backward (significant upward y-motion). Screen-reader users will hear the text in an order that doesn't match the visual layout. PDF/UA-1 §7.10 / WCAG 1.3.2.`,failureSummary:'Most common cause: multi-column layouts that were drawn column-by-column in the source document instead of being tagged with a proper reading order. Fix in Acrobat: Tools → Accessibility → Reading Order → "Show Order Panel" → drag the order entries into the correct sequence. In source documents (Word, InDesign), use proper linked text frames / column flow so the export-to-PDF preserves a top-down read.'}}function ie(t,r){return t<=5||r?null:{ruleId:"pdf-no-bookmarks",impact:"moderate",wcagCriterion:"2.4.5",description:`Multi-page PDF (${t} pages) has no bookmarks / outline. Keyboard and AT users cannot navigate the document structure without scrolling page-by-page.`,failureSummary:'Add bookmarks to the PDF in Acrobat (View → Show/Hide → Navigation Panes → Bookmarks, then add entries for each section heading). Or re-export from the source document with "Generate bookmarks" enabled (Word: Save As PDF → Options → Create bookmarks using: Headings).'}}function V({r:t,g:r,b:n}){const e=i=>{const o=i/255;return o<=.03928?o/12.92:Math.pow((o+.055)/1.055,2.4)};return .2126*e(t)+.7152*e(r)+.0722*e(n)}function se(t,r){const n=V(t),e=V(r),i=Math.max(n,e),o=Math.min(n,e);return(i+.05)/(o+.05)}function ae(t,r){return!isFinite(t)||t<=0?!1:!!(r&&t>=14*1.333||t>=18*1.333)}function ce(t){return t?3:4.5}let U=null;function le(){return U||(U=(async()=>{try{const t=(await Q(async()=>{const{default:n}=await import("./pdf.worker-B4IDxXWI.js");return{default:n}},[])).default,r=await Q(()=>import("./pdf-DfaD4CCm.js"),[]);return r.GlobalWorkerOptions&&(r.GlobalWorkerOptions.workerSrc=t),r}catch(t){return{error:t instanceof Error?t.message:String(t)}}})()),U}async function de(t,r){let n;try{n=await fetch(t)}catch(o){return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`Network error fetching PDF: ${o instanceof Error?o.message:String(o)}`}}if(!n.ok)return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`Fetch failed with HTTP ${n.status}`};const e=n.headers.get("content-length");if(e&&parseInt(e,10)>r)return{ok:!1,source:t,findings:[],pageCount:null,fatalError:`PDF exceeds size cap (${e} bytes > ${r}). Skipped — audit it manually via the CLI: \`wcagcheckr-ci pdf ${t}\`.`};const i=await n.arrayBuffer();return i.byteLength>r?{ok:!1,source:t,findings:[],pageCount:null,fatalError:`PDF exceeds size cap (${i.byteLength} bytes > ${r}). Skipped.`}:fe(new Uint8Array(i),t)}async function ue(t,r){const n={failingRuns:0,worstRatio:null,textItems:0,itemsSkippedTooSmall:0,itemsSkippedOutOfBounds:0,itemsSkippedBgOnly:0,itemsSampled:0,bestObservedRatio:null},e=r.OPS;if(!e)return n;let i;try{i=await t.getOperatorList()}catch(m){return n.renderError=`getOperatorList threw: ${m instanceof Error?m.message:String(m)}`,n}let o={r:0,g:0,b:0},s=12,p=!1;const F=[],R={r:255,g:255,b:255},$=.2126*R.r+.7152*R.g+.0722*R.b,T=i.fnArray,x=i.argsArray,v=T.length;for(let m=0;m<v;m++){const b=T[m],k=x[m]??[];if(b===e.save)F.push({fillColor:{...o},fontSize:s,fontIsBold:p});else if(b===e.restore){const l=F.pop();l&&(o=l.fillColor,s=l.fontSize,p=l.fontIsBold)}else if(b===e.setFillRGBColor){const l=Number(k[0])|0,h=Number(k[1])|0,y=Number(k[2])|0;isFinite(l)&&isFinite(h)&&isFinite(y)&&(o={r:l,g:h,b:y})}else if(b===e.setFillGray){const l=Number(k[0]);if(isFinite(l)){const h=Math.max(0,Math.min(255,Math.round(l*255)));o={r:h,g:h,b:h}}}else if(b===e.setFont){const l=Number(k[1]);isFinite(l)&&l>0&&(s=l);const h=String(k[0]??"");p=/-?(Bold|Black|Heavy)/i.test(h)}else if(b===e.showText||b===e.showSpacedText||b===e.nextLineShowText||b===e.nextLineSetSpacingShowText){n.textItems++;const l=.2126*o.r+.7152*o.g+.0722*o.b;if(Math.abs(l-$)<1){n.itemsSkippedBgOnly++;continue}n.itemsSampled++;const h=ae(s,p),y=ce(h),C=se(o,R);(n.bestObservedRatio===null||C>n.bestObservedRatio)&&(n.bestObservedRatio=C),C<y&&(n.failingRuns++,(n.worstRatio===null||C<n.worstRatio)&&(n.worstRatio=C))}}return n}async function fe(t,r){var j,q;const n=await le();if("error"in n)return{ok:!1,source:r,findings:[],pageCount:null,fatalError:`pdfjs failed to load in offscreen document: ${n.error}`};const e=n;let i;try{i=await e.getDocument({data:t,verbosity:0,disableFontFace:!0,useSystemFonts:!1}).promise}catch(u){return{ok:!0,source:r,findings:[{ruleId:"pdf-structure-tree-unparseable",impact:"serious",wcagCriterion:"1.3.1",description:`pdfjs could not open the PDF: ${u instanceof Error?u.message:String(u)}. Usually means encrypted, malformed, or non-standard structure.`,failureSummary:"Try opening the PDF in a recent Acrobat Reader — if it opens there but fails the extension audit, the PDF uses uncommon encoding pdfjs cannot handle. If it fails everywhere the source document needs to be regenerated."}],pageCount:null}}const o=i.numPages;let s=!1;try{const u=await i.getOutline();s=Array.isArray(u)&&u.length>0}catch{}const p=X();let F=0,R=0,$=0,T=0,x=0,v=0,m=null;const b=[];let k=0,l=0;const h=[];for(let u=1;u<=o;u++){let P;try{P=await i.getPage(u)}catch{continue}let L=null;try{L=await P.getStructTree()}catch{}L?J(L,u,p):p.bumpRule("pdf-untagged-content",u);try{const a=await P.getAnnotations();(a??[]).filter(d=>d.subtype==="Widget").length>0&&(R++,F+=Z(a))}catch{}let c=null,E;try{c=await P.getTextContent();const a=(c==null?void 0:c.items)??[];let f=0;for(const d of a)f+=((d==null?void 0:d.str)??"").length;$+=f}catch(a){T++,E=a instanceof Error?a.message:String(a)}if(c!=null&&c.items&&c.items.length>0){const a=[];for(const f of c.items){const d=f.transform;if(!d||d.length<6)continue;const S=Math.abs(d[3]??0);S>0&&(f.str??"").trim()&&a.push(S)}if(a.length>=2){const f=new Map;for(const g of a){const w=Math.round(g*2)/2;f.set(w,(f.get(w)??0)+1)}let d=1/0,S=-1;for(const[g,w]of f)(w>S||w===S&&g<d)&&(S=w,d=g);const A=d*1.2;for(let g=0;g<c.items.length;g++){const w=c.items[g],D=w.transform;if(!D||D.length<6)continue;const H=Math.abs(D[3]??0),_=(w.str??"").trim();if(!_||H<A||_.length>200)continue;let O="";for(let I=g+1;I<c.items.length&&O.length<800;I++){const M=(((j=c.items[I])==null?void 0:j.str)??"").trim();if(!M)continue;const B=(q=c.items[I])==null?void 0:q.transform;if(B&&B.length>=6&&Math.abs(B[3]??0)>=A&&M.length<200)break;O+=(O?" ":"")+M}O.length!==0&&h.push({pageNum:u,headingText:_,sectionContent:O.slice(0,800)})}}}if(c!=null&&c.items&&c.items.length>=2){let a=0;for(let f=1;f<c.items.length;f++){const d=c.items[f-1],S=c.items[f],A=d.transform,g=S.transform;if(!A||A.length<6||!g||g.length<6||!(S.str??"").trim()||!(d.str??"").trim())continue;const w=A[5],D=g[5],H=Math.abs(g[3])||12;D-w>2*H&&a++}a>0&&(k+=a,l++)}try{const a=await ue(P,e);b.push({page:u,...a,...E?{textContentError:E}:{}}),a.failingRuns>0&&(x+=a.failingRuns,v++,a.worstRatio!==null&&(m===null||a.worstRatio<m)&&(m=a.worstRatio))}catch{}}const y=ee(p),C=te(F,R);C&&y.push(C);const z=ie(o,s);z&&y.push(z);const N=re($,o,T===o);N&&y.push(N);const W=ne(v,x,m);W&&y.push(W);const G=oe(k,l);return G&&y.push(G),{ok:!0,source:r,findings:y,pageCount:o,perPageContrast:b,aiCandidates:{figureAltTexts:p.figureAltCandidates,headings:h}}}chrome.runtime.onMessage.addListener((t,r,n)=>{const e=t;if(!e||e.type!=="OFFSCREEN_PDF_AUDIT_REQUEST")return!1;const i=typeof e.url=="string"?e.url:"",o=typeof e.maxBytes=="number"?e.maxBytes:16*1024*1024;return(async()=>{let s;try{s=await de(i,o)}catch(F){s={ok:!1,source:i,findings:[],pageCount:null,fatalError:`Offscreen audit threw: ${F instanceof Error?F.message:String(F)}`}}const p={type:"OFFSCREEN_PDF_AUDIT_RESPONSE",ok:s.ok,source:s.source,findings:s.findings,pageCount:s.pageCount,...s.fatalError?{fatalError:s.fatalError}:{},...s.perPageContrast?{_perPageContrast:s.perPageContrast}:{},...s.aiCandidates?{aiCandidates:s.aiCandidates}:{}};n(p)})(),!0});
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ai-usage-log-D5enikfX.js","assets/crash-reporter-Bu2p8K-p.js","assets/scheduled-audit-runner-QcMYcqgA.js","assets/preload-helper-D7HrI6pR.js","assets/diff-DIBMr3fQ.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{_ as H}from"./preload-helper-D7HrI6pR.js";import{ag as ne,ah as X,ai as x,aj as L,g as oe,C as se,ak as ie,al as ce,am as le,an as de,ao as ue,ap as fe,aq as ge,ar as pe,as as he,at as Ee,au as Se,av as Te,aw as me,ax as we,ay as Re,aa as Ae,az as ye,aA as Ie,aB as _e,aC as Ce,aD as be,aE as Pe,q as P,aF as O,aG as Ue,aH as ve,aI as Y,aJ as Oe,aK as ke}from"./scheduled-audit-runner-QcMYcqgA.js";import{v as y,T as G,w as C,j as Ne}from"./ai-usage-log-D5enikfX.js";import{c as S,o as g,f as xe,g as Le,i as De,h as Fe,d as z,e as $e}from"./crash-reporter-Bu2p8K-p.js";import{m as V}from"./diff-DIBMr3fQ.js";const N="tierConfig:cache",Me=60*60*1e3,He=24*60*60*1e3,Ge=7*24*60*60*1e3;async function Ve(){return(await chrome.storage.local.get(N))[N]??null}async function We(e){await chrome.storage.local.set({[N]:e})}function Be(e,t=Date.now()){const r=t-e.fetchedAt;return r<Me?"fresh":r<He?"stale":r<Ge?"grace":"expired"}function Ke(e,t){const r={...e},a=p=>{if(typeof p=="number")return p===-1?1/0:p},n=p=>typeof p=="boolean"?p:void 0,o=p=>{if(p==="all"||p==="configurable"||p==="default-only")return p},s=a(t.maxComponents);s!==void 0&&(r.maxComponents=s);const c=a(t.maxBaselines);c!==void 0&&(r.maxBaselines=c);const d=o(t.stateMatrix);d!==void 0&&(r.stateMatrix=d);const l=n(t.storybookAutoIterate);l!==void 0&&(r.storybookAutoIterate=l);const i=n(t.exportJson);i!==void 0&&(r.exportJson=i);const u=n(t.exportSarif);u!==void 0&&(r.exportSarif=u);const h=n(t.exportJunit);h!==void 0&&(r.exportJunit=h);const U=n(t.cloudSync);U!==void 0&&(r.cloudSync=U);const E=n(t.forensicAnchoring);E!==void 0&&(r.forensicAnchoring=E);const m=n(t.autoExportAuditReports);m!==void 0&&(r.autoExportAuditReports=m);const w=n(t.pdfAudit);return w!==void 0&&(r.pdfAudit=w),r}function je(e,t){var a;if(e==="trial")return((a=t.trial)==null?void 0:a.features)??null;const r=t.plans.find(n=>n.code===e||n.code.startsWith(e+"-"));return(r==null?void 0:r.features)??null}const I=S("tier-config-client"),Qe="wcagcheckr",qe=`https://api.wcagcheckr.com/v1/products/${Qe}/tier-config`,Xe=1e4,W="tier-config-refresh",Ye=60,ze=["trial","free","solo","team"];function J(e){const t={};for(const r of ze){const a=je(r,e);t[r]=a?Ke(G[r],a):{...G[r]}}return t}async function Je(){const e=await Ve();if(!e){y(null);return}if(Be(e)==="expired"){I.warn("cached tier-config is expired (>7d); using hardcoded defaults"),y(null);return}y(J(e.config))}async function Z(){try{const e=await fetch(qe,{signal:AbortSignal.timeout(Xe),headers:{accept:"application/json"}});if(!e.ok)throw new Error(`http ${e.status}`);const t=await e.json();await We({fetchedAt:Date.now(),config:t}),y(J(t));const r=t.wcagTargetVersion;if(r==="2.1"||r==="2.2")try{await chrome.storage.local.set({wcagTargetVersion:r}),ne(r)}catch(a){I.warn("failed to persist wcagTargetVersion",a)}I.info("tier-config refreshed from server")}catch(e){I.warn("tier-config refresh failed; keeping prior cache",e)}}function Ze(){chrome.alarms.create(W,{periodInMinutes:Ye}),chrome.alarms.onAlarm.addListener(e=>{e.name===W&&Z()})}const et=S("support-messenger"),tt="https://api.wcagcheckr.com/v1/products/wcagcheckr/support",k="support:rate-window",rt=5,at=10*60*1e3,nt=2,ot="wcagcheckr",B="storybook:lastDetected";async function st(e){if(!e)return;const t=await chrome.runtime.getPlatformInfo(),a=(await chrome.storage.local.get(B))[B];return{extensionVersion:chrome.runtime.getManifest().version,platform:t,storybookDetected:a!=null&&a.detected?a.version??"detected":"none",licenseTier:await X(),logTail:xe(Le())}}async function it(e=Date.now()){const r=((await chrome.storage.local.get(k))[k]??[]).filter(a=>e-a<at);return r.length>=rt?!1:(r.push(e),await chrome.storage.local.set({[k]:r}),!0)}async function ee(e,t=0){try{const r=await fetch(tt,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!r.ok)throw new Error(`http ${r.status}`);const a=await r.json();if(!a.success)throw new Error(a.error??"server returned success=false");return{ticketRef:a.ticketRef??""}}catch(r){if(t<nt){const a=(t+1)*1e3;return await new Promise(n=>setTimeout(n,a)),ee(e,t+1)}throw r}}function ct(){return g("SUPPORT_MESSAGE_REQUEST",async e=>{if(!await it())return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:V("NETWORK","Rate limit reached. Try again in 10 minutes.",!0)};try{const t=await st(e.includeContext);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!0,ticketRef:(await ee({productSlug:ot,subject:e.subject,body:e.body,replyEmail:e.replyEmail,context:t,extensionVersion:chrome.runtime.getManifest().version,timestamp:new Date().toISOString()})).ticketRef}}catch(t){et.error("send failed",t);const r=t instanceof Error?t.message:String(t);return{type:"SUPPORT_MESSAGE_RESPONSE",success:!1,error:V("NETWORK",r,!0)}}})}const te=S("ai-color-suggester");async function lt(e,t,r=[]){if(!t.enabled||e.length===0)return{results:[],totalCostUsd:0,capExceeded:!1};const a=x(t);if(!a.ok)return{results:[],totalCostUsd:0,capExceeded:!1};const n=a.client,o=L(t.costCapUsd),s=[];for(const c of e){if(!o.canCharge())break;try{const d=await n.suggestColorFix({foreground:c.foreground,background:c.background,fontSize:c.fontSize,fontWeight:c.fontWeight,targetLevel:c.targetLevel,paletteHints:r});o.recordCharge(d.costUsd),d.verdict==="suggested"&&d.candidates.length>0&&s.push({matchKey:c.matchKey,suggestions:d.candidates,reasoning:d.reasoning,costUsd:d.costUsd})}catch(d){te.warn(`color-fix suggestion failed for ${c.matchKey}`,d)}}return{results:s,totalCostUsd:o.state.spentUsd,capExceeded:o.state.exceeded}}async function dt(){const e=await chrome.storage.local.get("aiConfig");return C(e.aiConfig)}function ut(){return g("AI_COLOR_SUGGEST_REQUEST",async e=>{const t=await dt();if(!t.enabled)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!t.apiKey)return{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{results:r,totalCostUsd:a,capExceeded:n}=await lt(e.inputs,t,e.paletteHints);return{type:"AI_COLOR_SUGGEST_RESPONSE",results:r,totalCostUsd:a,capExceeded:n}}catch(r){return te.warn("color-suggest handler failed",r),{type:"AI_COLOR_SUGGEST_RESPONSE",results:[],totalCostUsd:0,capExceeded:!1,unavailableReason:r instanceof Error?r.message:String(r)}}})}function K(e){if(!e)return null;const t=e.match(/rgba?\(\s*([0-9.]+)\s*,?\s*([0-9.]+)\s*,?\s*([0-9.]+)(?:\s*[,/]\s*([0-9.]+))?\s*\)/i);return t?{r:Math.round(parseFloat(t[1])),g:Math.round(parseFloat(t[2])),b:Math.round(parseFloat(t[3])),a:t[4]!==void 0?parseFloat(t[4]):1}:null}function j(e){const t=r=>{const a=r/255;return a<=.03928?a/12.92:Math.pow((a+.055)/1.055,2.4)};return .2126*t(e.r)+.7152*t(e.g)+.0722*t(e.b)}function ft(e,t){const r=j(e),a=j(t),n=Math.max(r,a),o=Math.min(r,a);return(n+.05)/(o+.05)}function gt(e,t){const r=Math.max(0,Math.min(1,e.a));return{r:Math.round(e.r*r+t.r*(1-r)),g:Math.round(e.g*r+t.g*(1-r)),b:Math.round(e.b*r+t.b*(1-r))}}function pt(e,t){var M;if(e!=="color-contrast"&&e!=="color-contrast-enhanced")return null;const r=t.styles;if(!r)return null;const a=((M=r.effectiveBackground)==null?void 0:M.color)??r.background,n=r.foreground;if(!n||!a)return null;const o=K(n),s=K(a);if(!o||!s||s.a<.999)return null;const c=o.a<.999?gt(o,s):{r:o.r,g:o.g,b:o.b},d=ft(c,s),l=r.fontSize??16,i=r.fontWeight??400,u=l>=24||l>=18.5&&i>=700,E=e==="color-contrast-enhanced"?u?4.5:7:u?3:4.5,m=d>=E?"pass":"fail",w=v=>`rgb(${v.r}, ${v.g}, ${v.b})`,p=`Deterministic WCAG contrast measurement (no AI guessing, no pixel sampling). Foreground ${w(c)}${o.a<.999?` (originally rgba with alpha=${o.a}, composited over background)`:""} against background ${w(s)} yields contrast ratio ${d.toFixed(2)}:1. Text is ${l}px at font-weight ${i}; ${u?"qualifies as large text (threshold 3:1 for AA)":"normal text (threshold 4.5:1 for AA)"}. ${m==="pass"?`Passes AA at ${E}:1.`:`Falls below the ${E}:1 threshold.`}`;return{verdict:m,ratio:d,threshold:E,reasoning:p}}async function ht(e,t,r){var c,d,l,i,u;const a=JSON.stringify({ruleId:e,selector:t,styles:{fg:((c=r.styles)==null?void 0:c.foreground)??null,bg:((d=r.styles)==null?void 0:d.background)??null,fs:((l=r.styles)==null?void 0:l.fontSize)??null,fw:((i=r.styles)==null?void 0:i.fontWeight)??null,ts:((u=r.styles)==null?void 0:u.textSample)??null},failureSummary:r.failureSummary??null}),n=new TextEncoder().encode(a),o=await crypto.subtle.digest("SHA-256",n);return Array.from(new Uint8Array(o)).map(h=>h.toString(16).padStart(2,"0")).join("")}const _=S("ai-incomplete-resolver");function Q(e,t){if(!e)return t;const r=e.toLowerCase(),a=/verdict\s+corrected\s+to\s+pass|verdict:\s*pass\s+\(corrected\)/i,n=/verdict\s+corrected\s+to\s+fail|verdict:\s*fail\s+\(corrected\)/i,o=R(r,a),s=R(r,n);if(o>s&&o>=0)return"pass";if(s>o&&s>=0)return"fail";const c=/actually\s+passes|in\s+fact\s+passes|passes\s+AA/gi,d=/actually\s+fails|in\s+fact\s+fails|fails\s+AA/gi,l=R(r,c),i=R(r,d);return l<0&&i<0?t:l>i&&l/r.length>=.5?"pass":i>l&&i/r.length>=.5?"fail":t}function R(e,t){let r=-1;const a=t.flags.includes("g")?t.flags:t.flags+"g",n=new RegExp(t.source,a);let o;for(;(o=n.exec(e))!==null;)r=o.index,o.index===n.lastIndex&&n.lastIndex++;return r}async function Et(){const e=await chrome.storage.local.get("aiConfig");return C(e.aiConfig)}async function St(e){if(!e.aiConfig.enabled||e.elements.length===0)return{resolutions:[],totalCostUsd:0};const t=x(e.aiConfig);if(!t.ok)return{resolutions:[],totalCostUsd:0};const r=t.client,a=L(e.aiConfig.costCapUsd),n=[],o=await oe(e.pageUrl),s=new Map;for(const c of o)s.set(`${c.ruleId}::${c.selector}`,c);for(const c of e.elements){if(!a.canCharge())break;const d=await ht(e.ruleId,c.selector,c),l=s.get(`${e.ruleId}::${c.selector}`),i=pt(e.ruleId,c);if(i){_.info(`Deterministic verdict for ${e.ruleId} on ${c.selector}: ${i.verdict} (${i.ratio.toFixed(2)}:1 vs ${i.threshold}:1) — math overrides cache + AI`),n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:c.selector,verdict:i.verdict,reasoning:i.reasoning,resolvedAt:new Date().toISOString(),costUsd:0,wcagCriterion:e.wcagCriterion,inputHash:d});continue}if(l&&l.inputHash===d&&l.verdict!=="uncertain"){_.info(`Reusing cached resolution for ${e.ruleId} on ${c.selector} (hash match, verdict=${l.verdict})`);const u=Q(l.reasoning,l.verdict);n.push({...l,verdict:u,resolvedAt:new Date().toISOString(),costUsd:0,inputHash:d});continue}try{const u=await r.resolveAxeIncomplete({ruleId:e.ruleId,element:c,pageUrl:e.pageUrl,targetLevel:e.targetLevel});a.recordCharge(u.costUsd);const h=Q(u.reasoning,u.verdict);n.push({pageUrl:e.pageUrl,ruleId:e.ruleId,selector:c.selector,verdict:h,reasoning:u.reasoning,resolvedAt:new Date().toISOString(),costUsd:u.costUsd,wcagCriterion:e.wcagCriterion,inputHash:d})}catch(u){_.warn(`resolveAxeIncomplete failed for ${c.selector}`,u)}}return n.length>0&&await se(n),{resolutions:n,totalCostUsd:a.state.spentUsd}}function Tt(){return g("AI_RESOLVE_INCOMPLETE_REQUEST",async e=>{const t=await Et();if(!t.enabled)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"AI augmentation is disabled in Settings → AI augmentation."};if(!t.apiKey)return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:"No AI API key configured. Add one in Settings → AI augmentation."};try{const{resolutions:r,totalCostUsd:a}=await St({ruleId:e.ruleId,pageUrl:e.pageUrl,wcagCriterion:e.wcagCriterion,elements:e.elements,targetLevel:e.targetLevel,aiConfig:t});return{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:r,totalCostUsd:a}}catch(r){return _.warn("ai-incomplete-resolver failed",r),{type:"AI_RESOLVE_INCOMPLETE_RESPONSE",resolutions:[],totalCostUsd:0,unavailableReason:r instanceof Error?r.message:"Unknown error during AI resolution."}}})}function mt(){return g("INTERACTIVE_AUDIT_REQUEST",async e=>{try{switch(e.criterionId){case"2.4.3":{const t=await fe({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.1.2":{const t=await ue({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"2.4.7":{const t=await de({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl});return t.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:t.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t.error}}case"1.4.11":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first; 1.4.11 needs the page screenshot."};const n=await le({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"1.3.2":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=(r==null?void 0:r.results)??[];if(a.length===0)return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:"No audit results available. Run an audit first, then the 1.3.2 walkthrough can judge its reading-order findings."};const n=await ce({componentId:e.componentId,pageUrl:e.pageUrl,results:a});return n.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:n.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:n.error}}case"2.5.3":{const t=await chrome.storage.local.get("sidePanel:lastAudit"),r=t==null?void 0:t["sidePanel:lastAudit"],a=await ie({tabId:e.tabId,componentId:e.componentId,pageUrl:e.pageUrl,results:r==null?void 0:r.results});return a.ok?{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!0,result:a.result}:{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:a.error}}default:return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:`Interactive audit for criterion ${e.criterionId} not yet implemented.`}}}catch(t){return{type:"INTERACTIVE_AUDIT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}})}async function wt(){var t;if(typeof chrome>"u"||!((t=chrome.storage)!=null&&t.local))return C(void 0);const e=await chrome.storage.local.get("aiConfig");return C(e.aiConfig)}async function Rt(e){const t=await wt();if(!t.enabled||!t.apiKey)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[]};const r=x(t);if(!r.ok)return{findings:[],totalCostUsd:0,capExceeded:!1,errors:[`AI client unavailable: ${r.reason}`]};const a=r.client,n=L(t.costCapUsd),o=[],s=[],c=Math.max(1,t.maxCandidatesPerCheck??10);if(t.enabledChecks.altText){const d=e.figureAltTexts.slice(0,c);for(const l of d){if(!n.canCharge())break;try{const i=await a.judgeGenericLinkText({linkText:l.alt,surroundingText:`(This is an alt text on a PDF Figure tag, page ${l.pageNum}.)`});n.recordCharge(i.costUsd),i.verdict==="fail"&&i.confidence>=.6&&o.push({ruleId:"pdf-alt-text-not-descriptive",impact:"moderate",wcagCriterion:"1.1.1",description:`Figure on page ${l.pageNum} has alt text "${l.alt}" that doesn't describe the figure's content. ${i.reasoning} A screen-reader user hears the literal alt and gets no useful information about what the figure shows.`,failureSummary:'Replace generic alt text with a description of what the figure actually shows. For data charts: include the key data point. For decorative images: use alt="" so the screen reader skips them. PDF/UA-1 §7.4 / WCAG 1.1.1.'})}catch(i){s.push(`alt-text page ${l.pageNum}: ${i instanceof Error?i.message:String(i)}`)}}}else s.push("altText AI check disabled in user settings");if(t.enabledChecks.headings&&e.headings&&e.headings.length>0){const d=e.headings.slice(0,c);for(const l of d){if(!n.canCharge())break;try{const i=await a.judgeHeading({headingText:l.headingText,sectionContent:l.sectionContent});n.recordCharge(i.costUsd),i.verdict==="fail"&&i.confidence>=.6&&o.push({ruleId:"pdf-heading-not-descriptive",impact:"moderate",wcagCriterion:"2.4.6",description:`Heading on page ${l.pageNum} "${l.headingText}" doesn't describe the content of its section. ${i.reasoning} Screen-reader users navigating by heading hear titles that don't help them locate the section they want.`,failureSummary:`Rewrite the heading to describe what the section is about. "Section 1" → "Q3 financial summary." "More info" → "How to apply for benefits." Generic, recycled, or placeholder heading text wastes the SR user's heading-navigation feature.`})}catch(i){s.push(`heading page ${l.pageNum}: ${i instanceof Error?i.message:String(i)}`)}}}return{findings:o,totalCostUsd:n.state.spentUsd,capExceeded:n.state.exceeded,errors:s}}function At(e){return g("PDF_AUDIT_REQUEST",async t=>{const r=await e();if(!Ne(r,"pdfAudit"))return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF accessibility audit is not enabled on the ${r} tier. Upgrade or contact your admin to enable the pdfAudit feature.`};try{const a=await ge(t.url,{maxBytes:t.maxBytes});let n=[];if(a.aiCandidates)try{n=(await Rt(a.aiCandidates)).findings}catch{}return{type:"PDF_AUDIT_RESPONSE",ok:a.ok,source:a.source,findings:[...a.findings,...n],pageCount:a.pageCount,...a.fatalError?{fatalError:a.fatalError}:{},...a._perPageContrast?{_perPageContrast:a._perPageContrast}:{},...a.aiCandidates?{aiCandidates:a.aiCandidates}:{}}}catch(a){return{type:"PDF_AUDIT_RESPONSE",ok:!1,source:t.url,findings:[],pageCount:null,fatalError:`PDF audit handler threw: ${a instanceof Error?a.message:String(a)}`}}})}const yt=S("ax-tree-snapshot"),It="1.3";function _t(e){var r,a,n;const t=[];for(const o of e.properties??[]){const s=(r=o.value)==null?void 0:r.value;s!==void 0&&(typeof s=="string"||typeof s=="number"||typeof s=="boolean"||s===null)&&t.push({name:o.name,value:s})}return{nodeId:e.nodeId,parentId:e.parentId,childIds:e.childIds??[],role:typeof((a=e.role)==null?void 0:a.value)=="string"?e.role.value:"unknown",name:typeof((n=e.name)==null?void 0:n.value)=="string"?e.name.value:"",ignored:!!e.ignored,properties:t,backendDomNodeId:e.backendDOMNodeId}}async function Ct(e){let t=!1;try{try{await chrome.debugger.attach({tabId:e},It),t=!0}catch(n){if(!(n instanceof Error?n.message:String(n)).includes("Another debugger"))throw yt.warn("chrome.debugger.attach failed",n),n}await chrome.debugger.sendCommand({tabId:e},"Accessibility.enable");const r=await chrome.debugger.sendCommand({tabId:e},"Accessibility.getFullAXTree");return((r==null?void 0:r.nodes)??[]).map(_t)}finally{if(t)try{await chrome.debugger.detach({tabId:e})}catch{}}}const re=S("perf-throttle"),bt="1.3",Pt={none:{label:"No throttling",network:null,cpuRate:1},"3g-slow":{label:"Slow 3G",network:{offline:!1,latency:400,downloadThroughput:500*1024/8,uploadThroughput:500*1024/8},cpuRate:6},"3g-fast":{label:"Fast 3G",network:{offline:!1,latency:150,downloadThroughput:1.5*1024*1024/8,uploadThroughput:750*1024/8},cpuRate:4},"4g":{label:"4G LTE",network:{offline:!1,latency:20,downloadThroughput:4*1024*1024/8,uploadThroughput:3*1024*1024/8},cpuRate:2},"cpu-2x":{label:"CPU 2× slowdown (no network throttle)",network:null,cpuRate:2},"cpu-4x":{label:"CPU 4× slowdown (no network throttle)",network:null,cpuRate:4}};async function Ut(e){try{return await chrome.debugger.attach({tabId:e},bt),!0}catch(t){if((t instanceof Error?t.message:String(t)).includes("Another debugger"))return!1;throw t}}async function vt(e,t){const r=Pt[t];await Ut(e),await chrome.debugger.sendCommand({tabId:e},"Network.enable"),r.network?await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",r.network):await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:r.cpuRate}),re.info(`applied ${t} (label="${r.label}", cpu×${r.cpuRate})`)}async function Ot(e){try{await chrome.debugger.sendCommand({tabId:e},"Network.emulateNetworkConditions",{offline:!1,latency:0,downloadThroughput:-1,uploadThroughput:-1}),await chrome.debugger.sendCommand({tabId:e},"Emulation.setCPUThrottlingRate",{rate:1})}catch(t){re.debug("throttle reset commands failed (debugger may not be attached)",t)}}const f=S("service-worker");De("service-worker");pe();var A,q;(q=(A=chrome.sidePanel)==null?void 0:A.setPanelBehavior)==null||q.call(A,{openPanelOnActionClick:!0}).catch(e=>f.warn("setPanelBehavior failed",e));he();Ee();Se();Te().catch(e=>f.warn("initial cloud pull failed",e));(async()=>(await me(),await Je(),Z(),we(),Re(),Ae()))();chrome.alarms.onAlarm.addListener(e=>{const t=ye(e.name);t!==null&&Ie(t).catch(r=>f.warn(`scheduled audit ${t} threw at top level`,r))});Ze();_e();Ce();ct();ut();be();Tt();mt();At(X);self.addEventListener("unhandledrejection",e=>{const t=e.reason;Fe(t instanceof Error?t:new Error(String(t)))});let b=!1;chrome.runtime.onConnect.addListener(e=>{if(e.name==="audit-keepalive"){f.debug("keepalive connected"),e.onDisconnect.addListener(async()=>{f.debug("keepalive disconnected"),await Pe()});return}if(e.name==="sidepanel-tracker"){b=!0,f.debug("chrome.sidePanel opened"),e.onDisconnect.addListener(async()=>{b=!1,f.debug("chrome.sidePanel closed — restoring in-page overlay"),await F()});return}});let D=!1;const T={isCanceled:()=>D};async function ae(){const e=await P();if(e)try{await z(e,{type:"SIDEBAR_HIDE_REQUEST"})}catch(t){f.warn("sidebar hide failed",t)}}async function F(){const e=await P();if(e)try{await z(e,{type:"SIDEBAR_SHOW_REQUEST"})}catch(t){f.warn("sidebar show failed",t)}}g("START_AUDIT",async e=>{D=!1,await ae();const t=await P();let r;const a={verifyFixesOnly:e.verifyFixesOnly};if(e.mode==="single-element"){if(!e.scope)throw new Error("START_AUDIT single-element requires scope");r=O(e.scope,T,e.frameId,e.matrixOverride,a)}else if(e.mode==="full-page")r=O("html",T,0,e.matrixOverride,a);else if(e.mode==="quick-scan"){const{QUICK_SCAN_MATRIX_SETTINGS:n}=await H(async()=>{const{QUICK_SCAN_MATRIX_SETTINGS:o}=await import("./ai-usage-log-D5enikfX.js").then(s=>s.I);return{QUICK_SCAN_MATRIX_SETTINGS:o}},__vite__mapDeps([0,1]));r=O(e.scope??"html",T,e.frameId??0,n,a)}else if(e.mode==="all-frames")r=Ue(T);else if(e.mode==="parallel-scan"){const{runParallelScan:n}=await H(async()=>{const{runParallelScan:o}=await import("./scheduled-audit-runner-QcMYcqgA.js").then(s=>s.aU);return{runParallelScan:o}},__vite__mapDeps([2,3,1,0,4]));r=n(T)}else r=ve(T);r.catch(n=>{f.error("audit failed",n);const o=n instanceof Error?n.message:String(n),s=/no audit target tab/i.test(o);$e({type:"AUDIT_FAILED_EVENT",error:{code:s?"RESTRICTED_URL":"UNKNOWN",message:s?"No audit target tab found. Open a regular http(s) page (not chrome:// or about:blank) and try again.":`Audit failed: ${o}`,recoverable:!0}})}).finally(()=>{t!=null&&Y(t).catch(n=>f.debug("post-audit debugger release failed (best-effort)",n)),b||F()})});g("CANCEL_AUDIT",async()=>{D=!0,f.info("cancel requested")});let $=!1;const kt={isCanceled:()=>$};g("START_SITE_CRAWL",async e=>{$=!1,await ae();const t=await P();Oe(e.startUrl,{maxPages:e.maxPages,includeRegex:e.includeRegex,excludeRegex:e.excludeRegex,verifyFixesOnly:e.verifyFixesOnly},kt).catch(r=>f.error("site crawl failed",r)).finally(()=>{t!=null&&Y(t).catch(r=>f.debug("post-crawl debugger release failed (best-effort)",r)),b||F()})});g("CANCEL_SITE_CRAWL",async()=>{$=!0,f.info("site crawl cancel requested")});g("REGRADE_SITE_CRAWL",async()=>{try{const e=await ke();return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:e.ok,...e.reason?{reason:e.reason}:{}}}catch(e){return{type:"REGRADE_SITE_CRAWL_RESPONSE",ok:!1,reason:e instanceof Error?e.message:String(e)}}});g("OPEN_SETTINGS",()=>{chrome.runtime.openOptionsPage()});g("PERF_THROTTLE_APPLY_REQUEST",async e=>{try{return await vt(e.tabId,e.profile),{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_APPLY_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("PERF_THROTTLE_CLEAR_REQUEST",async e=>{try{return await Ot(e.tabId),{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!0}}catch(t){return{type:"PERF_THROTTLE_CLEAR_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});g("AX_TREE_SNAPSHOT_REQUEST",async e=>{try{return{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!0,nodes:await Ct(e.tabId)}}catch(t){return f.warn("ax-tree snapshot failed",t),{type:"AX_TREE_SNAPSHOT_RESPONSE",ok:!1,error:t instanceof Error?t.message:String(t)}}});f.info("service worker ready");
|