{"_id":"@brokenhd/goodness-a11y","_rev":"6-80d7da1675656bb5d41a6ea566977a16","name":"@brokenhd/goodness-a11y","dist-tags":{"latest":"0.2.3"},"versions":{"0.1.0":{"name":"@brokenhd/goodness-a11y","version":"0.1.0","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","_id":"@brokenhd/goodness-a11y@0.1.0","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"bin":{"goodness-a11y":"dist/bin/goodness-a11y.js","goodness-lighthouse":"dist/bin/goodness-lighthouse.js"},"dist":{"shasum":"599bb0f231ebf5650320f89e66794681a2e4ddf5","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.1.0.tgz","fileCount":36,"integrity":"sha512-9u+aUe26VbCVJTDHf4jM96h389gv6OSE0BJAvyzC4Vg1m6kT864MgZUVUcbwEGy/NrGyKec9BT9Y5GZWZprPCg==","signatures":[{"sig":"MEUCIQDv+2t3ZJOAKXO7r+TVX8iiBeuvqB3uZwZBJPc+es5/9gIge/bHRBt3EvxFtpU+pVJk3Lx3e6zPn2zZkT7mbduc2pU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":47072},"main":"./dist/lib/index.js","type":"module","types":"./dist/lib/index.d.ts","engines":{"node":">=18.18.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"}},"gitHead":"7baa0db88a3c92b188927372890b209a50bffa29","scripts":{"lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/lighthouse-config.test.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"workspaces":["test/fixture"],"_npmVersion":"10.8.2","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","directories":{},"_nodeVersion":"20.19.0","dependencies":{"minimatch":"^9.0.5","eslint-plugin-jsx-a11y":"^6.10.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.15.0","globals":"^15.12.0","@eslint/js":"^9.15.0","typescript":"^5.7.2","@types/node":"^22.10.0","typescript-eslint":"^8.18.0"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0","@lhci/cli":"^0.14.0 || ^0.15.0"},"peerDependenciesMeta":{"@lhci/cli":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/goodness-a11y_0.1.0_1774986646934_0.3045181420196297","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@brokenhd/goodness-a11y","version":"0.1.1","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","_id":"@brokenhd/goodness-a11y@0.1.1","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"bin":{"goodness-a11y":"dist/bin/goodness-a11y.js","goodness-lighthouse":"dist/bin/goodness-lighthouse.js"},"dist":{"shasum":"67ae2bc89fb3fbd32caa510a5336e3228b535032","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.1.1.tgz","fileCount":36,"integrity":"sha512-lDje5GnckKZHS+1HvLZemKqUGSXhVMjMLVFFr6bfaul5WnmEEq0LbTQqNMap32qjjDNVvd2cmxGGePx28HSepQ==","signatures":[{"sig":"MEUCIQDthMl/qP4czpFLGA8jHx1ejHEvHqaAJZWuMCmRP8xxqAIgd9IVkYTtZo2mjYfeYkkJLU0j8lGNiVqhORfT7znNkmw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56673},"main":"./dist/lib/index.js","type":"module","types":"./dist/lib/index.d.ts","engines":{"node":">=18.18.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"}},"gitHead":"79424078d408f6791f4c61d60904e8bc5e4b741a","scripts":{"lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/lighthouse-config.test.js dist/test/run-eslint-layered.test.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"workspaces":["test/fixture"],"_npmVersion":"10.8.2","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","directories":{},"_nodeVersion":"20.19.0","dependencies":{"minimatch":"^9.0.5","eslint-plugin-jsx-a11y":"^6.10.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.15.0","globals":"^15.12.0","@eslint/js":"^9.15.0","typescript":"^5.7.2","@types/node":"^22.10.0","typescript-eslint":"^8.18.0"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0","@lhci/cli":"^0.14.0 || ^0.15.0"},"peerDependenciesMeta":{"@lhci/cli":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/goodness-a11y_0.1.1_1774990065973_0.5017214118107067","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@brokenhd/goodness-a11y","version":"0.2.0","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","_id":"@brokenhd/goodness-a11y@0.2.0","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"bin":{"goodness-a11y":"dist/bin/goodness-a11y.js"},"dist":{"shasum":"fa5dcdf719abb4cc77d39c54731e289dfe976561","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.2.0.tgz","fileCount":35,"integrity":"sha512-hGTJZFGqBuuxFqc7k6f5O2F92Zx5ZrfxGmLXAilIh4YibuR37Yc91icI/GsJX7A1GYhs57fRwo2QNsFAXo+NNA==","signatures":[{"sig":"MEUCIQC9J3bG7w09b9Cp+FZUqtNpZkPK4SJEnhV0H6f5zLwNMAIgeM6uv3mLt+4NWFuQMQXxG/OTIrjza6QcF8fSG3C1fcs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":51553},"main":"./dist/lib/index.js","type":"module","types":"./dist/lib/index.d.ts","engines":{"node":">=18.18.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"}},"gitHead":"55384e15add6ff5f357f0af130c748ecd12e20b2","scripts":{"lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/run-eslint-layered.test.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"workspaces":["test/fixture"],"_npmVersion":"10.8.2","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","directories":{},"_nodeVersion":"20.19.0","dependencies":{"minimatch":"^9.0.5","eslint-plugin-jsx-a11y":"^6.10.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.15.0","globals":"^15.12.0","@eslint/js":"^9.15.0","typescript":"^5.7.2","@types/node":"^22.10.0","typescript-eslint":"^8.18.0"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/goodness-a11y_0.2.0_1774990219967_0.7324944698499964","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@brokenhd/goodness-a11y","version":"0.2.1","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","_id":"@brokenhd/goodness-a11y@0.2.1","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"bin":{"goodness-a11y":"dist/bin/goodness-a11y.js"},"dist":{"shasum":"7a8eb6720df721816c34ab179a44d894b1a16eb5","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.2.1.tgz","fileCount":31,"integrity":"sha512-NvNy078HUa7lm0QIavhT7SuWeTcIXLI3ncyhNk/+WXO8mrO3+j+g62sVoPjnWtHeCeXDwQb7mlXJ5Wg/udCSdA==","signatures":[{"sig":"MEUCIDKqv3joJSnCwzH0OSQwElx8hIC7IghovirJtx9nj88OAiEApq4YsLTTlf52esK8StNQ6nHlEMd8YcrGqmRro+2WwjM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40414},"main":"./dist/lib/index.js","type":"module","types":"./dist/lib/index.d.ts","engines":{"node":">=18.18.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"}},"gitHead":"695dc6091ef13d9c9d5928d1db10e07df795a05b","scripts":{"lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/run-eslint-layered.test.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"workspaces":["test/fixture"],"_npmVersion":"10.8.2","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","directories":{},"_nodeVersion":"20.19.0","dependencies":{"minimatch":"^9.0.5","eslint-plugin-jsx-a11y":"^6.10.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.15.0","globals":"^15.12.0","@eslint/js":"^9.15.0","typescript":"^5.7.2","@types/node":"^22.10.0","typescript-eslint":"^8.18.0"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/goodness-a11y_0.2.1_1774990668365_0.9163374181693213","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@brokenhd/goodness-a11y","version":"0.2.2","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","_id":"@brokenhd/goodness-a11y@0.2.2","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"bin":{"goodness-a11y":"dist/bin/goodness-a11y.js"},"dist":{"shasum":"095696b7c01a7e11fda4a422ef54c0ed9b8c31d1","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.2.2.tgz","fileCount":31,"integrity":"sha512-Zc2xBe5+ANslwJoGI0eqJFFKuJKC9XsQtNbah6jAeeblfgJCzgm/gAUfQsh/FKIRpSBvXBboovWWBk761aYEoQ==","signatures":[{"sig":"MEUCIHCKdejyJB7zJ+E2m/w7AaJl1NthSqL1G+y/8kBwc22mAiEA9I9KwUUzdLoJdUuyFvlYQokzRD4oTUrDSYvq72hQspc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":41021},"main":"./dist/lib/index.js","type":"module","types":"./dist/lib/index.d.ts","engines":{"node":">=18.18.0"},"exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"},"./eslint-layer":{"types":"./dist/eslint/goodness-a11y-layer.d.ts","import":"./dist/eslint/goodness-a11y-layer.js","default":"./dist/eslint/goodness-a11y-layer.js"}},"gitHead":"14fd74db4668f191b74759e62a7511e96bcfc156","scripts":{"lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/run-eslint-layered.test.js","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"workspaces":["test/fixture"],"_npmVersion":"10.8.2","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","directories":{},"_nodeVersion":"20.19.0","dependencies":{"minimatch":"^9.0.5","eslint-plugin-jsx-a11y":"^6.10.0"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.15.0","globals":"^15.12.0","@eslint/js":"^9.15.0","typescript":"^5.7.2","@types/node":"^22.10.0","typescript-eslint":"^8.18.0"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0"},"_npmOperationalInternal":{"tmp":"tmp/goodness-a11y_0.2.2_1774991412601_0.06439568006985752","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@brokenhd/goodness-a11y","version":"0.2.3","description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","type":"module","bin":{"goodness-a11y":"dist/bin/goodness-a11y.js"},"main":"./dist/lib/index.js","types":"./dist/lib/index.d.ts","exports":{".":{"types":"./dist/lib/index.d.ts","import":"./dist/lib/index.js"},"./eslint-layer":{"types":"./dist/eslint/goodness-a11y-layer.d.ts","import":"./dist/eslint/goodness-a11y-layer.js","default":"./dist/eslint/goodness-a11y-layer.js"}},"workspaces":["test/fixture"],"engines":{"node":">=18.18.0"},"scripts":{"build":"tsc","prepublishOnly":"npm run build","lint":"eslint src","test":"npm run build && node --test dist/test/filter-files.test.js dist/test/run-eslint-layered.test.js"},"devDependencies":{"@eslint/js":"^9.15.0","@types/node":"^22.10.0","eslint":"^9.15.0","globals":"^15.12.0","typescript":"^5.7.2","typescript-eslint":"^8.18.0"},"keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"author":"","license":"MIT","dependencies":{"eslint-plugin-jsx-a11y":"^6.10.0","minimatch":"^9.0.5"},"peerDependencies":{"eslint":"^8.57.0 || ^9.0.0"},"_id":"@brokenhd/goodness-a11y@0.2.3","gitHead":"fba6a4aa2af8a0766ae2d1bd804f439238ff21d9","_nodeVersion":"20.19.0","_npmVersion":"10.8.2","dist":{"integrity":"sha512-KBquJKzlUbfTUspaKGlPh/Iwq9sEebgQOqKYUoYrvivn3TiK/lz1sP3tnGp2WiSVo72OrbwPEpa5ZwM8sTNhZQ==","shasum":"90c8f94ebd4cdde788dac7d22210f764f58553d2","tarball":"https://registry.npmjs.org/@brokenhd/goodness-a11y/-/goodness-a11y-0.2.3.tgz","fileCount":31,"unpackedSize":41061,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCICglksudLqMFzeBAJRP+C7COCaTNSk9RsWz/z3Jieg4IAiAj3GIlka2noEo8S85Ro6DYZ8JtChSAHWXZ/J1n+q7a1A=="}]},"_npmUser":{"name":"brokenhd","email":"michaelastarks@gmail.com"},"directories":{},"maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/goodness-a11y_0.2.3_1774992106778_0.5001937286501734"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-31T19:50:46.713Z","modified":"2026-03-31T21:21:47.061Z","0.1.0":"2026-03-31T19:50:47.130Z","0.1.1":"2026-03-31T20:47:46.143Z","0.2.0":"2026-03-31T20:50:20.116Z","0.2.1":"2026-03-31T20:57:48.499Z","0.2.2":"2026-03-31T21:10:12.817Z","0.2.3":"2026-03-31T21:21:46.916Z"},"license":"MIT","keywords":["accessibility","a11y","eslint","jsx-a11y","pull-request","ci"],"description":"Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request","maintainers":[{"name":"brokenhd","email":"michaelastarks@gmail.com"}],"readme":"# goodness-a11y\n\nRun **ESLint** (including [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y) or your own rules) **only on files that changed** between two git refs—typically the base and head of a pull request. This gives you PR-scoped accessibility linting without scanning the whole repository or running browser-based URL tests.\n\n## Requirements\n\n- **Node.js** 18.18+\n- **ESLint** 8.57+ or 9.x (`peerDependency`)\n- **eslint-plugin-jsx-a11y** is installed as a **dependency** of `goodness-a11y` (you do not need to add it separately).\n  - By default, `goodness-a11y` uses your repo’s ESLint config (`--eslint-config-mode repo`).\n  - To reduce per-repo setup, you can enable the built-in `jsx-a11y` recommended rules layer with `--eslint-config-mode layered`.\n  - For a “no config in the repo” mode (useful for quick adoption but less customizable), use `--eslint-config-mode package-only`.\n\n## Install\n\n```bash\nnpm install -D @brokenhd/goodness-a11y eslint\n```\n\nConfigure JSX accessibility rules in your project’s `eslint.config.js` / `.eslintrc` (see [eslint-plugin-jsx-a11y](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y)).\n\nFor **flat config** (`eslint.config.js`), you can import the same `jsx-a11y` layer the CLI uses without `import.meta.resolve` or path joins:\n\n```js\nimport { buildGoodnessA11yFlatLayer } from '@brokenhd/goodness-a11y/eslint-layer';\n\nexport default [\n  // ...your other config blocks\n  ...buildGoodnessA11yFlatLayer(),\n];\n```\n\nThe subpath is declared in this package’s `exports` field as `./eslint-layer`.\n\n## CLI\n\n```bash\n# Compare two refs (local or CI)\nnpx goodness-a11y --base main --head HEAD\n\n# Custom project root\nnpx goodness-a11y --base origin/main --head HEAD --cwd ./apps/web\n\n# Limit which changed files are linted (comma-separated globs, relative to cwd)\nnpx goodness-a11y --base main --head HEAD --include '**/*.tsx,**/*.jsx'\n\n# Use this package’s built-in jsx-a11y layer (recommended for simpler installs)\nnpx goodness-a11y --base main --head HEAD --eslint-config-mode layered\n\n# Use only this package’s config layer (no repo ESLint config)\nnpx goodness-a11y --base main --head HEAD --eslint-config-mode package-only\n```\n\n### Resolving base / head\n\nThe CLI resolves refs in this order:\n\n1. `--base` / `--head`\n2. `GOODNESS_BASE` / `GOODNESS_HEAD`\n3. `GITHUB_EVENT_PATH` pointing at a `pull_request` event payload (`pull_request.base.sha` and `pull_request.head.sha`)\n\nIf none of these provide both refs, the command exits with an error.\n\n### Default file filter\n\nOnly changed files matching these globs are linted (others are ignored):\n\n`**/*.js`, `**/*.jsx`, `**/*.mjs`, `**/*.cjs`, `**/*.ts`, `**/*.tsx`\n\nOverride with `--include`.\n\n## GitHub Actions\n\nYour workflow must:\n\n1. Check out the repository with **full history** so `git diff` can resolve both SHAs (`fetch-depth: 0`).\n2. Install dependencies (`npm ci` / `pnpm install` / etc.) so `eslint` and `goodness-a11y` are available.\n3. Run the composite action **after** install.\n\n### Example workflow\n\n```yaml\nname: PR accessibility (changed files)\n\non:\n  pull_request:\n\njobs:\n  a11y:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n    steps:\n      - uses: actions/checkout@v4\n        with:\n          fetch-depth: 0\n\n      - uses: actions/setup-node@v4\n        with:\n          node-version: '20'\n\n      - run: npm ci\n\n      - name: Goodness (ESLint on changed files)\n        uses: ./node_modules/@brokenhd/goodness-a11y/action.yml\n        # After publishing: uses: your-org/goodness-a11y@v0.1.0\n        # (path to action.yml depends on how you vendor the package)\n```\n\nIf you install `goodness-a11y` from npm, reference the action from `node_modules`:\n\n```yaml\n- uses: ./node_modules/@brokenhd/goodness-a11y/action.yml\n```\n\nAlternatively, copy the `steps` from [`action.yml`](./action.yml) into your workflow and run `npx goodness-a11y` yourself.\n\n### Composite action inputs\n\n| Input               | Description |\n|---------------------|-------------|\n| `working-directory` | Project root with ESLint config (default: `.`) |\n| `base` / `head`     | Optional override for git refs |\n| `include`           | Optional comma-separated globs (same as CLI `--include`) |\n| `eslint-config-mode`| `repo` \\| `layered` \\| `package-only` |\n| `max-warnings`      | Optional (fail when warnings exceed threshold) |\n| `format`            | ESLint formatter name (default: `stylish`) |\n\nThe composite action sets `GOODNESS_BASE` / `GOODNESS_HEAD` from the PR when `base` / `head` inputs are empty. Use it on `pull_request` workflows, or pass `base` / `head` explicitly for other events (so `github.event.pull_request` is not required).\n\nRun **actions/setup-node** and **install dependencies** before this step so `npx goodness-a11y` resolves `eslint` and `goodness-a11y` from `node_modules`.\n\n## Limitations\n\n- **Static analysis only** (what ESLint can see). It does not replace full-page or runtime checks (contrast in context, focus order across the whole document, etc.).\n \n## Programmatic API\n\n```js\nimport { runGoodness } from '@brokenhd/goodness-a11y';\n\nconst { exitCode, message } = await runGoodness({\n  cwd: process.cwd(),\n  base: 'main',\n  head: 'HEAD',\n  include: ['**/*.tsx'], // optional; omit for defaults\n});\n```\n\n## Developing this package\n\nThe implementation is **TypeScript** under [`src/`](./src). Run **`npm run build`** to emit `dist/` (required for `npm test` and for publishing). The published tarball includes `dist/` via `prepublishOnly`. If you install this repo from a **git URL** instead of the npm registry, run `npm run build` after install so the CLI entrypoints exist.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}