Last updated: 2026-03-19
- Formatting: Run
npm run fmt(Prettier) andnpm run eslintbefore every commit. No exceptions. - Zero-Exception Testing: 100% coverage goal. Run
npm testbefore completion.feat/fixand other behavior-changing PRs require unit + integration tests where applicable; seedoc/code-submission-guidelines.mdfor exceptions (e.g., somechore/docs changes). - Import Rule: Directory-level import restrictions are strictly enforced. See
eslint.config.js. - Commits: Angular commit convention is mandatory. PRs with non-conforming commits will be rejected. See
doc/code-submission-guidelines.md. - Issues: All unresolved issues tracked in GitHub Issues.
- Return Early: Keep the happy path left-aligned. Handle errors/edge cases first with early returns — never nest when you can exit.
- Exports: Default export at the top of the file, immediately after imports.
- JSDoc: Add JSDoc/DocBlock comments where appropriate, especially for exported APIs and complex logic. Document parameters and return types. See
doc/code-submission-guidelines.md(source of truth) anddoc/developer-guide.mdfor additional guidance. - Naming: Files and rule/check IDs in kebab-case. Functions in camelCase. Booleans prefixed
is/has/should. Constants inUPPER_SNAKE_CASE. - Variables: Declare at point of use, not at the top of the function.
- Prefer Virtual Nodes for attribute access and property reads (
virtualNode.attr(),virtualNode.props). - Use real DOM only when you need DOM APIs (e.g.,
getBoundingClientRect,getRootNode). core/utils/functions should default to real DOM inputs/outputs, except utilities that are explicitly documented as operating onVirtualNode(for example, tree or selector helpers). Avoid introducing newVirtualNode-dependent utilities unless there is a clear performance or API benefit.- Conversion: Use
getNodeFromTree()fromcore/utilswhen you receive an ambiguous input (such as aVirtualNode, selector, or mixed type) and need to resolve it to a real DOMNode.
standards/→ nothing (pure data, no imports).core/utils/→ othercore/utils,core/base,standardsvia direct file paths only (no index).core/imports/→ node modules only (the only place npm imports are allowed).commons/→ othercommons(direct paths),core/utils(index OK).checks/andrules/→ any directory (index OK).- Never import
commonsfromcore/utils. This is the most commonly rejected violation.
- Check evaluate functions: Return
true(pass),false(fail), orundefined(incomplete). Usethis.data()to pass values to message templates and to provide incomplete-result detail. - Rule JSON: Use
all,any,nonecheck arrays.selector+ optionalmatchesto scope candidates. Validimpactvalues:"minor","moderate","serious","critical". - Standards data: Never hardcode ARIA/HTML lists in checks. Query from
standards/viacommons/standardsfunctions. - Messages: All user-facing strings live in check/rule JSON
metadata.messages. Use${data.property}templates. Support singular/plural variants. Updatelocales/_template.jsonwhenever messages change (auto-synced onnpm run build).
- Color contrast: Handles all CSS color formats, opacity, blend modes, stacking contexts, text-shadow. Return
undefinedwhen background cannot be determined. Seedoc/developer-guide.md. - ARIA validation: Must stay current with spec. Query roles/attrs from
standards/aria-roles.jsandstandards/aria-attrs.js. Handle implicit vs. explicit roles. Seedoc/rule-development.md. - Hidden elements: Use
isVisibleToScreenReaders(), not CSS visibility alone. Account foraria-hidden="true"and Shadow DOM boundaries. - i18n: Update
locales/_template.jsonon every message change and commit the generated file alongside source.
- Structure: Mirror
lib/exactly undertest/. Filelib/commons/text/sanitize.js→test/commons/text/sanitize.js. - Checks: Use
axe.testUtils.MockCheckContext(). Only resetcheckContextinafterEach—fixtureandaxe._treeare auto-cleared. - Integration tests: All rule changes require an HTML + JSON pair. Use
test/integration/rules/<rule-name>/for mocha-hosted tests ortest/integration/full/<rule-name>/when the rule requires a full HTML page. JSON selectors must use axe array format (["#id"]; iframes:["iframe", "#id"]). Also update or create virtual-rules tests where appropriate. - Shadow DOM: Every relevant check/rule must include an open Shadow DOM test case using
queryShadowFixture. - Logging: Do not commit
console.logstatements.
- Bundles (
axe.js,axe.min.js) are auto-generated for releases/publishing and are not committed to the repo (they are gitignored). - Locales template (
locales/_template.json) is auto-generated. When message strings change, regenerate this file and commit it in the same commit as the source changes — never in a separate commit. - One change per PR. Do not mix refactoring with feature work.
- Commit format:
<type>(<scope>): <subject>— imperative, lowercase, no period, ≤100 chars total. Body explains motivation. Footer:Closes issue #123or full URL. Seedoc/code-submission-guidelines.mdfor the full type list.
Example:
fix(aria-valid-attr-value): handle multiple aria-errormessage IDs
When aria-errormessage contains multiple space-separated IDs, verify
all IDs exist in aria-describedby instead of matching the full string.
Closes issue #4957
- New rules: Update
CHANGELOG.md.doc/rule-descriptions.mdis auto-generated bynpm run build. - API changes: Update
doc/API.mdandaxe.d.tsTypeScript definitions. - Breaking changes: Avoid breaking changes — prefer supporting both old and new formats simultaneously. If unavoidable, add
BREAKING CHANGE: descriptionto commit footer, include migration guide inCHANGELOG.md, and tag deprecated code with@deprecatedJSDoc.
- Code patterns:
doc/examples/code-patterns.md— return early, default export, imports, JSDoc, Virtual Node usage - Test patterns:
doc/examples/test-patterns.md— unit tests, check tests, Shadow DOM tests, integration test HTML+JSON - Rule & check templates:
doc/examples/rule-check-templates.md— JSON templates for rules and checks, evaluate function pattern - PR review patterns:
doc/examples/pr-review-patterns.md— common reviewer feedback, anti-patterns, what reviewers look for
- Contributing guide:
CONTRIBUTING.md - Import rules detail:
eslint.config.js - Code submission standards:
doc/code-submission-guidelines.md - Developer guide:
doc/developer-guide.md - Rule development:
doc/rule-development.md - API reference:
doc/API.md - Pull Request Checklist:
doc/pull-request-checklist.md - Slack: axe-community
- Issues: GitHub Issues