Search by

phil / accessibility-check

phil

Accessibility of content checked before it is published: HTML and UJO documents, rules registered by class with their WCAG 2.2 success criterion, severity and translated message — text alternatives, headings, link names, contrast, table headers, languages and more —, a JSON report, a validator const

0.1.0-alpha 2026-11-12 14:43 UTC

This package is auto-updated.

Last update: 2026-11-12 23:50:51 UTC


README

Catch what keeps readers out before a content is published: missing text alternatives, broken outlines, empty links, faint text.

phil/accessibility-check checks a content at the moment it is published. It reads HTML — a whole page or the fragment an editor produced — through the HTML parser of PHP, and UJO (Universal JSON Output) documents block by block, so that an author is told which block and which field to fix. Each rule is a class with an identifier, the WCAG 2.2 success criterion it tests, a severity and a message in English, French, Spanish, German, Italian and Portuguese: text alternatives of images, the order of headings and the first-level heading, names of links and buttons, link texts that say nothing, the contrast of the colours the content gives, header cells of tables, languages of pages and passages, titles of frames, captions of videos, identifiers given twice, titles of drawings. The report says, rule by rule, whether it passed, lists what was found with its location, and serializes to JSON.

It is for any PHP application that publishes what people write: a CMS, a blog, a wiki, a tool that lays out books or game material. A check does not replace a test with people and assistive technologies; it stops the mistakes a machine can see, every time, before readers meet them.

It is a plain PHP library built on the dom, libxml and mbstring extensions and symfony/translation. With the packages it adapts to, it also gives Symfony applications a validator constraint, a guard of symfony/workflow that holds back a publication, and a console command.

The design is small: AccessibilityChecker runs the rules a Policy keeps over an HtmlTarget or a UjoTarget and returns a Report of RuleResults and Findings; a rule implements HtmlRule, UjoRule or both, and yields Violations; symfony/translation writes their messages, through Translation\Messages.

Status

Part State
HTML read through Dom\HTMLDocument, limits of size, depth and elements, UTF-8 only Implemented and tested
UJO documents read block by block, nested blocks included, fields that hold HTML parsed apart Implemented and tested
15 rules, with their WCAG 2.2 success criterion and severity Implemented and tested
Contrast of WCAG computed from the colours of the content and of the tokens of the look Implemented and tested
Messages in English, French, Spanish, German, Italian and Portuguese Implemented and tested
Report with the outcome of each rule, locations and JSON Implemented and tested
Symfony validator constraint AccessibleContent Implemented and tested
Workflow guard PublicationGuard Implemented and tested
Console command phil:accessibility:check Implemented and tested

Documentation

Document What it covers
Installation Requirements, installing, and the services of a Symfony application.
Checking Checking HTML and UJO, the report, the findings and their locations, JSON.
Rules The catalogue of the rules: what each checks, its criterion, its severity and its messages.
Policy Limits, headings, contrast and colours, languages, generic link texts, rules turned off.
Messages The translator, its six languages, the keys and their placeholders.
Validator The AccessibleContent constraint.
Publication guard Holding back a publication of symfony/workflow.
Console The phil:accessibility:check command.
Extension points Writing a rule, adding messages, the plain fields of UJO, the content of a subject.
Exceptions AccessibilityCheckException and its three exceptions.
Testing The library's tests, mutation bar, fuzzing and benchmark, and how to test with it.
Reference Every type of the library, with its role.

Quick start

composer require phil/accessibility-check
use Phil\AccessibilityCheck\AccessibilityChecker;

$report = new AccessibilityChecker()->checkHtml(<<<'HTML'
    <h2>Opening hours</h2>
    <h4>Summer</h4>
    <img src="/uploads/IMG_2041.jpg">
    <p>Book a table <a href="/booking">here</a>.</p>
    <p style="color: #aaa">Closed on holidays.</p>
    HTML);

foreach ($report->findings as $finding) {
    printf("[%s] %s (WCAG %s) %s: %s\n", $finding->severity->value, $finding->rule, $finding->criterion->value,
        $finding->location->describe(), $report->message($finding));
}
// [error] image-alt (WCAG 1.1.1) line 3, img: The image /uploads/IMG_2041.jpg has no text alternative: …
// [warning] heading-order (WCAG 1.3.1) line 2, h4: This h4 heading follows an h2: a level is skipped.
// [warning] link-text (WCAG 2.4.4) line 4, p:nth-of-type(1) > a: The text of the link to /booking, "here", …
// [error] color-contrast (WCAG 1.4.3) line 5, p:nth-of-type(2): The text "Closed on holidays." has a contrast of 2.32:1 …

$report->passes();                 // false: an error was found
echo json_encode($report);         // the outcome of each rule and every finding

Requirements

PHP 8.5 or later, with the dom, libxml and mbstring extensions; phil/ujo to check UJO documents; symfony/validator, symfony/workflow and symfony/console for the constraint, the guard and the command.

Contributing

Contributions are welcome on the PHIL monorepo: read the contribution guide and the code of conduct. Report a vulnerability privately, as the security policy explains, never in a public issue.

License

MIT, © Philippe Gamache, doing business as Le Gnome Archiviste; a Parler Haut Interagir Librement project. See LICENSE.