Paradise

A multi-model accessibility analyser for HTML, JavaScript, and CSS. It reasons about all three at once, in source, before the page renders — so it catches issues that single-file linters miss and reports issues that rendered-DOM scanners can’t tell from intentional behaviour.

The intermediate representation (IR) it builds, ActionLanguage, descends from doctoral work on adaptive user interfaces — published in the W4A 2008 CISNA Model paper, parked when I left academia for CNIB, and finished, fifteen years later, when source-level reasoning about JavaScript turned out to be exactly the missing piece for honest accessibility analysis.

Paradise is a platform I continue to develop, not a finished commercial tool. Fourteen working analysers, twenty-one ARIA widget patterns validated, ninety-five passing tests, over ninety percent coverage. Available as a VS Code extension: the extension is in active development, and is available in source at bobdodd/paradise. A browser plugin version is planned. A working in-browser Playground demonstrates what the analysers detect and serves as a template for anyone wanting to build their own analysis surface. GPL-3.0. Source on GitHub.

What Paradise is

Most accessibility tooling sees one slice of a web page. Linters like eslint-plugin-jsx-a11y read a JavaScript file in isolation and flag patterns that might be problems — they never see the HTML the handler actually attaches to. Browser-based scanners like axe, WAVE, and Lighthouse read the rendered DOM after JavaScript has run — they see the result, but they cannot tell whether a missing handler was an oversight in the source or an artefact of a code path the scanner did not trigger.

Paradise reads the source. It parses HTML into a DOMModel, JavaScript into an ActionLanguage tree, and CSS into a CSSModel; it merges the three into a unified DocumentModel using CSS selectors as the joining key; and it runs its analysers over the integrated structure. A button defined in index.html, given a click handler in handlers.js, hidden by a CSS class in styles.css, is one element to Paradise. Its analysers reason about that single element across all three files at once.

The current set covers cross-file event-handler validation, ARIA relationship validation, focus-management validation, all twenty-one WAI-ARIA widget patterns, and framework-specific patterns for React, Vue, Svelte, and Angular. Most ship as multi-model analysers that require all three sources together. A few work on JavaScript alone — useful as a fallback when the corresponding HTML isn’t available.

What’s different about it

Three families of accessibility analysis tools, in the order they appear in most projects:

AST-pattern lintersRendered-DOM scannersParadise
Exampleseslint-plugin-jsx-a11yaxe, WAVE, LighthouseParadise
What it readsone file’s ASTthe rendered DOMsource HTML + JS + CSS
Sees source intentyesnoyes
Sees runtime effectsnoyesyes (via the IR)
Cross-file reasoningnon/a (one DOM only)yes
Framework-awarepartiallynoyes

The cost of seeing only one slice is false positives. An AST linter flags a <div onclick> even when the handler in another file is keyboard-accessible. A rendered-DOM scanner flags a missing aria-labelledbytarget because the JavaScript that injects it runs on a code path the scanner didn’t trigger. Both tools are noisy enough that practitioners learn to ignore their output — which means real issues hide in the noise.

Paradise’s measured false-positive reduction against axe and ESLint-jsx-a11y on the test corpus is 88%. The methodology and the case studies live on the evidence page (in progress).

The ActionLanguage intermediate representation

The technical contribution. Most JavaScript analysis works on the abstract syntax tree — what was written. Paradise’s ActionLanguage works on a tree of actions — what the program does. A loop over an array becomes an iteration node; a closure over a variable becomes a binding node; an addEventListener becomes a registration node tied to the selector it targets.

The form of the tree comes directly from my PhD-era work on adaptive user interfaces, where it described the executable semantics of small algorithm fragments that could be substituted at runtime to suit a particular user. The same shape — actions in a tree, sequenced, with attributes — turned out to be exactly what was needed to reason about runtime accessibility behaviour from source. The IR is annotated enough to recover original line numbers for diagnostics, but abstract enough that two semantically-equivalent JavaScript fragments collapse to the same tree.

Status, scope, and what it does not do

  • Working analysers for the families listed above. Detail page in progress.
  • Confidence-weighted findings. Every issue carries a HIGH / MEDIUM / LOW level and a short reason, exposed as a percentage in the surfaces. Confidence is engine certainty given the source it has, not severity. See Architecture for how the level resolves and why.
  • Suggested fixes.For many findings the engine emits a corrective code suggestion alongside the diagnostic. Surfaces apply best-effort: the Playground’s Fix dialog, the VS Code plugin’s Quick Fixes (Code Actions), and CI consumers iterating issue.fix programmatically.
  • VS Code plugin in active development. Distributed as a .vsix from the source repo.
  • Browser plugin planned, not yet built.
  • CI use via the analyser engine consumed as a Node library.
  • Honest limitations.Paradise does not see things that only exist at runtime — third-party widgets injected into iframes, dynamically loaded modules whose source isn’t present, content fetched at interaction time. For those, runtime tools win. autoA11y is the runtime complement; its history (academic origins, multiple lineages including a commercial CNIB version) belongs on the research page.
  • Not a replacement for human review. Like every other tool in this space, Paradise reports what it can detect, not everything that matters.

Source, licence, citation

Paradise is open source at bobdodd/paradise. History extracted with git filter-repo from its original home as the Action Language/ subdirectory of the doctoral repo, so every commit that ever touched the code is preserved in the new repo.

Licence: GPL-3.0-or-later for the analyser engine and the VS Code plugin, matching the rest of the Bob-owned tooling. The companion documentation pages (this page and the /paradise/*sub-pages) are CC BY-SA 4.0 alongside the rest of a11ybob.com.

The W4A 2008 paper underlying the ActionLanguage tree shape: Dodd, Green & Pearson — The CISNA Model of Accessible Adaptive Hypermedia.

More

  • Lineage — the PhD-era work, the W4A 2008 CISNA Model paper, where ActionLanguage came from, and the relationship with autoA11y.
  • Architecture — the multi-model approach in detail, with a worked example of cross-file analysis.
  • ActionLanguage IR — the form of the tree, the model entities, and a worked JS-to-IR translation.
  • Analysers — the fourteen accessibility analysers that ship with Paradise, grouped by family, each with its own page.
  • Widget patterns — the twenty-one canonical WAI-ARIA widget patterns, with expected roles, states, and keyboard interactions for each.
  • Evidence — the 88% number, the corpus and methodology behind it, and where Paradise still misses.
  • VS Code plugin — install, configure, use; current release status and the planned browser plugin.
  • Cite — suggested citation, BibTeX entries for Paradise and the W4A 2008 paper.
  • Playground— the in-browser surface running Paradise’s analysers.