@binclusive/a11y 0.1.0 → 0.1.2
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/README.md +25 -13
- package/package.json +8 -3
- package/src/cli.ts +338 -104
- package/src/collect-android-xml.ts +447 -0
- package/src/contract.ts +9 -4
- package/src/core.ts +5 -1
- package/src/decisions-lint.ts +137 -0
- package/src/detect-stack.ts +70 -2
- package/src/diff-scope.ts +42 -20
- package/src/enforce.ts +18 -6
- package/src/finding-voice.ts +66 -0
- package/src/pr-comment.ts +30 -5
- package/src/reporter/finding.ts +7 -2
- package/src/reporter/github-adapter.ts +16 -2
- package/src/runner/runner.ts +3 -0
- package/src/sarif.ts +68 -9
package/README.md
CHANGED
|
@@ -4,19 +4,21 @@ A local accessibility checker for React/TSX code, grounded in a real-world audit
|
|
|
4
4
|
|
|
5
5
|
> **It runs entirely on your machine. No network, no account, no upload — your code never leaves the laptop.** That's not a privacy policy, it's how it's built: there's nothing to upload. Point it at a private repo with zero hesitation.
|
|
6
6
|
|
|
7
|
-
This is a private review build. Clone it, point it at any React codebase (yours
|
|
7
|
+
This is a private review build. Clone it, point it at any React codebase (yours or ours), and see what it finds — no setup, no explanation needed.
|
|
8
8
|
|
|
9
9
|
> **New here? Start with the [Getting Started](docs/GETTING-STARTED.md) walkthrough.** Zero to your first fix — install, `init`, wire your editor, read a finding, clear it, gate CI.
|
|
10
|
+
>
|
|
11
|
+
> **Just want it on your PRs?** The [CI Quickstart](docs/QUICKSTART-CI.md) is the 5-minute path — copy [`examples/github-actions/a11y.yml`](examples/github-actions/a11y.yml), open a PR, read the findings. No account, no secret.
|
|
10
12
|
|
|
11
13
|
---
|
|
12
14
|
|
|
13
15
|
## See it in 30 seconds
|
|
14
16
|
|
|
15
|
-
On **
|
|
17
|
+
On **shadcn/ui's own `taxonomy` app**, `eslint-plugin-jsx-a11y` (the linter everyone runs) passes the docs search box **clean** — while a11y-checker catches its unlabeled `<Input>`, ranks it (`22/26 orgs`), and hands you the fix.
|
|
16
18
|
|
|
17
|
-

|
|
18
20
|
|
|
19
|
-
**▶ [Watch all five demos →](demo/README.md)** — the head-to-head above, a getting-started walkthrough on
|
|
21
|
+
**▶ [Watch all five demos →](demo/README.md)** — the head-to-head above, a getting-started walkthrough on the cal.com monorepo, the `binclusive.json` config reference, the state of accessibility across 31 OSS repos, and the agentic self-fix loop. Each is a replayable [asciinema](https://asciinema.org) cast (`asciinema play demo/<name>.cast`), not just a GIF.
|
|
20
22
|
|
|
21
23
|
---
|
|
22
24
|
|
|
@@ -33,7 +35,7 @@ That's the whole thing. It scans every `.tsx` under the folder and prints a cove
|
|
|
33
35
|
|
|
34
36
|
No clone handy? Point it at this repo's own test fixtures: `pnpm scan ./test/fixtures`.
|
|
35
37
|
|
|
36
|
-
> **No React source?** (A live site, an ASP.NET/Razor app, plain HTML.) The same checker can render a real page in a browser and audit the live DOM — `pnpm scan:url https://example.com`. See **[Auditing HTML & live pages (non-React)](#auditing-html--live-pages-non-react)** below.
|
|
38
|
+
> **No React source?** (A live site, an ASP.NET/Razor app, plain HTML.) The same checker can render a real page in a browser and audit the live DOM — `pnpm scan:url https://www.example.com`. See **[Auditing HTML & live pages (non-React)](#auditing-html--live-pages-non-react)** below.
|
|
37
39
|
|
|
38
40
|
> **Using your own design system?** (Almost everyone is.) A cold scan leaves most of your components in `declare` — *that's expected, not a failure.* To turn on its best trick (finding bugs *inside* your own components), it needs to know which of your components are buttons, inputs, etc. You don't write that by hand:
|
|
39
41
|
>
|
|
@@ -88,19 +90,19 @@ There's also a **second producer**: a rendered-DOM collector that drives a real
|
|
|
88
90
|
|
|
89
91
|
## Auditing HTML & live pages (non-React)
|
|
90
92
|
|
|
91
|
-
The scan above works on `.tsx` source. But not every page *has* React source on disk — a deployed
|
|
93
|
+
The scan above works on `.tsx` source. But not every page *has* React source on disk — a deployed site, an ASP.NET/Razor app, a plain HTML/Bootstrap/jQuery page. For those, point the checker at the **rendered page** instead of the source:
|
|
92
94
|
|
|
93
95
|
```bash
|
|
94
96
|
pnpm exec playwright install chromium # one-time: the browser the render path drives
|
|
95
97
|
```
|
|
96
98
|
|
|
97
99
|
```bash
|
|
98
|
-
pnpm scan:url https://example.com
|
|
100
|
+
pnpm scan:url https://www.example.com # a deployed site
|
|
99
101
|
pnpm scan:url http://localhost:5000 # your local dev server
|
|
100
102
|
pnpm scan:url ./wwwroot/index.html # a local static .html file (bare path works)
|
|
101
103
|
```
|
|
102
104
|
|
|
103
|
-
`<target>` takes an `http(s)://` URL, a `file://` URL, or a **bare local path** (auto-converted to `file://`). Under the hood it renders the page in real Chromium (via Playwright), runs **axe-core** against the live DOM, then flows every finding through the *same* corpus / WCAG / enforcement machinery as the source scan — so a contrast bug on
|
|
105
|
+
`<target>` takes an `http(s)://` URL, a `file://` URL, or a **bare local path** (auto-converted to `file://`). Under the hood it renders the page in real Chromium (via Playwright), runs **axe-core** against the live DOM, then flows every finding through the *same* corpus / WCAG / enforcement machinery as the source scan — so a contrast bug on a live site comes back tiered and gated exactly like a missing label in your `.tsx`.
|
|
104
106
|
|
|
105
107
|
This is the source-less path — one command audits any live site, React or not.
|
|
106
108
|
|
|
@@ -134,9 +136,12 @@ jobs:
|
|
|
134
136
|
a11y:
|
|
135
137
|
runs-on: ubuntu-latest
|
|
136
138
|
steps:
|
|
139
|
+
# fetch-depth: 0 — the a11y diff scan needs base history; a shallow clone finds 0 changed files (a11y#198)
|
|
137
140
|
- uses: actions/checkout@v4
|
|
141
|
+
with:
|
|
142
|
+
fetch-depth: 0
|
|
138
143
|
- id: a11y
|
|
139
|
-
uses: Binclusive/a11y
|
|
144
|
+
uses: Binclusive/a11y@v0.1.1
|
|
140
145
|
- if: always() # advisory gate exits 0; upload regardless of findings
|
|
141
146
|
uses: github/codeql-action/upload-sarif@v3
|
|
142
147
|
with:
|
|
@@ -148,6 +153,12 @@ provenance (`deterministic` vs `agent`) in the SARIF property bag. The SARIF
|
|
|
148
153
|
file exists only to render on **your** GitHub — it carries file/line for local
|
|
149
154
|
annotation and is never sent to the Binclusive dashboard.
|
|
150
155
|
|
|
156
|
+
> **Pin for supply-chain safety.** The examples pin to the released tag
|
|
157
|
+
> `@v0.1.1`. For production, pin to a commit SHA — `uses:
|
|
158
|
+
> Binclusive/a11y@<sha> # v0.1.1` — rather than a floating tag or branch, so a
|
|
159
|
+
> moved tag can't silently change what runs in your CI. Dependabot
|
|
160
|
+
> (`github-actions` ecosystem) will bump the pin for you.
|
|
161
|
+
|
|
151
162
|
### Optional — opt into a blocking check (default off)
|
|
152
163
|
|
|
153
164
|
The check is **non-blocking by default**: it exits 0 on any severity or volume of
|
|
@@ -163,7 +174,7 @@ way.
|
|
|
163
174
|
|
|
164
175
|
```yaml
|
|
165
176
|
- id: a11y
|
|
166
|
-
uses: Binclusive/a11y
|
|
177
|
+
uses: Binclusive/a11y@v0.1.1
|
|
167
178
|
with:
|
|
168
179
|
fail-on: critical # optional — block only on critical findings
|
|
169
180
|
# max-violations: 0 # optional — block on any finding at all
|
|
@@ -188,7 +199,7 @@ means "lane off", never an error; the scan still exits 0.
|
|
|
188
199
|
|
|
189
200
|
```yaml
|
|
190
201
|
- id: a11y
|
|
191
|
-
uses: Binclusive/a11y
|
|
202
|
+
uses: Binclusive/a11y@v0.1.1
|
|
192
203
|
with:
|
|
193
204
|
llm-api-key: ${{ secrets.LLM_API_KEY }} # optional — your BYOK model key
|
|
194
205
|
llm-model: "" # optional — override the model
|
|
@@ -218,7 +229,7 @@ does not, and nothing new crosses the wire.
|
|
|
218
229
|
|
|
219
230
|
```yaml
|
|
220
231
|
- id: a11y
|
|
221
|
-
uses: Binclusive/a11y
|
|
232
|
+
uses: Binclusive/a11y@v0.1.1
|
|
222
233
|
with:
|
|
223
234
|
binclusive-app-id: ${{ vars.BINCLUSIVE_APP_ID }}
|
|
224
235
|
binclusive-app-private-key: ${{ secrets.BINCLUSIVE_APP_PRIVATE_KEY }}
|
|
@@ -238,7 +249,7 @@ artifact:
|
|
|
238
249
|
|
|
239
250
|
```sh
|
|
240
251
|
docker run --rm -v "$PWD:/workspace" -w /workspace -e A11Y_PLATFORM=null \
|
|
241
|
-
ghcr.io/binclusive/a11y
|
|
252
|
+
ghcr.io/binclusive/a11y:latest \
|
|
242
253
|
check /workspace/src --ci --format sarif > a11y.sarif
|
|
243
254
|
```
|
|
244
255
|
|
|
@@ -259,6 +270,7 @@ native platform adapters build on, are in **[`docs/CI.md`](docs/CI.md)**.
|
|
|
259
270
|
|---|---|
|
|
260
271
|
| **Adopt it with your own design system** | **`WALKTHROUGH.md`** |
|
|
261
272
|
| **Run it on any CI/CD (CircleCI / Jenkins / Drone / generic)** | **`docs/CI.md`** |
|
|
273
|
+
| **Ready-made configs for GitLab / CircleCI / Buildkite / Jenkins / Bitbucket** | **[`examples/ci/`](examples/ci/)** |
|
|
262
274
|
| **Audit a live URL or HTML page (non-React)** | **`docs/AUDIT-URL.md`** |
|
|
263
275
|
| The pitch + the moat, with numbers | `docs/decks/numbers.html` |
|
|
264
276
|
| Real findings on real OSS projects | `docs/decks/showcase.html` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@binclusive/a11y",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Local accessibility checker for React/TSX, grounded in axe-core's published rule catalog. Runs entirely on your machine — no network, no upload.",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
],
|
|
16
16
|
"repository": {
|
|
17
17
|
"type": "git",
|
|
18
|
-
"url": "git+https://github.com/Binclusive/a11y
|
|
18
|
+
"url": "git+https://github.com/Binclusive/a11y.git"
|
|
19
19
|
},
|
|
20
20
|
"publishConfig": {
|
|
21
21
|
"registry": "https://registry.npmjs.org",
|
|
@@ -56,6 +56,8 @@
|
|
|
56
56
|
"mcp": "tsx ./src/mcp.ts",
|
|
57
57
|
"gen:baseline": "tsx ./src/baseline/gen-baseline.ts",
|
|
58
58
|
"typecheck": "tsc --noEmit",
|
|
59
|
+
"decisions:check": "tsx ./scripts/check-decisions.ts",
|
|
60
|
+
"check:action-pin": "node ./scripts/check-action-pin.mjs",
|
|
59
61
|
"test": "vitest run",
|
|
60
62
|
"//test:e2e": "Rendered-DOM e2e (real Chromium). Excluded from `test`. CI must run `npx playwright install chromium` first.",
|
|
61
63
|
"test:e2e": "vitest run --config vitest.e2e.config.ts",
|
|
@@ -63,6 +65,9 @@
|
|
|
63
65
|
"matrix:run": "tsx experiments/stack-matrix/run.ts",
|
|
64
66
|
"matrix:report": "tsx experiments/stack-matrix/report.ts",
|
|
65
67
|
"matrix:baseline": "tsx experiments/stack-matrix/baseline.ts",
|
|
66
|
-
"matrix:check": "tsx experiments/stack-matrix/check.ts"
|
|
68
|
+
"matrix:check": "tsx experiments/stack-matrix/check.ts",
|
|
69
|
+
"android:matrix:run": "tsx experiments/android-matrix/run.ts",
|
|
70
|
+
"android:matrix:baseline": "tsx experiments/android-matrix/baseline.ts",
|
|
71
|
+
"android:matrix:check": "tsx experiments/android-matrix/check.ts"
|
|
67
72
|
}
|
|
68
73
|
}
|