@brokenhd/goodness-a11y
v0.2.3
Published
Run ESLint accessibility rules (e.g. jsx-a11y) only on files changed in a pull request
Downloads
56
Maintainers
Readme
goodness-a11y
Run ESLint (including 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.
Requirements
- Node.js 18.18+
- ESLint 8.57+ or 9.x (
peerDependency) - eslint-plugin-jsx-a11y is installed as a dependency of
goodness-a11y(you do not need to add it separately).- By default,
goodness-a11yuses your repo’s ESLint config (--eslint-config-mode repo). - To reduce per-repo setup, you can enable the built-in
jsx-a11yrecommended rules layer with--eslint-config-mode layered. - For a “no config in the repo” mode (useful for quick adoption but less customizable), use
--eslint-config-mode package-only.
- By default,
Install
npm install -D @brokenhd/goodness-a11y eslintConfigure JSX accessibility rules in your project’s eslint.config.js / .eslintrc (see eslint-plugin-jsx-a11y).
For flat config (eslint.config.js), you can import the same jsx-a11y layer the CLI uses without import.meta.resolve or path joins:
import { buildGoodnessA11yFlatLayer } from '@brokenhd/goodness-a11y/eslint-layer';
export default [
// ...your other config blocks
...buildGoodnessA11yFlatLayer(),
];The subpath is declared in this package’s exports field as ./eslint-layer.
CLI
# Compare two refs (local or CI)
npx goodness-a11y --base main --head HEAD
# Custom project root
npx goodness-a11y --base origin/main --head HEAD --cwd ./apps/web
# Limit which changed files are linted (comma-separated globs, relative to cwd)
npx goodness-a11y --base main --head HEAD --include '**/*.tsx,**/*.jsx'
# Use this package’s built-in jsx-a11y layer (recommended for simpler installs)
npx goodness-a11y --base main --head HEAD --eslint-config-mode layered
# Use only this package’s config layer (no repo ESLint config)
npx goodness-a11y --base main --head HEAD --eslint-config-mode package-onlyResolving base / head
The CLI resolves refs in this order:
--base/--headGOODNESS_BASE/GOODNESS_HEADGITHUB_EVENT_PATHpointing at apull_requestevent payload (pull_request.base.shaandpull_request.head.sha)
If none of these provide both refs, the command exits with an error.
Default file filter
Only changed files matching these globs are linted (others are ignored):
**/*.js, **/*.jsx, **/*.mjs, **/*.cjs, **/*.ts, **/*.tsx
Override with --include.
GitHub Actions
Your workflow must:
- Check out the repository with full history so
git diffcan resolve both SHAs (fetch-depth: 0). - Install dependencies (
npm ci/pnpm install/ etc.) soeslintandgoodness-a11yare available. - Run the composite action after install.
Example workflow
name: PR accessibility (changed files)
on:
pull_request:
jobs:
a11y:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Goodness (ESLint on changed files)
uses: ./node_modules/@brokenhd/goodness-a11y/action.yml
# After publishing: uses: your-org/[email protected]
# (path to action.yml depends on how you vendor the package)If you install goodness-a11y from npm, reference the action from node_modules:
- uses: ./node_modules/@brokenhd/goodness-a11y/action.ymlAlternatively, copy the steps from action.yml into your workflow and run npx goodness-a11y yourself.
Composite action inputs
| Input | Description |
|---------------------|-------------|
| working-directory | Project root with ESLint config (default: .) |
| base / head | Optional override for git refs |
| include | Optional comma-separated globs (same as CLI --include) |
| eslint-config-mode| repo | layered | package-only |
| max-warnings | Optional (fail when warnings exceed threshold) |
| format | ESLint formatter name (default: stylish) |
The 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).
Run actions/setup-node and install dependencies before this step so npx goodness-a11y resolves eslint and goodness-a11y from node_modules.
Limitations
- 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.).
Programmatic API
import { runGoodness } from '@brokenhd/goodness-a11y';
const { exitCode, message } = await runGoodness({
cwd: process.cwd(),
base: 'main',
head: 'HEAD',
include: ['**/*.tsx'], // optional; omit for defaults
});Developing this package
The implementation is TypeScript under 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.
License
MIT
