1import * as aChecker from "accessibility-checker";
2import "lume/types.ts";
3import { rm } from "node:fs";
4
5// HTML Accessibility Plugin, by dish
6// version 1.0.0
7// Based on IBM's accessibility-checker library
8
9export default function () {
10 return (site: Lume.Site) => {
11 site.process([".html"], checkPages);
12
13 async function checkPages(pages: Lume.Page[]) {
14 const barReport = site.debugBar?.collection("Accessibility Checker");
15 if (barReport) {
16 barReport.icon = "wheelchair-motion";
17 barReport.contexts = {
18 "violation": {
19 background: "error",
20 },
21 "potentialviolation": {
22 background: "error",
23 },
24 "recommendation": {
25 background: "info",
26 },
27 "potentialrecommendation": {
28 background: "info",
29 },
30 };
31 }
32 console.info("[checkAccessibility] Starting...");
33 rm(`${Deno.cwd()}/accessibility-results`, { recursive: true, force: true }, (err) => {
34 if (err) throw err;
35 });
36 for (const page of pages) {
37 const label = page.outputPath.substring(0, page.outputPath.length - 5);
38 try {
39 let res = await aChecker.getCompliance(
40 page.content,
41 label,
42 );
43 if (aChecker.assertCompliance(res.report) === 0) {
44 (() => {});
45 } else {
46 barReport?.items.push({
47 title: page.data.url,
48 details: `${res.report.results.length} errors`,
49 items: Array.from(res.report.results).map((rep) => ({
50 title: `${rep.ruleId} - ${rep.reasonId}`,
51 context: rep.level,
52 text: rep.message,
53 actions: [
54 {
55 text: "Highlight",
56 icon: "question",
57 onclick: `highlightElement("${rep.path.dom}", "${page.outputPath}")`,
58 },
59 {
60 text: "Help",
61 icon: "question",
62 href: rep.help,
63 target: "_blank",
64 },
65 ],
66 })),
67 });
68 }
69 } catch (err) {
70 console.error(err);
71 }
72 }
73 await aChecker.close();
74 }
75 };
76}
77
78function lookupRule(rules: Object, ruleId: string, reasonId: string) {
79 const rule = rules[ruleId];
80 const reason: string = rule[reasonId];
81 return reason;
82}