eaa-kit 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +23 -8
  2. package/dist/astro/index.d.ts +1 -1
  3. package/dist/astro/index.js +1 -1
  4. package/dist/audit/runners/worker.js +1 -1
  5. package/dist/audit-Bwm1xBdJ.js +2 -0
  6. package/dist/{audit-e_uixhPG.js → audit-DRjAY2iY.js} +164 -75
  7. package/dist/{baseline-D2qWmUC6.js → baseline-BpE7DbDq.js} +1 -1
  8. package/dist/{baseline-BscHfFSW.js → baseline-rtnj3RHB.js} +1 -1
  9. package/dist/cache-D4dOIuOi.js +219 -0
  10. package/dist/{checklist-BtgkxMEa.js → checklist-DDd9jewi.js} +3 -3
  11. package/dist/cli/index.js +28 -12
  12. package/dist/{command-CZKp9Wi_.js → command-3r4fht5f.js} +6 -5
  13. package/dist/{coverage-BD2_CYns.js → coverage-cb5kPp48.js} +3 -285
  14. package/dist/coverage-n1X9CkiG.js +3 -0
  15. package/dist/criteria-CnPJKGeb.js +286 -0
  16. package/dist/eleventy/index.d.ts +1 -1
  17. package/dist/eleventy/index.js +1 -1
  18. package/dist/{html-Bmh7X_sM.js → html-BIxxF3FC.js} +6 -4
  19. package/dist/index.d.ts +19 -0
  20. package/dist/index.js +2 -2
  21. package/dist/{init-BjKYttxc.js → init-DrFfzjvm.js} +2 -2
  22. package/dist/jsdom-BUYuVJJm.js +3 -0
  23. package/dist/{jsdom-CQar6OQS.js → jsdom-CsW_xVcA.js} +11 -12
  24. package/dist/{json-PNg6BeXp.js → json-Bus6YhxB.js} +4 -3
  25. package/dist/{json-HJDgJp09.js → json-CrQmoTj6.js} +1 -1
  26. package/dist/{load-vZdV_fD1.js → load-BaWMa-G_.js} +6 -1
  27. package/dist/load-n62iXDq_.js +2 -0
  28. package/dist/nuxt/index.d.ts +1 -1
  29. package/dist/nuxt/index.js +1 -1
  30. package/dist/{playwright-C-miJP2b.js → playwright-ukCr_5o3.js} +1 -1
  31. package/dist/{pool-dkexq5xo.js → pool-B4tEUa2S.js} +6 -2
  32. package/dist/{completeness-Dwq3CPB3.js → remediation-C0klJblu.js} +55 -42
  33. package/dist/{render-CtsqR0k-.js → render-C1sUZZI_.js} +41 -3
  34. package/dist/{result-DfUru6y_.js → result-B7_zVxAX.js} +1 -1
  35. package/dist/result-CRmjjoAA.js +2 -0
  36. package/dist/{run-YiqyQA2b.d.ts → run-BK2blxMI.d.ts} +8 -0
  37. package/dist/{run-D7hdVXLA.js → run-DrS0Komf.js} +6 -2
  38. package/dist/{sarif-BKvq_AUm.js → sarif-BNCE0PNT.js} +3 -2
  39. package/dist/statement/templates/at.de.md +14 -0
  40. package/dist/statement/templates/at.en.md +14 -0
  41. package/dist/statement/templates/ch.de.md +14 -0
  42. package/dist/statement/templates/ch.en.md +14 -0
  43. package/dist/statement/templates/de.de.md +14 -0
  44. package/dist/statement/templates/de.en.md +14 -0
  45. package/dist/statement/templates/es.en.md +14 -0
  46. package/dist/statement/templates/es.es.md +15 -0
  47. package/dist/statement/templates/fr.en.md +14 -0
  48. package/dist/statement/templates/fr.fr.md +15 -0
  49. package/dist/statement/templates/it.en.md +14 -0
  50. package/dist/statement/templates/it.it.md +15 -0
  51. package/dist/statement/templates/nl.en.md +14 -0
  52. package/dist/statement/templates/nl.nl.md +15 -0
  53. package/dist/vite/index.d.ts +1 -1
  54. package/dist/vite/index.js +1 -1
  55. package/dist/webpack/index.d.ts +1 -1
  56. package/dist/webpack/index.js +1 -1
  57. package/dist/{worksheet-eUjwYLxC.js → worksheet-BIxMtbUd.js} +3 -2
  58. package/package.json +3 -2
  59. package/dist/audit-DK2StT1_.js +0 -2
  60. package/dist/coverage-7bQqWNfN.js +0 -2
  61. package/dist/jsdom-DMvU2h-f.js +0 -3
  62. package/dist/load-Bc_xDGAh.js +0 -2
