audit (EXPERIMENTAL)
auditAccessibility(agent.describe({ styles: true })) turns the affordance
map into findings. It is the lint the map made obvious: every element with
handlers should have a name, a role, and enough contrast and size to use —
and because the map is the framework's own record of its wiring, a finding
here is a real defect, not a scraper's guess.
import { enableAgentInterface, auditAccessibility } from 'tosijs'
const agent = enableAgentInterface()
const report = auditAccessibility(agent.describe({ styles: true }))
report.failed // 0 when clean
report.findings // [{ rule, severity, message, record, index }]
Pure over the description — no DOM, so it runs on a map that arrived over a
wire, in a test, or in CI. Pass styles: true to describe() or the
contrast rule has nothing to measure and skips itself (it says so).
The rules
| rule | what it catches | why |
|---|---|---|
anonymous-affordance |
a wired element with no accessible name, text, or value | a screen reader announces "button"; an agent sees <div> |
unnameable-action |
a handler that is an anonymous function (ƒ) |
nothing can invoke or describe it but a click |
missing-role |
a non-semantic tag (div/span) wired to act | assistive tech has no idea it is a control |
contrast |
text/background below the WCAG AA ratio | measured with tosijs's own Color; needs styles: true |
target-size |
interactive element below 24×24 (WCAG 2.5.8) | too small to hit reliably; toggles exempt |
label-hidden-by-placeholder |
a control whose only name is its placeholder | the name vanishes the moment the user types |
Findings carry the record and its index, so a caller can jump straight to
the element — or hand the pair to schematicSVG's flags to draw them.
The divergence is closed (tosijs-floorplan 0.4.0, issue #4).
target-sizeand "is this interactive" used to be implemented twice — here, and in the vendored renderer that draws the same map — and the two had drifted into contradicting each other on real elements. Both now come from./schematic, so the audit and the drawing cannot disagree by construction. Geometry is judged where the geometry lives; this module keeps only what it uniquely knows (the accessible name, the contrast math) and the rule wording.Adopting the shared rule changed five verdicts, deliberately, in both directions — see the 1.11.0 CHANGELOG entry.
It is one definition of evidence, not one set of answers. Three questions a drawing answers differently from a lint are adjusted here, by handing the shared predicate an adjusted record rather than by keeping a copy of it: zero-size (a
0×0element is hidden, not a small target — the renderer draws nothing either way), list containers that are themselves controls (floorplan#7), and producerflags, which a renderer may honour because it already drew them and a lint may not because it never reads them (floorplan#8). All three are filed upstream; if they land, these become no-ops.
EXPERIMENTAL. Ships with the agent surface; rules and shapes may change.