@wcag-checkr/ci 1.0.0-rc.98 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/ErrorBoundary-C_dGDDCo.js +594 -0
- package/dist/assets/ai-usage-log-CYyG5MT2.js +1 -0
- package/dist/assets/content-script.ts-DUFtdkRn.js +217 -0
- package/dist/assets/{content-script.ts-loader-BjJqq5Xq.js → content-script.ts-loader-BhZWdOHh.js} +1 -1
- package/dist/assets/copy-ai-fixer-prompt-B-MMXqXA.js +19 -0
- package/dist/assets/crash-reporter-KD5f4utB.js +4 -0
- package/dist/assets/design-system-audit-DpxJrxnb.js +1 -0
- package/dist/assets/devtools-panel-BmQF2Qi9.js +1 -0
- package/dist/assets/diff-RnwNJg4F.js +1 -0
- package/dist/assets/dom-criterion-analyzers-DoUaJV5C.js +8 -0
- package/dist/assets/fraunces-latin-400-normal-6IfK1voy.woff2 +0 -0
- package/dist/assets/fraunces-latin-400-normal-NUPT2cO8.woff +0 -0
- package/dist/assets/fraunces-latin-500-normal-BTR4KCeb.woff +0 -0
- package/dist/assets/fraunces-latin-500-normal-DnGCNyPD.woff2 +0 -0
- package/dist/assets/fraunces-latin-600-normal-BFCDtZfi.woff2 +0 -0
- package/dist/assets/fraunces-latin-600-normal-DL5QCzvS.woff +0 -0
- package/dist/assets/fraunces-latin-ext-400-normal-D8gbi3Gu.woff2 +0 -0
- package/dist/assets/fraunces-latin-ext-400-normal-UihxqfOe.woff +0 -0
- package/dist/assets/fraunces-latin-ext-500-normal-BMcFk1Xs.woff +0 -0
- package/dist/assets/fraunces-latin-ext-500-normal-Z5DV8IzT.woff2 +0 -0
- package/dist/assets/fraunces-latin-ext-600-normal-B0Dy4lqi.woff +0 -0
- package/dist/assets/fraunces-latin-ext-600-normal-BtzmzP0X.woff2 +0 -0
- package/dist/assets/fraunces-vietnamese-400-normal-B65MOf9T.woff +0 -0
- package/dist/assets/fraunces-vietnamese-400-normal-CvGt0Ybw.woff2 +0 -0
- package/dist/assets/fraunces-vietnamese-500-normal-B-KbxExq.woff +0 -0
- package/dist/assets/fraunces-vietnamese-500-normal-GOH_-EGq.woff2 +0 -0
- package/dist/assets/fraunces-vietnamese-600-normal-BjlAJixd.woff2 +0 -0
- package/dist/assets/fraunces-vietnamese-600-normal-DlAl5EAR.woff +0 -0
- package/dist/assets/geist-sans-latin-400-normal-BOaIZNA2.woff +0 -0
- package/dist/assets/geist-sans-latin-400-normal-gapTbOY8.woff2 +0 -0
- package/dist/assets/geist-sans-latin-500-normal-CN2lyvyL.woff +0 -0
- package/dist/assets/geist-sans-latin-500-normal-uokXdC-Q.woff2 +0 -0
- package/dist/assets/geist-sans-latin-600-normal-CA1yjETN.woff +0 -0
- package/dist/assets/geist-sans-latin-600-normal-DFOURf8L.woff2 +0 -0
- package/dist/assets/geist-sans-latin-700-normal-BmN9tIp5.woff2 +0 -0
- package/dist/assets/geist-sans-latin-700-normal-CjScfYeH.woff +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-400-normal-BEIGL1Tu.woff2 +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-400-normal-ugxPyKxw.woff +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-500-normal-DJqRU3vO.woff +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-500-normal-DmUKJPL_.woff2 +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-600-normal-8K4wrrwR.woff +0 -0
- package/dist/assets/jetbrains-mono-cyrillic-600-normal-EVf6-Yzo.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-400-normal-B9oWc5Lo.woff +0 -0
- package/dist/assets/jetbrains-mono-greek-400-normal-C190GLew.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-500-normal-D7SFKleX.woff +0 -0
- package/dist/assets/jetbrains-mono-greek-500-normal-JpySY46c.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-600-normal-H7WoG9Et.woff2 +0 -0
- package/dist/assets/jetbrains-mono-greek-600-normal-mc2nkWzM.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-400-normal-6-qcROiO.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-400-normal-V6pRDFza.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-500-normal-BWZEU5yA.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-500-normal-CJOVTJB7.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-600-normal-BfsvjouI.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-600-normal-C8RAYTDA.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-400-normal-Bc8Ftmh3.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-400-normal-fXTG6kC5.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-500-normal-Cut-4mMH.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-500-normal-ckzbgY84.woff +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-600-normal-BfB_LPfz.woff2 +0 -0
- package/dist/assets/jetbrains-mono-latin-ext-600-normal-DObL3zCW.woff +0 -0
- package/dist/assets/jetbrains-mono-vietnamese-400-normal-CqNFfHCs.woff +0 -0
- package/dist/assets/jetbrains-mono-vietnamese-500-normal-DNRqzVM1.woff +0 -0
- package/dist/assets/jetbrains-mono-vietnamese-600-normal-OWROknRo.woff +0 -0
- package/dist/assets/offscreen-BAvM-6sh.js +1 -0
- package/dist/assets/options-D_6nRFjj.js +6 -0
- package/dist/assets/parallel-tab-flow-DjD6Nlor.js +1 -0
- package/dist/assets/pdf-DfaD4CCm.js +13 -0
- package/dist/assets/pdf.worker-B4IDxXWI.js +1 -0
- package/dist/assets/pdf.worker-ByF8NTMy.mjs +62201 -0
- package/dist/assets/rubric-config-client-DvjbA4nG.js +1 -0
- package/dist/assets/scheduled-audit-runner-ZCuDk8-r.js +2019 -0
- package/dist/assets/service-worker.ts-CvO1EqpM.js +2 -0
- package/dist/assets/side-panel-Cq-w2yTn.css +1 -0
- package/dist/assets/side-panel-DaVp_XgU.js +4 -0
- package/dist/assets/site-report-renderer-MWuVmKOh.js +248 -0
- package/dist/assets/styles-BJICDw6s.css +1 -0
- package/dist/assets/{styles-DhnON7zr.js → styles-B_kTykZT.js} +12 -12
- package/dist/assets/tier-config-client-85XOCE5d.js +1 -0
- package/dist/assets/zip-encoder-CtULHXx_.js +1 -0
- package/dist/devtools/panel.html +9 -7
- package/dist/manifest.json +10 -11
- package/dist/offscreen/offscreen.html +12 -0
- package/dist/options/options.html +6 -6
- package/dist/service-worker-loader.js +1 -1
- package/dist/side-panel/side-panel.html +13 -7
- package/package.json +2 -1
- package/wcagcheckr-ci.mjs +238 -39
- package/dist/assets/ErrorBoundary-C2WBadbU.js +0 -544
- package/dist/assets/ai-usage-log-Dj9Ub_DT.js +0 -1
- package/dist/assets/content-script.ts-vGsvD70K.js +0 -181
- package/dist/assets/copy-ai-fixer-prompt-DDYcXAe7.js +0 -19
- package/dist/assets/crash-reporter-Dc5lvxvY.js +0 -4
- package/dist/assets/devtools-panel-CSy65hq-.js +0 -1
- package/dist/assets/diff-DIBMr3fQ.js +0 -1
- package/dist/assets/dom-criterion-analyzers-C2gMp3xS.js +0 -1
- package/dist/assets/forensic-log-D-KXUwm8.js +0 -129
- package/dist/assets/options-Byz5A0JD.js +0 -6
- package/dist/assets/parallel-tab-flow-BUjkjlHH.js +0 -1
- package/dist/assets/service-worker.ts-DwSYhM1S.js +0 -954
- package/dist/assets/side-panel-DIo5JGlH.js +0 -1
- package/dist/assets/site-report-renderer-D8y25osg.js +0 -147
- package/dist/assets/state-BIsozXtc.js +0 -1
- package/dist/assets/styles-Bh3rgVbO.css +0 -1
- package/dist/side-panel/App.tsx +0 -193
- package/dist/side-panel/README.md +0 -57
- package/dist/side-panel/audit-launcher.test.ts +0 -56
- package/dist/side-panel/audit-launcher.ts +0 -65
- package/dist/side-panel/format-component-id.test.ts +0 -89
- package/dist/side-panel/format-component-id.ts +0 -40
- package/dist/side-panel/github-issue.test.ts +0 -102
- package/dist/side-panel/github-issue.ts +0 -66
- package/dist/side-panel/jira-issue.ts +0 -64
- package/dist/side-panel/main.tsx +0 -19
- package/dist/side-panel/store.ts +0 -289
- package/dist/side-panel/styles.css +0 -16
- package/dist/side-panel/wire-messaging.test.ts +0 -202
- package/dist/side-panel/wire-messaging.ts +0 -288
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{x as c,C as f,E as h,F as l,G as d,H as p}from"./ai-usage-log-CYyG5MT2.js";import{q as i,c as u,T as s}from"./crash-reporter-KD5f4utB.js";const o=u("tier-config-client"),w="wcagcheckr",T=`https://api.wcagcheckr.com/v1/products/${w}/tier-config`,m=1e4,n="tier-config-refresh",C=60,E=["free","solo","team"];function g(e){const t={};for(const r of E){const a=d(r,e);t[r]=a?p(s[r],a):{...s[r]}}return t}async function _(){const e=await c();if(!e){i(null);return}if(f(e)==="expired"){o.warn("cached tier-config is expired (>7d); using hardcoded defaults"),i(null);return}i(g(e.config))}async function I(){const e=await c();return!!e&&f(e)!=="expired"}async function R(){try{const e=await fetch(T,{signal:AbortSignal.timeout(m),headers:{accept:"application/json"}});if(!e.ok)throw new Error(`http ${e.status}`);const t=await e.json();await h({fetchedAt:Date.now(),config:t}),i(g(t));const r=t.wcagTargetVersion;if(r==="2.1"||r==="2.2")try{await chrome.storage.local.set({wcagTargetVersion:r}),l(r)}catch(a){o.warn("failed to persist wcagTargetVersion",a)}o.info("tier-config refreshed from server")}catch(e){o.warn("tier-config refresh failed; keeping prior cache",e)}}function A(){chrome.alarms.create(n,{periodInMinutes:C}),chrome.alarms.onAlarm.addListener(e=>{e.name===n&&R()})}export{A as a,I as h,R as r,_ as w};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const A=new Uint32Array(256);for(let t=0;t<256;t++){let n=t;for(let o=0;o<8;o++)n=n&1?3988292384^n>>>1:n>>>1;A[t]=n>>>0}function M(t){let n=4294967295;for(let o=0;o<t.length;o++)n=A[(n^t[o])&255]^n>>>8;return(n^4294967295)>>>0}function w(t){return new TextEncoder().encode(t)}function e(t){return new Uint8Array([t&255,t>>>8&255])}function c(t){return new Uint8Array([t&255,t>>>8&255,t>>>16&255,t>>>24&255])}function p(t){let n=0;for(const l of t)n+=l.length;const o=new Uint8Array(n);let s=0;for(const l of t)o.set(l,s),s+=l.length;return o}function T(t){const o=Math.max(1980,t.getFullYear())-1980<<9|t.getMonth()+1<<5|t.getDate(),s=t.getHours()<<11|t.getMinutes()<<5|Math.floor(t.getSeconds()/2);return{date:o,time:s}}function b(t,n=new Date){const{date:o,time:s}=T(n),l=[],i=[];let h=0;for(const r of t){const f=w(r.name),g=r.bytes??w(r.content??""),d=M(g),u=g.length,m=p([c(67324752),e(20),e(2048),e(0),e(s),e(o),c(d),c(u),c(u),e(f.length),e(0),f,g]);l.push(m);const D=p([c(33639248),e(798),e(20),e(2048),e(0),e(s),e(o),c(d),c(u),c(u),e(f.length),e(0),e(0),e(0),e(0),c(0),c(h),f]);i.push(D),h+=m.length}const U=h;let y=0;for(const r of i)y+=r.length;const B=p([c(101010256),e(0),e(0),e(t.length),e(t.length),c(y),c(U),e(0)]),a=[];for(const r of l)a.push(r);for(const r of i)a.push(r);return a.push(B),new Blob(a,{type:"application/zip"})}export{b as createZip};
|
package/dist/devtools/panel.html
CHANGED
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<title>wcagcheckr</title>
|
|
6
|
-
<script type="module" crossorigin src="/assets/devtools-panel-
|
|
6
|
+
<script type="module" crossorigin src="/assets/devtools-panel-BmQF2Qi9.js"></script>
|
|
7
7
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/_commonjsHelpers-Cpj98o6Y.js">
|
|
9
|
-
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/styles-
|
|
9
|
+
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-KD5f4utB.js">
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/ai-usage-log-CYyG5MT2.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/styles-B_kTykZT.js">
|
|
12
12
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-D7HrI6pR.js">
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
15
|
-
<link rel="
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/diff-RnwNJg4F.js">
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/scheduled-audit-runner-ZCuDk8-r.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/design-system-audit-DpxJrxnb.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/ErrorBoundary-C_dGDDCo.js">
|
|
17
|
+
<link rel="stylesheet" crossorigin href="/assets/styles-BJICDw6s.css">
|
|
16
18
|
</head>
|
|
17
19
|
<body class="bg-slate-50">
|
|
18
20
|
<div id="root"></div>
|
package/dist/manifest.json
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest_version": 3,
|
|
3
3
|
"name": "wcagcheckr",
|
|
4
|
-
"description": "Audit
|
|
5
|
-
"version": "1.0.0
|
|
6
|
-
"version_name": "1.0.0-rc.98",
|
|
4
|
+
"description": "Audit your real site for WCAG issues across hover, focus, dark mode & RTL states — baselines surface only NEW violations.",
|
|
5
|
+
"version": "1.0.0",
|
|
7
6
|
"author": "Locustware",
|
|
8
7
|
"homepage_url": "https://wcagcheckr.com",
|
|
9
8
|
"icons": {
|
|
@@ -15,12 +14,12 @@
|
|
|
15
14
|
"permissions": [
|
|
16
15
|
"debugger",
|
|
17
16
|
"storage",
|
|
17
|
+
"unlimitedStorage",
|
|
18
18
|
"sidePanel",
|
|
19
19
|
"scripting",
|
|
20
20
|
"tabs",
|
|
21
21
|
"alarms",
|
|
22
|
-
"
|
|
23
|
-
"declarativeNetRequestWithHostAccess",
|
|
22
|
+
"downloads",
|
|
24
23
|
"offscreen"
|
|
25
24
|
],
|
|
26
25
|
"host_permissions": [
|
|
@@ -38,7 +37,7 @@
|
|
|
38
37
|
"content_scripts": [
|
|
39
38
|
{
|
|
40
39
|
"js": [
|
|
41
|
-
"assets/content-script.ts-loader-
|
|
40
|
+
"assets/content-script.ts-loader-BhZWdOHh.js"
|
|
42
41
|
],
|
|
43
42
|
"matches": [
|
|
44
43
|
"<all_urls>"
|
|
@@ -57,18 +56,18 @@
|
|
|
57
56
|
],
|
|
58
57
|
"resources": [
|
|
59
58
|
"side-panel/side-panel.html",
|
|
60
|
-
"side-panel/*",
|
|
61
59
|
"assets/*",
|
|
62
60
|
"fonts/*",
|
|
63
61
|
"axe.min.js",
|
|
64
62
|
"assets/preload-helper-D7HrI6pR.js",
|
|
65
|
-
"assets/crash-reporter-
|
|
66
|
-
"assets/diff-
|
|
63
|
+
"assets/crash-reporter-KD5f4utB.js",
|
|
64
|
+
"assets/diff-RnwNJg4F.js",
|
|
67
65
|
"assets/_commonjsHelpers-Cpj98o6Y.js",
|
|
68
66
|
"assets/custom-rules-CAe0nbES.js",
|
|
67
|
+
"assets/design-system-audit-DpxJrxnb.js",
|
|
69
68
|
"assets/reflow-analyzer-DNgBX8N_.js",
|
|
70
|
-
"assets/dom-criterion-analyzers-
|
|
71
|
-
"assets/content-script.ts-
|
|
69
|
+
"assets/dom-criterion-analyzers-DoUaJV5C.js",
|
|
70
|
+
"assets/content-script.ts-DUFtdkRn.js"
|
|
72
71
|
],
|
|
73
72
|
"use_dynamic_url": false
|
|
74
73
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<title>wcagcheckr offscreen worker</title>
|
|
6
|
+
<script type="module" crossorigin src="/assets/offscreen-BAvM-6sh.js"></script>
|
|
7
|
+
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
8
|
+
<link rel="modulepreload" crossorigin href="/assets/preload-helper-D7HrI6pR.js">
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
</body>
|
|
12
|
+
</html>
|
|
@@ -4,15 +4,15 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>wcagcheckr — Settings</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/options-
|
|
7
|
+
<script type="module" crossorigin src="/assets/options-D_6nRFjj.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/_commonjsHelpers-Cpj98o6Y.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/styles-
|
|
13
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-KD5f4utB.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/ai-usage-log-CYyG5MT2.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/styles-B_kTykZT.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/tier-config-client-85XOCE5d.js">
|
|
14
14
|
<link rel="modulepreload" crossorigin href="/assets/custom-rules-CAe0nbES.js">
|
|
15
|
-
<link rel="stylesheet" crossorigin href="/assets/styles-
|
|
15
|
+
<link rel="stylesheet" crossorigin href="/assets/styles-BJICDw6s.css">
|
|
16
16
|
</head>
|
|
17
17
|
<body class="m-0 p-0 bg-slate-50">
|
|
18
18
|
<div id="root"></div>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import './assets/service-worker.ts-
|
|
1
|
+
import './assets/service-worker.ts-CvO1EqpM.js';
|
|
@@ -4,16 +4,22 @@
|
|
|
4
4
|
<meta charset="UTF-8" />
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
6
|
<title>WCAG Component Auditor</title>
|
|
7
|
-
<script type="module" crossorigin src="/assets/side-panel-
|
|
7
|
+
<script type="module" crossorigin src="/assets/side-panel-DaVp_XgU.js"></script>
|
|
8
8
|
<link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
|
|
9
9
|
<link rel="modulepreload" crossorigin href="/assets/_commonjsHelpers-Cpj98o6Y.js">
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-
|
|
11
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
12
|
-
<link rel="modulepreload" crossorigin href="/assets/styles-
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/crash-reporter-KD5f4utB.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/ai-usage-log-CYyG5MT2.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/styles-B_kTykZT.js">
|
|
13
13
|
<link rel="modulepreload" crossorigin href="/assets/preload-helper-D7HrI6pR.js">
|
|
14
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
15
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
16
|
-
<link rel="
|
|
14
|
+
<link rel="modulepreload" crossorigin href="/assets/diff-RnwNJg4F.js">
|
|
15
|
+
<link rel="modulepreload" crossorigin href="/assets/scheduled-audit-runner-ZCuDk8-r.js">
|
|
16
|
+
<link rel="modulepreload" crossorigin href="/assets/design-system-audit-DpxJrxnb.js">
|
|
17
|
+
<link rel="modulepreload" crossorigin href="/assets/ErrorBoundary-C_dGDDCo.js">
|
|
18
|
+
<link rel="modulepreload" crossorigin href="/assets/copy-ai-fixer-prompt-B-MMXqXA.js">
|
|
19
|
+
<link rel="modulepreload" crossorigin href="/assets/tier-config-client-85XOCE5d.js">
|
|
20
|
+
<link rel="modulepreload" crossorigin href="/assets/rubric-config-client-DvjbA4nG.js">
|
|
21
|
+
<link rel="stylesheet" crossorigin href="/assets/styles-BJICDw6s.css">
|
|
22
|
+
<link rel="stylesheet" crossorigin href="/assets/side-panel-Cq-w2yTn.css">
|
|
17
23
|
</head>
|
|
18
24
|
<body class="m-0 p-0">
|
|
19
25
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wcag-checkr/ci",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
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",
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
"node": ">=20.18"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
+
"pdfjs-dist": "^4.10.38",
|
|
24
25
|
"playwright": "^1.59.1"
|
|
25
26
|
},
|
|
26
27
|
"repository": {
|
package/wcagcheckr-ci.mjs
CHANGED
|
@@ -68,6 +68,10 @@ function parseArgs(argv) {
|
|
|
68
68
|
args.inputFile = a;
|
|
69
69
|
continue;
|
|
70
70
|
}
|
|
71
|
+
if (args.command === 'pdf' && !args.pdfTarget && !a.startsWith('--')) {
|
|
72
|
+
args.pdfTarget = a;
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
71
75
|
if (a === '--format') args.format = argv[++i];
|
|
72
76
|
else if (a === '--output') args.output = argv[++i];
|
|
73
77
|
else if (a === '--threshold') args.threshold = argv[++i];
|
|
@@ -76,6 +80,9 @@ function parseArgs(argv) {
|
|
|
76
80
|
else if (a === '--quiet') args.quiet = true;
|
|
77
81
|
else if (a === '--license') args.license = argv[++i];
|
|
78
82
|
else if (a === '--public-key-url') args.publicKeyUrl = argv[++i];
|
|
83
|
+
else if (a === '--watch') args.watch = true;
|
|
84
|
+
else if (a === '--watch-dir') args.watchDir = argv[++i];
|
|
85
|
+
else if (a === '--watch-debounce') args.watchDebounce = parseInt(argv[++i], 10);
|
|
79
86
|
else if (a === '--help' || a === '-h') args.help = true;
|
|
80
87
|
}
|
|
81
88
|
return args;
|
|
@@ -87,6 +94,13 @@ function printUsage() {
|
|
|
87
94
|
Usage:
|
|
88
95
|
wcagcheckr-ci audit <url> [options]
|
|
89
96
|
wcagcheckr-ci verify <forensic-log.json> [options]
|
|
97
|
+
wcagcheckr-ci pdf <path-or-url> [options]
|
|
98
|
+
|
|
99
|
+
pdf options:
|
|
100
|
+
--output <file> Write JSON report to file
|
|
101
|
+
--threshold <none|critical|serious|moderate|minor>
|
|
102
|
+
Severity gate for non-zero exit
|
|
103
|
+
--quiet Suppress progress output
|
|
90
104
|
|
|
91
105
|
audit options:
|
|
92
106
|
--format <json|sarif|junit> Output format (default: json)
|
|
@@ -97,6 +111,12 @@ audit options:
|
|
|
97
111
|
--timeout <ms> Audit timeout (default: 120000)
|
|
98
112
|
--license <token> Activate this license token before auditing
|
|
99
113
|
(gates paid features like forensic anchoring)
|
|
114
|
+
--watch Stay open after the initial audit and re-run
|
|
115
|
+
whenever a file under --watch-dir changes
|
|
116
|
+
--watch-dir <path> Directory to watch when --watch is on
|
|
117
|
+
(default: current working directory)
|
|
118
|
+
--watch-debounce <ms> Debounce window after a change before
|
|
119
|
+
re-auditing (default: 1500)
|
|
100
120
|
--quiet Suppress progress output
|
|
101
121
|
|
|
102
122
|
verify options:
|
|
@@ -137,6 +157,52 @@ if (args.command === 'verify') {
|
|
|
137
157
|
// runVerify exits the process itself.
|
|
138
158
|
}
|
|
139
159
|
|
|
160
|
+
// ─── pdf subcommand (rc.153, G3) ────────────────────────────────────────────
|
|
161
|
+
//
|
|
162
|
+
// Metadata-level PDF accessibility audit. No page rendering — checks
|
|
163
|
+
// the document Catalog for tagged status, document language, title,
|
|
164
|
+
// structure-tree root. The #1 PDF accessibility failure (untagged) is
|
|
165
|
+
// catchable at this level.
|
|
166
|
+
|
|
167
|
+
if (args.command === 'pdf') {
|
|
168
|
+
if (!args.pdfTarget) {
|
|
169
|
+
console.error('✗ pdf: missing PDF path or URL.\n');
|
|
170
|
+
printUsage();
|
|
171
|
+
process.exit(2);
|
|
172
|
+
}
|
|
173
|
+
const { auditPdfFile, auditPdfUrl } = await import('./pdf-audit.mjs');
|
|
174
|
+
const isUrl = /^https?:\/\//.test(args.pdfTarget);
|
|
175
|
+
log(`auditing PDF metadata for ${args.pdfTarget}`);
|
|
176
|
+
const result = isUrl
|
|
177
|
+
? await auditPdfUrl(args.pdfTarget)
|
|
178
|
+
: await auditPdfFile(args.pdfTarget);
|
|
179
|
+
if (!result.ok) {
|
|
180
|
+
console.error(`✗ ${result.fatalError ?? 'PDF audit failed.'}`);
|
|
181
|
+
process.exit(2);
|
|
182
|
+
}
|
|
183
|
+
if (args.output) {
|
|
184
|
+
const { writeFileSync } = await import('node:fs');
|
|
185
|
+
writeFileSync(args.output, JSON.stringify(result, null, 2), 'utf8');
|
|
186
|
+
log(`output written to ${args.output}`);
|
|
187
|
+
} else {
|
|
188
|
+
process.stdout.write(JSON.stringify(result, null, 2));
|
|
189
|
+
process.stdout.write('\n');
|
|
190
|
+
}
|
|
191
|
+
const exceeds = args.threshold === 'none'
|
|
192
|
+
? false
|
|
193
|
+
: result.findings.some((f) => {
|
|
194
|
+
const rank = SEVERITY_RANK[f.impact];
|
|
195
|
+
const cap = SEVERITY_RANK[args.threshold];
|
|
196
|
+
return rank <= cap;
|
|
197
|
+
});
|
|
198
|
+
log(
|
|
199
|
+
`${result.findings.length} finding${result.findings.length === 1 ? '' : 's'} ` +
|
|
200
|
+
`(version ${result.version ?? '?'}, tagged=${result.metadata?.tagged ?? '?'}, ` +
|
|
201
|
+
`lang=${result.metadata?.lang ?? '?'}, title=${result.metadata?.title ? 'yes' : 'no'})`,
|
|
202
|
+
);
|
|
203
|
+
process.exit(exceeds ? 1 : 0);
|
|
204
|
+
}
|
|
205
|
+
|
|
140
206
|
if (args.command !== 'audit' || !args.url) {
|
|
141
207
|
console.error(`✗ Unknown command or missing URL.\n`);
|
|
142
208
|
printUsage();
|
|
@@ -162,6 +228,9 @@ if (!['none', 'critical', 'serious', 'moderate', 'minor'].includes(args.threshol
|
|
|
162
228
|
|
|
163
229
|
log(`Loading extension from ${EXT_DIR}`);
|
|
164
230
|
log(`Auditing ${args.url} (threshold: ${args.threshold}, format: ${args.format})`);
|
|
231
|
+
if (args.watch) {
|
|
232
|
+
log(`watch mode ON — re-audits on file changes under ${args.watchDir ?? process.cwd()}`);
|
|
233
|
+
}
|
|
165
234
|
|
|
166
235
|
// Chrome extensions cannot load in legacy `headless: true` mode, so we
|
|
167
236
|
// pass `--headless=new` as a Chromium arg (the modern headless mode that
|
|
@@ -179,8 +248,10 @@ const context = await chromium.launchPersistentContext('', {
|
|
|
179
248
|
});
|
|
180
249
|
|
|
181
250
|
let exitCode = 0;
|
|
251
|
+
let targetPage;
|
|
252
|
+
let sidePanel;
|
|
182
253
|
try {
|
|
183
|
-
|
|
254
|
+
[targetPage] = context.pages();
|
|
184
255
|
await targetPage.goto(args.url, { waitUntil: 'domcontentloaded', timeout: 30_000 });
|
|
185
256
|
log('target page loaded');
|
|
186
257
|
|
|
@@ -193,38 +264,69 @@ try {
|
|
|
193
264
|
if (!extId) throw new Error('extension SW did not register within 10s');
|
|
194
265
|
log(`extension loaded (id: ${extId.slice(0, 8)}…)`);
|
|
195
266
|
|
|
196
|
-
|
|
267
|
+
sidePanel = await context.newPage();
|
|
197
268
|
await sidePanel.goto(`chrome-extension://${extId}/side-panel/side-panel.html`);
|
|
198
269
|
|
|
199
|
-
//
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
270
|
+
// rc.380 — Set dev mode explicitly. The persona wizard was removed in rc.333;
|
|
271
|
+
// the default persona is owner, which has no audit controls. Set userMode in
|
|
272
|
+
// storage and reload so the dev surface renders, then wait for the audit-mode
|
|
273
|
+
// select (the reliable dev-ready signal; the old "wcagcheckr" h1 moved).
|
|
274
|
+
await sidePanel.evaluate(() => chrome.storage.local.set({ userMode: 'dev', v2UiEnabled: false }));
|
|
275
|
+
await sidePanel.reload({ waitUntil: 'load' });
|
|
276
|
+
await sidePanel.waitForTimeout(500);
|
|
277
|
+
for (let i = 0; i < 5; i++) {
|
|
278
|
+
const gotIt = sidePanel.getByRole('button', { name: 'Got it' });
|
|
279
|
+
const next = sidePanel.getByRole('button', { name: 'Next' });
|
|
280
|
+
if (await gotIt.isVisible({ timeout: 400 }).catch(() => false)) { await gotIt.click(); break; }
|
|
281
|
+
if (await next.isVisible({ timeout: 400 }).catch(() => false)) { await next.click(); await sidePanel.waitForTimeout(120); continue; }
|
|
282
|
+
break;
|
|
204
283
|
}
|
|
205
|
-
await sidePanel.waitForSelector('
|
|
206
|
-
|
|
207
|
-
//
|
|
208
|
-
//
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
284
|
+
await sidePanel.waitForSelector('select[aria-label="Audit mode"]', { timeout: 10_000 });
|
|
285
|
+
|
|
286
|
+
// rc.124 — Headless-build lockdown gate. A team license is required to
|
|
287
|
+
// run audits during the private build phase. If --license is omitted
|
|
288
|
+
// OR validates to a non-team tier, refuse before doing any audit work.
|
|
289
|
+
if (!args.license) {
|
|
290
|
+
throw new Error(
|
|
291
|
+
'wcagcheckr is in private build phase. A team license is required to use the CLI. ' +
|
|
292
|
+
'Pass --license <token>. Email cliff@locustware.com for beta access.',
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
log('activating license token');
|
|
296
|
+
const activated = await sidePanel.evaluate(
|
|
297
|
+
async (token) =>
|
|
298
|
+
await new Promise((resolve) => {
|
|
299
|
+
chrome.runtime.sendMessage(
|
|
300
|
+
{ type: 'LICENSE_SET_REQUEST', token },
|
|
301
|
+
(response) => resolve(response ?? null),
|
|
302
|
+
);
|
|
303
|
+
}),
|
|
304
|
+
args.license,
|
|
305
|
+
);
|
|
306
|
+
if (!activated || !activated.validated) {
|
|
307
|
+
throw new Error(
|
|
308
|
+
`license activation failed — got ${JSON.stringify(activated)}`,
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
// Per the headless-build strategy, only team-tier licenses can use the CLI.
|
|
312
|
+
// At launch this constraint relaxes per per-feature tier mapping.
|
|
313
|
+
if (activated.tier !== 'team') {
|
|
314
|
+
throw new Error(
|
|
315
|
+
`wcagcheckr CLI requires a team-tier license during private build (got tier='${activated.tier}'). ` +
|
|
316
|
+
'Email cliff@locustware.com for beta access.',
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
// rc.342 — Per-feature tier gate. The lockdown above is the launch-flip
|
|
320
|
+
// kill-switch; this is the canonical per-feature gate post-launch.
|
|
321
|
+
// `features.cliRunner === false` blocks; undefined falls through as
|
|
322
|
+
// "permissive default" (matches the extension's behavior).
|
|
323
|
+
if (activated.features && activated.features.cliRunner === false) {
|
|
324
|
+
throw new Error(
|
|
325
|
+
`wcagcheckr CLI is not available on your current plan (tier='${activated.tier}'). ` +
|
|
326
|
+
'Upgrade your plan at https://wcagcheckr.com/pricing.',
|
|
220
327
|
);
|
|
221
|
-
if (!activated || activated.tier === 'free') {
|
|
222
|
-
throw new Error(
|
|
223
|
-
`license activation did not yield a paid tier — got ${JSON.stringify(activated)}`,
|
|
224
|
-
);
|
|
225
|
-
}
|
|
226
|
-
log(`license active — tier: ${activated.tier}`);
|
|
227
328
|
}
|
|
329
|
+
log(`license active — tier: ${activated.tier}`);
|
|
228
330
|
|
|
229
331
|
// Skip onboarding tour
|
|
230
332
|
for (let i = 0; i < 5; i++) {
|
|
@@ -242,21 +344,63 @@ try {
|
|
|
242
344
|
break;
|
|
243
345
|
}
|
|
244
346
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
347
|
+
// The per-audit work: navigate target (re-load on subsequent runs to
|
|
348
|
+
// pick up code changes), kick off the scan, wait for completion, export,
|
|
349
|
+
// print, threshold-check. Returns the exit code that THIS audit pass
|
|
350
|
+
// should produce — the watch loop overall stays at 0 until Ctrl+C.
|
|
351
|
+
async function runOneAudit() {
|
|
352
|
+
// On re-runs, navigate the target page again so it picks up source
|
|
353
|
+
// changes (assumes the dev server hot-reloads or the URL serves fresh
|
|
354
|
+
// content).
|
|
355
|
+
await targetPage.bringToFront();
|
|
356
|
+
await targetPage.reload({ waitUntil: 'domcontentloaded', timeout: 30_000 });
|
|
357
|
+
await targetPage.waitForTimeout(500);
|
|
358
|
+
await sidePanel.bringToFront();
|
|
359
|
+
await sidePanel.waitForTimeout(300);
|
|
360
|
+
|
|
361
|
+
await sidePanel.getByLabel('Audit mode').selectOption('full-page');
|
|
362
|
+
// rc.380 — Arm the completion listener BEFORE clicking. The post-audit
|
|
363
|
+
// summary text the CLI used to poll for ("N states · M unique violations")
|
|
364
|
+
// was removed in the rc.313–320 UI rebuild; AUDIT_COMPLETE_EVENT is the
|
|
365
|
+
// UI-independent signal the side panel itself listens for.
|
|
366
|
+
await sidePanel.evaluate(() => {
|
|
367
|
+
globalThis.__cliAuditOutcome = new Promise((res) => {
|
|
368
|
+
const l = (m) => {
|
|
369
|
+
if (m?.type === 'AUDIT_COMPLETE_EVENT') { chrome.runtime.onMessage.removeListener(l); res('completed'); }
|
|
370
|
+
else if (m?.type === 'AUDIT_FAILED_EVENT') { chrome.runtime.onMessage.removeListener(l); res('failed'); }
|
|
371
|
+
};
|
|
372
|
+
chrome.runtime.onMessage.addListener(l);
|
|
373
|
+
});
|
|
374
|
+
});
|
|
375
|
+
await sidePanel.getByRole('button', { name: /Scan page|Auditing/ }).click();
|
|
376
|
+
log('audit started');
|
|
377
|
+
|
|
378
|
+
const outcome = await sidePanel.evaluate(
|
|
379
|
+
(ms) => Promise.race([
|
|
380
|
+
globalThis.__cliAuditOutcome,
|
|
381
|
+
new Promise((r) => setTimeout(() => r('timeout'), ms)),
|
|
382
|
+
]),
|
|
383
|
+
args.timeout,
|
|
384
|
+
);
|
|
385
|
+
if (outcome !== 'completed') {
|
|
386
|
+
throw new Error(`audit did not complete (${outcome}) within ${args.timeout}ms`);
|
|
387
|
+
}
|
|
388
|
+
log('audit completed');
|
|
252
389
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
390
|
+
return await collectResults();
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Result-export + threshold-check, extracted so runOneAudit returns the
|
|
394
|
+
// exit code suggestion. Closure over `args`, `sidePanel`, etc.
|
|
395
|
+
async function collectResults() {
|
|
396
|
+
return await doExportAndThresholdCheck();
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
await runOneAudit();
|
|
257
400
|
|
|
258
401
|
// Trigger the existing export pipeline. The SW handles EXPORT_REQUEST and
|
|
259
402
|
// returns the formatted content for the requested format.
|
|
403
|
+
async function doExportAndThresholdCheck() {
|
|
260
404
|
const formatMap = { json: 'json', sarif: 'sarif', junit: 'junit' };
|
|
261
405
|
const exportFormat = formatMap[args.format];
|
|
262
406
|
|
|
@@ -340,6 +484,61 @@ try {
|
|
|
340
484
|
log(`✓ threshold not exceeded (--threshold=${args.threshold})`);
|
|
341
485
|
}
|
|
342
486
|
}
|
|
487
|
+
} // end doExportAndThresholdCheck
|
|
488
|
+
|
|
489
|
+
// Watch mode: keep the browser open, watch the directory tree, re-audit
|
|
490
|
+
// on change (debounced). Ctrl+C exits.
|
|
491
|
+
if (args.watch) {
|
|
492
|
+
const watchDir = args.watchDir ?? process.cwd();
|
|
493
|
+
const debounceMs = args.watchDebounce ?? 1500;
|
|
494
|
+
const { watch } = await import('node:fs');
|
|
495
|
+
log(`watching ${watchDir} (debounce ${debounceMs}ms) — Ctrl+C to exit`);
|
|
496
|
+
let pending = false;
|
|
497
|
+
let inFlight = false;
|
|
498
|
+
let runCount = 1;
|
|
499
|
+
function trigger() {
|
|
500
|
+
if (inFlight) {
|
|
501
|
+
pending = true;
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
504
|
+
inFlight = true;
|
|
505
|
+
setTimeout(async () => {
|
|
506
|
+
try {
|
|
507
|
+
runCount++;
|
|
508
|
+
log(`\n── Re-audit #${runCount} ──`);
|
|
509
|
+
await runOneAudit();
|
|
510
|
+
if (pending) {
|
|
511
|
+
pending = false;
|
|
512
|
+
inFlight = false;
|
|
513
|
+
trigger();
|
|
514
|
+
} else {
|
|
515
|
+
inFlight = false;
|
|
516
|
+
}
|
|
517
|
+
} catch (err) {
|
|
518
|
+
log(`re-audit failed: ${err.message}`);
|
|
519
|
+
inFlight = false;
|
|
520
|
+
}
|
|
521
|
+
}, debounceMs);
|
|
522
|
+
}
|
|
523
|
+
try {
|
|
524
|
+
watch(watchDir, { recursive: true }, (eventType, filename) => {
|
|
525
|
+
// Skip noise: node_modules, dist artifacts, .git, dotfiles other
|
|
526
|
+
// than the typical source files.
|
|
527
|
+
if (!filename) return;
|
|
528
|
+
const f = String(filename);
|
|
529
|
+
if (f.includes('node_modules')) return;
|
|
530
|
+
if (f.includes('.git')) return;
|
|
531
|
+
if (f.includes('/dist/') || f.startsWith('dist/') || f.includes('\\dist\\') || f.startsWith('dist\\')) return;
|
|
532
|
+
log(`change: ${f}`);
|
|
533
|
+
trigger();
|
|
534
|
+
});
|
|
535
|
+
} catch (err) {
|
|
536
|
+
log(`fs.watch failed (recursive may not be supported on this platform): ${err.message}`);
|
|
537
|
+
log('watch mode disabled; exiting after this audit.');
|
|
538
|
+
}
|
|
539
|
+
// Block forever until the user kills the process.
|
|
540
|
+
await new Promise(() => {});
|
|
541
|
+
}
|
|
343
542
|
} catch (err) {
|
|
344
543
|
console.error(`✗ ${err.message}`);
|
|
345
544
|
if (err.stack && !args.quiet) console.error(err.stack);
|