@@ -0,0 +1,219 @@
1
+ import { c as nullable, d as optional, h as string, i as enumeration, l as number, m as safeParse, t as array, u as object, y as withDefault } from "./schema-DJSF4K05.js";
2
+ import { a as isoDate } from "./text-BF1LHMiV.js";
3
+ import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { createHash } from "node:crypto";
6
+ const MANIFEST_FILE = "manifest.json";
7
+ const outcomeSchema = object({
8
+ ruleId: string(),
9
+ help: withDefault(string(), () => ""),
10
+ helpUrl: withDefault(string(), () => ""),
11
+ successCriteria: withDefault(array(string()), () => []),
12
+ enClauses: withDefault(array(string()), () => []),
13
+ tags: withDefault(array(string()), () => [])
14
+ });
15
+ const nodeSchema = object({
16
+ html: string(),
17
+ target: withDefault(array(string()), () => []),
18
+ failureSummary: optional(string())
19
+ });
20
+ const findingSchema = object({
21
+ ruleId: string(),
22
+ help: withDefault(string(), () => ""),
23
+ helpUrl: withDefault(string(), () => ""),
24
+ successCriteria: withDefault(array(string()), () => []),
25
+ enClauses: withDefault(array(string()), () => []),
26
+ tags: withDefault(array(string()), () => []),
27
+ impact: withDefault(nullable(string()), () => null),
28
+ nodes: withDefault(array(nodeSchema), () => [])
29
+ });
30
+ const incompleteSchema = object({
31
+ ruleId: string(),
32
+ help: withDefault(string(), () => ""),
33
+ helpUrl: withDefault(string(), () => ""),
34
+ successCriteria: withDefault(array(string()), () => []),
35
+ enClauses: withDefault(array(string()), () => []),
36
+ tags: withDefault(array(string()), () => []),
37
+ impact: withDefault(nullable(string()), () => null),
38
+ nodes: withDefault(array(nodeSchema), () => []),
39
+ reason: enumeration(["needs-review", "engine-limitation"]),
40
+ reasonDetail: withDefault(string(), () => "")
41
+ });
42
+ const entrySchema = object({
43
+ schemaVersion: number(),
44
+ /** The page this describes, as the run names it. */
45
+ page: string(),
46
+ /** ISO date the result was produced, printed by the reports. */
47
+ cachedOn: string(),
48
+ violations: withDefault(array(findingSchema), () => []),
49
+ incomplete: withDefault(array(incompleteSchema), () => []),
50
+ passes: withDefault(array(outcomeSchema), () => []),
51
+ inapplicable: withDefault(array(outcomeSchema), () => [])
52
+ });
53
+ const manifestSchema = object({
54
+ schemaVersion: number(),
55
+ /** Hash of everything in `CacheInputs`. A mismatch discards the cache. */
56
+ key: string(),
57
+ createdOn: withDefault(string(), () => "")
58
+ });
59
+ /**
60
+ * The identity of a page's content.
61
+ *
62
+ * Path and HTML together: the same markup at two paths is two pages, because
63
+ * the path is what a baseline, a diff and every report key on. A full digest
64
+ * rather than the sixteen characters `elementFingerprint` uses — that one is
65
+ * read by people in a committed file, and this one is read only by the tool,
66
+ * where a collision would serve one page's verdicts for another's.
67
+ */
68
+ function pageKey(page) {
69
+ return createHash("sha256").update(`${page.relativePath}\n${page.html}`).digest("hex");
70
+ }
71
+ /**
72
+ * The identity of everything else the verdict depends on.
73
+ *
74
+ * Headers are hashed with the rest and never recorded: what a run sent can
75
+ * change what it was served, so it belongs in the key, and a credential does
76
+ * not belong on disk.
77
+ */
78
+ function inputsKey(inputs) {
79
+ const headers = Object.entries(inputs.headers ?? {}).map(([name, value]) => `${name.toLowerCase()}=${value}`).sort().join("\n");
80
+ return createHash("sha256").update([
81
+ `tool=${inputs.toolVersion}`,
82
+ `axe=${inputs.axeVersion}`,
83
+ `tags=${[...inputs.tags].join(",")}`,
84
+ `engine=${inputs.engine}`,
85
+ `fast=${inputs.fast}`,
86
+ `viewport=${inputs.viewport ? `${inputs.viewport.width}x${inputs.viewport.height}` : ""}`,
87
+ `baseUrl=${inputs.baseUrl ?? ""}`,
88
+ `timeout=${inputs.timeoutMs ?? ""}`,
89
+ `headers=${createHash("sha256").update(headers).digest("hex")}`
90
+ ].join("\n")).digest("hex");
91
+ }
92
+ /**
93
+ * Open the cache for a run, discarding it if anything about the run changed.
94
+ *
95
+ * Everything is read up front and held in memory: an audit asks about every
96
+ * page before it audits any, the entries are small, and a synchronous answer
97
+ * is what lets the caller decide whether to import an engine at all.
98
+ */
99
+ async function openCache(inputs, options = {}) {
100
+ const root = path.resolve(options.cwd ?? process.cwd(), options.dir ?? ".eaa-kit/cache");
101
+ const key = inputsKey(inputs);
102
+ const today = isoDate(options.today ?? /* @__PURE__ */ new Date());
103
+ const entries = await manifestMatches(root, key) ? await readEntries(root) : /* @__PURE__ */ new Map();
104
+ const written = /* @__PURE__ */ new Map();
105
+ return {
106
+ get(page) {
107
+ return entries.get(pageKey(page));
108
+ },
109
+ put(page, audit) {
110
+ if (audit.error !== void 0) return;
111
+ written.set(pageKey(page), toEntry(page, audit, today));
112
+ },
113
+ async flush() {
114
+ if (written.size === 0) return;
115
+ try {
116
+ await mkdir(root, { recursive: true });
117
+ await writeFile(path.join(root, MANIFEST_FILE), `${JSON.stringify({
118
+ schemaVersion: 1,
119
+ key,
120
+ createdOn: today
121
+ }, null, 2)}\n`, "utf8");
122
+ await Promise.all([...written].map(([hash, entry]) => writeFile(path.join(root, `${hash}.json`), `${JSON.stringify(entry)}\n`, "utf8")));
123
+ } catch {}
124
+ }
125
+ };
126
+ }
127
+ /**
128
+ * Whether the stored cache was produced under the same conditions as this run.
129
+ *
130
+ * A mismatch empties the directory rather than leaving entries to be stepped
131
+ * over. They can never be read again — the key that would reach them is gone —
132
+ * and leaving them would grow `.eaa-kit/` without limit.
133
+ */
134
+ async function manifestMatches(root, key) {
135
+ let raw;
136
+ try {
137
+ raw = await readFile(path.join(root, MANIFEST_FILE), "utf8");
138
+ } catch {
139
+ return false;
140
+ }
141
+ let parsed;
142
+ try {
143
+ parsed = JSON.parse(raw);
144
+ } catch {
145
+ await discard(root);
146
+ return false;
147
+ }
148
+ const result = safeParse(manifestSchema, parsed);
149
+ if (!result.success || result.data.schemaVersion !== 1 || result.data.key !== key) {
150
+ await discard(root);
151
+ return false;
152
+ }
153
+ return true;
154
+ }
155
+ async function discard(root) {
156
+ try {
157
+ await rm(root, {
158
+ recursive: true,
159
+ force: true
160
+ });
161
+ } catch {}
162
+ }
163
+ /** Every entry in the directory, keyed by page hash. A bad file is skipped. */
164
+ async function readEntries(root) {
165
+ let files;
166
+ try {
167
+ files = await readdir(root);
168
+ } catch {
169
+ return /* @__PURE__ */ new Map();
170
+ }
171
+ const entries = /* @__PURE__ */ new Map();
172
+ await Promise.all(files.filter((file) => file.endsWith(".json") && file !== MANIFEST_FILE).map(async (file) => {
173
+ try {
174
+ const parsed = JSON.parse(await readFile(path.join(root, file), "utf8"));
175
+ const result = safeParse(entrySchema, parsed);
176
+ if (!result.success || result.data.schemaVersion !== 1) return;
177
+ entries.set(path.basename(file, ".json"), result.data);
178
+ } catch {}
179
+ }));
180
+ return entries;
181
+ }
182
+ /** The parts of a result that describe the page rather than the run. */
183
+ function toEntry(page, audit, today) {
184
+ return {
185
+ schemaVersion: 1,
186
+ page: page.relativePath,
187
+ cachedOn: today,
188
+ violations: audit.violations,
189
+ incomplete: audit.incomplete,
190
+ passes: audit.passes,
191
+ inapplicable: audit.inapplicable
192
+ };
193
+ }
194
+ /**
195
+ * A stored result, put back together as this run's audit.
196
+ *
197
+ * The page's own facts come from the cache; everything about *this* run — where
198
+ * the file is, what URL it is audited under, which engine is running — comes
199
+ * from the run, because those are not properties of the result. `durationMs` is
200
+ * zero rather than the duration of a run that happened on another day, and
201
+ * `reused` is what stops every consumer downstream from mistaking this for work
202
+ * that was done just now.
203
+ */
204
+ function fromEntry(entry, page, context) {
205
+ return {
206
+ relativePath: page.relativePath,
207
+ absolutePath: page.absolutePath,
208
+ url: context.url,
209
+ engine: context.engine,
210
+ violations: entry.violations,
211
+ incomplete: entry.incomplete,
212
+ passes: entry.passes,
213
+ inapplicable: entry.inapplicable,
214
+ durationMs: 0,
215
+ reused: { on: entry.cachedOn }
216
+ };
217
+ }
218
+ //#endregion
219
+ export { fromEntry, openCache };
@@ -1,5 +1,5 @@
1
1
  import { n as count } from "./text-BF1LHMiV.js";
