The contract every accessibility rule implements.
This behaviour is the whole extension point of farol. A rule is a plain
module: it names itself, points at the WCAG criterion it enforces, and
receives the parsed document as a list of Farol.Node trees (a forest).
It returns findings; it never raises and never performs IO.
why/0 and fix/0 are as important as the check itself. Farol's promise
is that every finding teaches: why explains the human impact in plain
words (who is affected and how), and fix shows the way out. Write them
for the developer reading a failing test at 5pm, not for a compliance
auditor.
Summary
Callbacks
Runs the rule against the parsed document forest.
Generic way out of the violation. Shown verbatim in every report.
Unique, stable, kebab-case identifier, like "img-alt". Greppable on purpose.
The WCAG conformance level of the criterion: "a", "aa" or "aaa".
:error breaks assert_accessible/2 by default; :warning only informs.
The WCAG 2.2 success criterion number, like "1.1.1".
Human-first explanation of the impact. Shown verbatim in every report.
Callbacks
@callback check(nodes :: [Farol.Node.t()]) :: [Farol.Finding.t()]
Runs the rule against the parsed document forest.
@callback fix() :: String.t()
Generic way out of the violation. Shown verbatim in every report.
@callback id() :: String.t()
Unique, stable, kebab-case identifier, like "img-alt". Greppable on purpose.
@callback level() :: String.t()
The WCAG conformance level of the criterion: "a", "aa" or "aaa".
@callback severity() :: :error | :warning
:error breaks assert_accessible/2 by default; :warning only informs.
@callback wcag() :: String.t()
The WCAG 2.2 success criterion number, like "1.1.1".
@callback why() :: String.t()
Human-first explanation of the impact. Shown verbatim in every report.