2
- import { a as emitDocument, o as fail, s as note } from "./command-CZKp9Wi_.js";
2
+ import { a as emitDocument, o as fail, s as note } from "./command-3r4fht5f.js";
3
3
  import "./review-CdMK2GpQ.js";
4
4
  import { access } from "node:fs/promises";
5
5
  import path from "node:path";
@@ -7,7 +7,7 @@ import path from "node:path";
7
7
  async function runChecklistCommand(options = {}) {
8
8
  const cwd = options.cwd ?? process.cwd();
9
9
  const recordPath = options.record ?? "eaa-review.json";
10
- const { WCAG22_AA_CRITERIA } = await import("./coverage-7bQqWNfN.js");
10
+ const { WCAG22_AA_CRITERIA } = await import("./coverage-n1X9CkiG.js");
11
11
  const { answeredCount, blankReview, readReview, ReviewError, writeReview } = await import("./review-DIbOTmOM.js");
12
12
  let existing;
13
13
  try {
@@ -23,7 +23,7 @@ async function runChecklistCommand(options = {}) {
23
23
  if (options.reviewedBy !== void 0) record.reviewedBy = options.reviewedBy;
24
24
  await writeReview(recordPath, record, cwd);
25
25
  note(existing === void 0 ? `Review record written to ${recordPath}` : `Review record updated at ${recordPath}: ${count(answeredCount(record), "criterion")} already answered`);
26
- const { buildWorksheet } = await import("./worksheet-eUjwYLxC.js");
26
+ const { buildWorksheet } = await import("./worksheet-BIxMtbUd.js");
27
27
  await emitDocument(buildWorksheet({
28
28
  recordPath,
29
29
  review: record
package/dist/cli/index.js CHANGED
@@ -1,15 +1,15 @@
1
1
  #!/usr/bin/env node
2
2
  import { c as meetsThreshold, n as IMPACT_LEVELS, o as impactRank, s as isImpactLevel, t as DEFAULT_FAIL_ON } from "../impact-luGCnN8F.js";
3
3
  import { c as nullable, d as optional, h as string, l as number, m as safeParse, n as boolean, p as record, t as array, u as object, y as withDefault } from "../schema-DJSF4K05.js";
4
- import { c as ConfigError, i as loadConfig, s as COUNTRIES, u as STATEMENT_LOCALES } from "../load-vZdV_fD1.js";
5
- import { c as StatementError, i as readAuditReport, o as checkStatementEvidence, s as refuses, t as renderStatement } from "../render-CtsqR0k-.js";
4
+ import { c as ConfigError, i as loadConfig, s as COUNTRIES, u as STATEMENT_LOCALES } from "../load-BaWMa-G_.js";
5
+ import { c as StatementError, i as readAuditReport, o as checkStatementEvidence, s as refuses, t as renderStatement } from "../render-C1sUZZI_.js";
6
6
  import { n as count, t as collapse } from "../text-BF1LHMiV.js";
7
7
  import { t as TOOL_VERSION } from "../version-B3v4rNoG.js";
8
8
  import { t as elementFingerprint } from "../fingerprint-BjYV_0F7.js";
9
- import { a as pruneBaseline, c as writeBaseline, i as buildBaseline, n as DEFAULT_BASELINE_FILE, o as readBaseline, r as applyBaseline, t as BaselineError } from "../baseline-D2qWmUC6.js";
10
- import { a as emitDocument, c as runEngine, d as parseHeader, i as baselineInvocation, l as warn, n as auditDefaults, o as fail, r as auditInvocation, s as note, t as advise, u as basicAuth } from "../command-CZKp9Wi_.js";
9
+ import { a as pruneBaseline, c as writeBaseline, i as buildBaseline, n as DEFAULT_BASELINE_FILE, o as readBaseline, r as applyBaseline, t as BaselineError } from "../baseline-BpE7DbDq.js";
10
+ import { a as emitDocument, c as runEngine, d as parseHeader, i as baselineInvocation, l as warn, n as auditDefaults, o as fail, r as auditInvocation, s as note, t as advise, u as basicAuth } from "../command-3r4fht5f.js";
11
11
  import { t as DEFAULT_REVIEW_FILE } from "../review-CdMK2GpQ.js";
12
- import { n as runAuditCommand, r as resolvePages, t as OUTPUT_FORMATS } from "../audit-e_uixhPG.js";
12
+ import { n as runAuditCommand, r as resolvePages, t as OUTPUT_FORMATS } from "../audit-DRjAY2iY.js";
13
13
  import { enableCompileCache } from "node:module";
14
14
  import { readFile } from "node:fs/promises";
15
15
  import path from "node:path";
@@ -155,6 +155,8 @@ const reportSchema = object({
155
155
  pages: withDefault(array(object({
156
156
  path: string(),
157
157
  error: withDefault(nullable(string()), () => null),
158
+ /** Present when the later run reused this page rather than auditing it. */
159
+ reusedFrom: optional(string()),
158
160
  violations: withDefault(array(object({
159
161
  ruleId: string(),
160
162
  impact: withDefault(nullable(string()), () => null),
@@ -205,9 +207,22 @@ function entriesOf(report) {
205
207
  }
206
208
  return entries;
207
209
  }
208
- /** Pages a run reached a verdict on. A page that errored is not one of them. */
210
+ /**
211
+ * Pages a run reached a verdict on *itself*.
212
+ *
213
+ * A page that errored is not one of them, and neither is a page whose result
214
+ * was reused from a cache: this comparison exists to say what changed between
215
+ * two runs, and a run that did not look at a page learned nothing about it. The
216
+ * difference matters in one direction only, and it is the direction that lies —
217
+ * a violation present in the earlier report and absent from a reused page would
218
+ * otherwise be announced as fixed, which is a changelog of work nobody did.
219
+ *
220
+ * A report written before reuse existed carries no marker, and is read exactly
221
+ * as it was meant when it was written: those runs audited every page they
222
+ * listed.
223
+ */
209
224
  function auditedPages(report) {
210
- return new Set(report.pages.filter((page) => page.error === null).map((page) => page.path));
225
+ return new Set(report.pages.filter((page) => page.error === null && page.reusedFrom === void 0).map((page) => page.path));
211
226
  }
212
227
  function sideOf(report) {
213
228
  return {
@@ -423,7 +438,8 @@ async function runStatementCommand(options = {}) {
423
438
  const statement = await renderStatement(config, {
424
439
  ...options.locale ? { locale: options.locale } : {},
425
440
  ...options.country ? { country: options.country } : {},
426
- ...audit ? { audit } : {}
441
+ ...audit ? { audit } : {},
442
+ ...review ? { review } : {}
427
443
  });
428
444
  note(`Statement for ${config.site.url} from ${path.basename(configPath)} (${statement.template}, ${format})`);
429
445
  if (audit) {
@@ -548,7 +564,7 @@ function parseBasicAuth(value) {
548
564
  const program = new Command();
549
565
  program.exitOverride();
550
566
  program.name("eaa-kit").description("WCAG 2.2 AA auditor and EU accessibility statement generator for static sites.\nNot legal advice.").version(TOOL_VERSION, "-v, --version");
551
- program.command("audit").description("Audit built HTML against WCAG 2.2 AA").argument("[dir]", "directory holding the built site (default: found automatically)").option("--include <globs...>", "glob patterns to audit, relative to dir").option("--exclude <globs...>", "glob patterns to skip").option("--base-url <url>", "audit pages under their real site URL").option("--url <url>", "audit a running site instead of a build directory").option("--no-build", "never run the project build or start its server").option("--per-page", "also list every page and its result").option("--manual", "what to check by hand for the rules this engine cannot evaluate").option("--coverage", "list every WCAG 2.2 A/AA criterion and what this run reached on it").option("--allow-remote", "allow --url to crawl a host that is not localhost").option("--ignore-robots", "crawl paths robots.txt disallows").option("--sitemap <path>", "where the site lists its pages, if not /sitemap.xml").option("--max-pages <n>", "stop the crawl after this many pages", parsePositive).option("--max-depth <n>", "how far from the entry URL to follow links", parseDepth).option("--header <header>", "send this header with every request, e.g. \"Authorization: Bearer …\". Repeatable", collectHeader).option("--basic-auth <user:password>", "send an Authorization header for basic auth", parseBasicAuth).option("--fail-on <impact>", `exit 1 on violations at or above this impact (${IMPACT_LEVELS.join("|")}; default: ${DEFAULT_FAIL_ON})`, parseImpact).option("--format <format>", `output format (${OUTPUT_FORMATS.join("|")}; default: console)`, parseFormat).option("--output <path>", "write the report to a file instead of stdout").option("--browser", "audit in real Chromium, covering the rules jsdom cannot evaluate").option("--fast", "skip the rules the browserless engine cannot decide anyway, losing their element lists").option("--concurrency <n>", "pages to audit at once, or 1 for none (default: from the page and core count)", parseConcurrency).option("--baseline <path>", "accept the violations recorded in this file; fail only on new ones").option("--review <path>", "what a person checked, from eaa-kit checklist").option("--review-max-age <days>", "stop counting review entries older than this", parseDepth).option("--config <path>", "take defaults from this config file, otherwise it is searched for").action(async (dir, flags) => {
567
+ program.command("audit").description("Audit built HTML against WCAG 2.2 AA").argument("[dir]", "directory holding the built site (default: found automatically)").option("--include <globs...>", "glob patterns to audit, relative to dir").option("--exclude <globs...>", "glob patterns to skip").option("--base-url <url>", "audit pages under their real site URL").option("--url <url>", "audit a running site instead of a build directory").option("--no-build", "never run the project build or start its server").option("--per-page", "also list every page and its result").option("--manual", "what to check by hand for the rules this engine cannot evaluate").option("--coverage", "list every WCAG 2.2 A/AA criterion and what this run reached on it").option("--allow-remote", "allow --url to crawl a host that is not localhost").option("--ignore-robots", "crawl paths robots.txt disallows").option("--sitemap <path>", "where the site lists its pages, if not /sitemap.xml").option("--max-pages <n>", "stop the crawl after this many pages", parsePositive).option("--max-depth <n>", "how far from the entry URL to follow links", parseDepth).option("--header <header>", "send this header with every request, e.g. \"Authorization: Bearer …\". Repeatable", collectHeader).option("--basic-auth <user:password>", "send an Authorization header for basic auth", parseBasicAuth).option("--fail-on <impact>", `exit 1 on violations at or above this impact (${IMPACT_LEVELS.join("|")}; default: ${DEFAULT_FAIL_ON})`, parseImpact).option("--format <format>", `output format (${OUTPUT_FORMATS.join("|")}; default: console)`, parseFormat).option("--output <path>", "write the report to a file instead of stdout").option("--browser", "audit in real Chromium, covering the rules jsdom cannot evaluate").option("--fast", "skip the rules the browserless engine cannot decide anyway, losing their element lists").option("--concurrency <n>", "pages to audit at once, or 1 for none (default: from the page and core count)", parseConcurrency).option("--baseline <path>", "accept the violations recorded in this file; fail only on new ones").option("--no-cache", "audit every page, reusing no result from an earlier run").option("--review <path>", "what a person checked, from eaa-kit checklist").option("--review-max-age <days>", "stop counting review entries older than this", parseDepth).option("--config <path>", "take defaults from this config file, otherwise it is searched for").action(async (dir, flags) => {
552
568
  const defaults = await auditDefaults({ ...flags.config ? { config: flags.config } : {} });
553
569
  const invocation = auditInvocation(dir, defaults, flags);
554
570
  const { exitCode } = await runAuditCommand(invocation.dir, invocation.options);
@@ -561,7 +577,7 @@ program.command("baseline").description("Record the violations a build already h
561
577
  process.exitCode = exitCode;
562
578
  });
563
579
  program.command("checklist").description("Write the manual review: the 34 WCAG criteria no automated rule can reach").option("--record <path>", `where the answers live (default: ${DEFAULT_REVIEW_FILE})`).option("--output <path>", "write the worksheet here instead of stdout").option("--reviewed-by <name>", "who is carrying out the review").action(async (flags) => {
564
- const { runChecklistCommand } = await import("../checklist-BtgkxMEa.js");
580
+ const { runChecklistCommand } = await import("../checklist-DDd9jewi.js");
565
581
  const { exitCode } = await runChecklistCommand(flags);
566
582
  process.exitCode = exitCode;
567
583
  });
@@ -570,11 +586,11 @@ program.command("diff").description("Compare two JSON reports: what a change mad
570
586
  process.exitCode = exitCode;
571
587
  });
572
588
  program.command("init").description("Write an eaa.config.json to generate statements from").option("--output <path>", "write here instead of eaa.config.json").option("--force", "overwrite a config that is already there").option("-y, --yes", "take every default without asking").action(async (flags) => {
573
- const { runInitCommand } = await import("../init-BjKYttxc.js");
589
+ const { runInitCommand } = await import("../init-DrFfzjvm.js");
574
590
  const { exitCode } = await runInitCommand(flags);
575
591
  process.exitCode = exitCode;
576
592
  });
577
- program.command("statement").description("Generate an EU accessibility statement from eaa.config").option("--config <path>", "path to the config file, otherwise it is searched for").option("--lang <locale>", `statement language (${STATEMENT_LOCALES.join("|")})`, parseLocale).option("--country <code>", `override the country template (${COUNTRIES.join("|")})`, parseCountry).option("--audit <path>", "list the barriers from an eaa-kit audit --format json report").option("--review <path>", "check the conformance claim against a review record; nothing from it is published").option("--format <format>", `output format (${STATEMENT_FORMATS.join("|")}), otherwise from the --output extension`, parseStatementFormat).option("--output <path>", "write the statement to a file instead of stdout").action(async (flags) => {
593
+ program.command("statement").description("Generate an EU accessibility statement from eaa.config").option("--config <path>", "path to the config file, otherwise it is searched for").option("--lang <locale>", `statement language (${STATEMENT_LOCALES.join("|")})`, parseLocale).option("--country <code>", `override the country template (${COUNTRIES.join("|")})`, parseCountry).option("--audit <path>", "list the barriers from an eaa-kit audit --format json report").option("--review <path>", "say how many criteria a person checked, and check the conformance claim against them").option("--format <format>", `output format (${STATEMENT_FORMATS.join("|")}), otherwise from the --output extension`, parseStatementFormat).option("--output <path>", "write the statement to a file instead of stdout").action(async (flags) => {
578
594
  const { lang, ...options } = flags;
579
595
  const { exitCode } = await runStatementCommand({
580
596
  ...options,
@@ -122,14 +122,14 @@ async function runEngine(pages, options) {
122
122
  ...options.timeoutMs === void 0 ? {} : { timeoutMs: options.timeoutMs }
123
123
  };
124
124
  if (!options.browser) {
125
- const { runPooledAudit } = await import("./pool-dkexq5xo.js");
125
+ const { runPooledAudit } = await import("./pool-B4tEUa2S.js");
126
126
  return runPooledAudit(pages, {
127
127
  ...runnerOptions,
128
128
  ...options.fast ? { fast: true } : {},
129
129
  ...options.concurrency === void 0 ? {} : { concurrency: options.concurrency }
130
130
  });
131
131
  }
132
- const { BrowserUnavailableError, runBrowserAudit } = await import("./playwright-C-miJP2b.js");
132
+ const { BrowserUnavailableError, runBrowserAudit } = await import("./playwright-ukCr_5o3.js");
133
133
  try {
134
134
  return await runBrowserAudit(options.directory, pages, {
135
135
  ...runnerOptions,
@@ -176,7 +176,7 @@ async function emitDocument(body, output, cwd) {
176
176
  * on different settings than it names would be worse than stopping.
177
177
  */
178
178
  async function auditDefaults(options = {}) {
179
- const { loadAuditConfig } = await import("./load-Bc_xDGAh.js");
179
+ const { loadAuditConfig } = await import("./load-n62iXDq_.js");
180
180
  const loaded = await loadAuditConfig({
181
181
  ...options.cwd ? { cwd: options.cwd } : {},
182
182
  ...options.config ? { path: options.config } : {}
@@ -186,8 +186,8 @@ async function auditDefaults(options = {}) {
186
186
  return loaded.audit;
187
187
  }
188
188
  function auditInvocation(dir, defaults, flags) {
189
- const { build, config: _config, header, basicAuth, ...typed } = flags;
190
- const { dir: configDir, build: configBuild, headers: _fromFile, ...fromConfig } = defaults;
189
+ const { build, cache, config: _config, header, basicAuth, ...typed } = flags;
190
+ const { dir: configDir, build: configBuild, cache: configCache, headers: _fromFile, ...fromConfig } = defaults;
191
191
  const headers = requestHeaders({
192
192
  ...header ? { header } : {},
193
193
  ...basicAuth ? { basicAuth } : {}
@@ -198,6 +198,7 @@ function auditInvocation(dir, defaults, flags) {
198
198
  ...fromConfig,
199
199
  ...typed,
200
200
  ...build === false || configBuild === false ? { noBuild: true } : {},
201
+ ...cache === false || configCache === false ? { noCache: true } : {},
201
202
  ...headers === void 0 ? {} : { headers }
202
203
  }
203
204
  };