aria-ease 2.6.0 โ 2.8.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.
- package/bin/cli.cjs +1 -1
- package/bin/cli.cjs.map +1 -1
- package/bin/cli.js +1 -1
- package/bin/cli.js.map +1 -1
- package/bin/cli.ts +1 -1
- package/dist/index.cjs +63 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +63 -10
- package/dist/index.js.map +1 -1
- package/dist/src/block/index.cjs.map +1 -1
- package/dist/src/block/index.js +1 -1
- package/dist/src/chunk-CGC24XEF.js +127 -0
- package/dist/src/chunk-CGC24XEF.js.map +1 -0
- package/dist/src/chunk-DF4OR64G.js +123 -0
- package/dist/src/chunk-DF4OR64G.js.map +1 -0
- package/dist/src/menu/index.cjs +63 -10
- package/dist/src/menu/index.cjs.map +1 -1
- package/dist/src/menu/index.js +56 -9
- package/dist/src/menu/index.js.map +1 -1
- package/package.json +1 -1
package/bin/cli.cjs
CHANGED
|
@@ -441,7 +441,7 @@ program.command("audit").description("Run axe-core powered accessibility audit o
|
|
|
441
441
|
console.log(import_chalk.default.red("\u274C No pages were successfully audited."));
|
|
442
442
|
process.exit(1);
|
|
443
443
|
}
|
|
444
|
-
console.log(import_chalk.default.green("\n\u{1F389} Great news! No accessibility violations found!"));
|
|
444
|
+
console.log(import_chalk.default.green("\n\u{1F389} Great news! No static accessibility violations found!"));
|
|
445
445
|
console.log(import_chalk.default.gray(` Audited ${auditedCount} page${auditedCount > 1 ? "s" : ""} successfully.
|
|
446
446
|
`));
|
|
447
447
|
process.exit(0);
|
package/bin/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["cli.ts","../src/utils/audit/src/audit/audit.js","../src/utils/audit/src/formatters/formatters.js","../src/utils/test/src/test.ts","configLoader.js"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { AxeResult } from \"Types\";\nimport { runAudit } from \"../src/utils/audit/src/audit/audit.js\";\nimport { formatResults } from \"../src/utils/audit/src/formatters/formatters.js\";\nimport { runTest } from \"../src/utils/test/index.js\";\nimport { loadConfig } from \"./configLoader.js\";\n\nconst program = new Command();\n\nprogram.name('aria-ease').description('Run accessibility tests and audits').version('2.2.3');\n\nprogram.command('audit')\n.description('Run axe-core powered accessibility audit on webpages')\n.option('-u, --url <url>', 'Single URL to audit')\n.option('-f, --format <format>', 'Output format for the audit report: json | csv | html | all', 'all')\n.option('-o, --out <path>', 'Directory to save the audit report', './accessibility-reports/audit')\n.action(async (opts) => {\n console.log(chalk.cyanBright('๐ Starting accessibility audit...\\n'));\n\n // Load config with robust discovery and validation\n const { config, configPath, errors } = await loadConfig(process.cwd());\n \n if (configPath) {\n console.log(chalk.green(`โ
Loaded config from ${path.basename(configPath)}\\n`));\n } else if (errors.length > 0) {\n console.log(chalk.red('โ Config file errors:\\n'));\n errors.forEach(err => console.log(chalk.red(` ${err}`)));\n console.log('');\n process.exit(1);\n } else {\n console.log(chalk.yellow('โน๏ธ No config file found, using CLI options.\\n'));\n }\n\n const urls: string[] = [];\n if(opts.url) urls.push(opts.url);\n if(config.audit?.urls && Array.isArray(config.audit.urls)) urls.push(...config.audit.urls);\n\n const format: string = (config.audit?.output && (config.audit.output as { format?: string }).format) || opts.format;\n if(!['json', 'csv', 'html', 'all'].includes(format)) {\n console.log(chalk.red('โ Invalid format. Use \"json\", \"csv\", \"html\" or \"all\".'));\n process.exit(1);\n }\n\n if(urls.length === 0) {\n console.log(chalk.red('โ No URLs provided. Use --url option or add \"urls\" in config file'));\n process.exit(1);\n }\n\n const allResults: { url: string, result?: AxeResult }[] = [];\n const auditOptions = {\n timeout: config.audit?.timeout,\n waitUntil: config.audit?.waitUntil\n };\n \n for (const url of urls) {\n console.log(chalk.yellow(`๐ Auditing: ${url}`));\n try {\n const result: AxeResult = await runAudit(url, auditOptions);\n allResults.push({ url: url, result });\n console.log(chalk.green(`โ
Completed audit for ${url}\\n`));\n } catch (error: unknown) {\n if(error instanceof Error && error.message) {\n console.log(chalk.red(`โ Failed auditing ${url}: ${error.message}`));\n }\n }\n }\n\n const hasResults = allResults.some(r => r.result && r.result.violations && r.result.violations.length > 0);\n if (!hasResults) {\n const auditedCount = allResults.filter(r => r.result).length;\n if (auditedCount === 0) {\n console.log(chalk.red('โ No pages were successfully audited.'));\n process.exit(1);\n }\n console.log(chalk.green('\\n๐ Great news! No accessibility violations found!'));\n console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? 's' : ''} successfully.\\n`));\n process.exit(0);\n }\n\n async function createReport(format: string) {\n const formatted = formatResults(allResults, format);\n\n const out = (config.audit?.output && (config.audit.output as { out?: string }).out) || opts.out;\n\n await fs.ensureDir(out);\n const d = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const timestamp = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const fileName = `ariaease-report-${timestamp}.${format}`;\n const filePath = path.join(out, fileName);\n\n await fs.writeFile(filePath, formatted, 'utf-8');\n console.log(chalk.magentaBright(`๐ Report saved to ${filePath}`));\n }\n\n if(['json', 'csv', 'html'].includes(format)) {\n await createReport(format);\n } else if(format === 'all') {\n await Promise.all(['json', 'csv', 'html'].map((format) => createReport(format)));\n }\n\n console.log(chalk.green('\\n๐ All audits completed.'));\n})\n\nprogram.command('test')\n.description('Run core a11y accessibility standard tests on UI components')\n.action(() => {\n runTest();\n})\n\nprogram.command('help')\n.description('Display help information')\n.action(() => {\n program.outputHelp();\n});\n\nprogram.parse(process.argv);","import AxeBuilder from \"@axe-core/playwright\";\nimport { chromium } from \"playwright\";\nexport async function runAudit(url, options) {\n let browser;\n // Default to 60s timeout and domcontentloaded for better reliability\n const timeout = options?.timeout || 60000;\n const waitUntil = options?.waitUntil || 'domcontentloaded';\n try {\n browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page = await context.newPage();\n await page.goto(url, { waitUntil, timeout });\n const axe = new AxeBuilder({ page });\n const axeResults = await axe.analyze();\n return axeResults;\n }\n catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"Executable doesn't exist\")) {\n console.error('\\nโ Playwright browsers not found!\\n');\n console.log('๐ฆ First-time setup required:');\n console.log(' Run: npx playwright install chromium\\n');\n console.log('๐ก This downloads the browser needed for auditing (~200MB)');\n console.log(' You only need to do this once.\\n');\n }\n else if (error.message.includes(\"page.goto: net::ERR_CONNECTION_REFUSED\")) {\n console.error('\\nโ Server Not Running!\\n');\n console.log(' Make sure your server is running before auditing URL');\n console.log(' Run: npm run dev # or your start command');\n }\n else if (error.message.includes(\"page.goto: Protocol error (Page.navigate): Cannot navigate to invalid URL\")) {\n console.error('\\nโ Cannot audit invalid URL\\n');\n }\n else {\n console.error('โ Audit error:', error.message);\n console.log(' Make sure you provide a valid URL');\n }\n }\n else {\n console.error('โ Audit error (non-Error):', String(error));\n }\n throw error;\n }\n finally {\n if (browser)\n await browser.close();\n }\n}\n","export function formatResults(allResults, format) {\n switch (format) {\n case 'json':\n return JSON.stringify(allResults.flatMap(({ url, result }) => result\n ? result.violations.flatMap(v => v.nodes.map(n => ({\n URL: url,\n Rule: v.id,\n Impact: v.impact,\n Description: v.description,\n Target: n.target,\n FailureSummary: n.failureSummary\n })))\n : []), null, 2);\n case 'csv':\n return toCSV(allResults);\n case 'html':\n return toHTML(allResults);\n default:\n return '';\n }\n}\nfunction toCSV(allResults) {\n const rows = ['URL,Rule,Impact,Description,Target,FailureSummary'];\n allResults.forEach(({ url, result }) => {\n if (result) {\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n rows.push(escapeCSV(url) + ',' +\n escapeCSV(v.id) + ',' +\n escapeCSV(v.impact) + ',' +\n escapeCSV(v.description) + ',' +\n escapeCSV(Array.isArray(n.target) ? n.target.join('; ') : String(n.target)) + ',' +\n escapeCSV(n.failureSummary ?? ''));\n });\n });\n }\n });\n return rows.join('\\n');\n}\nfunction escapeCSV(value) {\n const s = String(value ?? '');\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\nfunction toHTML(allResults) {\n const summary = {\n pagesAudited: 0,\n pagesWithViolations: 0,\n totalViolations: 0,\n distinctRules: new Set(),\n impactCounts: new Map()\n };\n allResults.forEach(({ result }) => {\n if (!result)\n return;\n summary.pagesAudited++;\n const pageViolations = result.violations.reduce((acc, v) => {\n const nodesCount = (v.nodes || []).length;\n if (nodesCount > 0) {\n summary.distinctRules.add(v.id);\n summary.totalViolations += nodesCount;\n acc += nodesCount;\n const impact = String(v.impact ?? 'unknown');\n summary.impactCounts.set(impact, (summary.impactCounts.get(impact) || 0) + nodesCount);\n }\n return acc;\n }, 0);\n if (pageViolations > 0)\n summary.pagesWithViolations++;\n });\n const rows = [];\n allResults.forEach(({ url, result }) => {\n if (!result)\n return;\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n const target = Array.isArray(n.target) ? n.target.join('; ') : String(n.target);\n rows.push(`\n <tr>\n <td class=\"nowrap\">${escapeHTML(url)}</td>\n <td class=\"nowrap\">${escapeHTML(v.id)}</td>\n <td class=\"impact ${escapeClass(String(v.impact ?? 'unknown'))}\">${escapeHTML(String(v.impact ?? ''))}</td>\n <td class=\"desc\">${escapeHTML(v.description ?? '')}</td>\n <td class=\"target\"><code>${escapeHTML(target)}</code></td>\n <td class=\"fail\">${escapeHTML(n.failureSummary ?? '').split(/\\r?\\n/).join('<br/>')}</td>\n </tr>\n `);\n });\n });\n });\n const impactSummary = Array.from(summary.impactCounts.entries()).map(([impact, count]) => `<li><strong class=\"impact ${escapeClass(impact)}\">${escapeHTML(impact)}</strong>: ${count}</li>`).join('\\n');\n const d = new Date();\n const pad = (n) => String(n).padStart(2, '0');\n const reportDateTime = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const headerSummary = `\n <section class=\"summary\">\n <h2>Report summary</h2>\n <ul>\n <li><strong>Date:</strong> ${reportDateTime}</li>\n <li><strong>Pages audited:</strong> ${summary.pagesAudited}</li>\n <li><strong>Pages with violations:</strong> ${summary.pagesWithViolations}</li>\n <li><strong>Total violations:</strong> ${summary.totalViolations}</li>\n <li><strong>Distinct rules:</strong> ${summary.distinctRules.size}</li>\n </ul>\n <div class=\"impact-summary\">\n <h3>By impact</h3>\n <ul class=\"summary-list\">\n ${impactSummary || '<li>None</li>'}\n </ul>\n </div>\n </section>\n `.trim();\n const html = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <title>Aria-Ease Accessibility Audit Report</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <style>\n :root{\n --bg:#ffffff; --muted:#6b7280; --border:#e6e9ee;\n --impact-critical: red; --impact-moderate:#fff4dd; --impact-serious:rgb(255, 123, 0);\n }\n body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:#111827; padding:24px; line-height:1.4}\n h1{margin:0 0 8px}\n .summary{background:#f8fafc;border:1px solid var(--border);padding:12px 16px;border-radius:8px;margin-bottom:18px}\n .summary ul{margin:6px 0 0 0;padding:0 18px}\n .impact-summary h3{margin:12px 0 6px}\n table{width:100%; border-collapse:collapse; margin-top:12px}\n th,td{border:1px solid var(--border); padding:10px; text-align:left; vertical-align:top}\n th{background:#f3f4f6; font-weight:600; position:sticky; top:0; z-index:1}\n .nowrap{white-space:nowrap}\n .target code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, \"Roboto Mono\", \"Courier New\", monospace; white-space:pre-wrap}\n .desc{max-width:380px}\n tr:nth-child(even){background:#fbfbfb}\n td.fail{color:#7b1e1e}\n .impact.critical{background:var(--impact-critical); font-weight:600}\n .impact.moderate{background:var(--impact-moderate); font-weight:600}\n .impact.serious{background:var(--impact-serious); font-weight:600}\n @media (max-width:900px){\n .desc{max-width:200px}\n table, thead, tbody, th, td, tr{display:block}\n thead{display:none}\n tr{margin-bottom:10px; border: 1px solid var(--border);}\n td{border:1px solid var(--border); padding:6px}\n td::before{font-weight:600; display:inline-block; width:120px}\n }\n .summary-list strong,\n .summary-list li {\n padding: 2px 4px;\n }\n </style>\n </head>\n <body>\n <h1>Aria-Ease Accessibility Audit Report</h1>\n ${headerSummary}\n <table>\n <thead>\n <tr>\n <th>URL</th><th>Rule</th><th>Impact</th><th>Description</th><th>Target</th><th>FailureSummary</th>\n </tr>\n </thead>\n <tbody>\n ${rows.join('\\n') || '<tr><td colspan=\"6\"><em>No violations found.</em></td></tr>'}\n </tbody>\n </table>\n </body>\n </html>\n `.trim();\n return html;\n}\nfunction escapeHTML(str) {\n return String(str ?? '')\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\nfunction escapeClass(s) {\n return String(s ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-');\n}\n","/**\n * Runs static and interactions accessibility test on UI components. \n * @param {HTMLElement} component The UI component to be tested\n * @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)\n*/\n\nimport { axe } from \"jest-axe\";\nimport type { JestAxeResult } from \"Types\";\nimport { runContractTests } from \"../contract/contractTestRunner\";\n\n\nexport async function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult> {\n const results = await axe(component);\n \n let contract;\n \n if (url) {\n console.log(`๐ญ Running Playwright E2E tests on ${url}`);\n const { runContractTestsPlaywright } = await import(\"../contract/contractTestRunnerPlaywright\");\n contract = await runContractTestsPlaywright(componentName, url);\n } else {\n console.log(`๐งช Running jsdom tests (limited event handling)`);\n contract = await runContractTests(componentName, component);\n }\n \n const result = {\n violations: results.violations,\n raw: results,\n contract\n };\n \n // Throw helpful error if there are failures (use counts from reporter, not raw arrays)\n if (contract.failures.length > 0) {\n const mode = url ? 'Playwright' : 'jsdom';\n \n throw new Error(\n `\\nโ ${contract.failures.length} assertion${contract.failures.length > 1 ? 's' : ''} failed (${mode} mode)\\n` +\n `โ
${contract.passes.length} assertion${contract.passes.length > 1 ? 's' : ''} passed\\n\\n` +\n `๐ Review the detailed test report above for specific failures.`\n );\n }\n \n if (results.violations.length > 0) {\n const violationCount = results.violations.length;\n throw new Error(\n `\\nโ ${violationCount} axe accessibility violation${violationCount > 1 ? 's' : ''} detected\\n\\n` +\n `๐ Check result.violations for details`\n );\n }\n \n return result;\n}\n\nlet runTest = async () => {}\n\nif (typeof window === \"undefined\") {\n runTest = async () => {\n console.log(`๐ Running component accessibility tests...\\n`);\n\n const { exec } = await import(\"child_process\");\n\n exec(\n `npx vitest --run --reporter verbose`,\n { cwd: process.cwd() },\n (error, stdout, stderr) => {\n // Always output stdout (test results)\n if (stdout) {\n console.log(stdout);\n }\n \n // Always output stderr (ContractReporter output)\n if (stderr) {\n console.error(stderr);\n }\n \n // Exit with proper code (error.code will be set if vitest failed)\n if (error && error.code) {\n process.exit(error.code);\n }\n }\n );\n }\n}\n\nexport { runTest }","import path from \"path\";\nimport fs from \"fs-extra\";\n/**\n * Validates the structure of an AriaEase config object\n * @param config - The config object to validate\n * @returns Validation result with errors if any\n */\nfunction validateConfig(config) {\n const errors = [];\n if (!config || typeof config !== 'object') {\n errors.push('Config must be an object');\n return { valid: false, errors };\n }\n const cfg = config;\n // Validate audit config if present\n if (cfg.audit !== undefined) {\n if (typeof cfg.audit !== 'object' || cfg.audit === null) {\n errors.push('audit must be an object');\n }\n else {\n // Validate urls\n if (cfg.audit.urls !== undefined) {\n if (!Array.isArray(cfg.audit.urls)) {\n errors.push('audit.urls must be an array');\n }\n else if (cfg.audit.urls.some(url => typeof url !== 'string')) {\n errors.push('audit.urls must contain only strings');\n }\n }\n // Validate output format\n if (cfg.audit.output !== undefined) {\n if (typeof cfg.audit.output !== 'object') {\n errors.push('audit.output must be an object');\n }\n else {\n const output = cfg.audit.output;\n if (output.format !== undefined) {\n if (!['json', 'csv', 'html', 'all'].includes(output.format)) {\n errors.push('audit.output.format must be one of: json, csv, html, all');\n }\n }\n if (output.out !== undefined && typeof output.out !== 'string') {\n errors.push('audit.output.out must be a string');\n }\n }\n }\n }\n }\n // Validate test config if present\n if (cfg.test !== undefined) {\n if (typeof cfg.test !== 'object' || cfg.test === null) {\n errors.push('test must be an object');\n }\n else {\n if (cfg.test.components !== undefined) {\n if (!Array.isArray(cfg.test.components)) {\n errors.push('test.components must be an array');\n }\n else {\n cfg.test.components.forEach((comp, idx) => {\n if (typeof comp !== 'object' || comp === null) {\n errors.push(`test.components[${idx}] must be an object`);\n }\n else {\n if (typeof comp.name !== 'string') {\n errors.push(`test.components[${idx}].name must be a string`);\n }\n if (typeof comp.path !== 'string') {\n errors.push(`test.components[${idx}].path must be a string`);\n }\n }\n });\n }\n }\n }\n }\n return { valid: errors.length === 0, errors };\n}\n/**\n * Attempts to load and parse a config file\n * @param filePath - Absolute path to the config file\n * @returns The parsed config or null if loading fails\n */\nasync function loadConfigFile(filePath) {\n try {\n const ext = path.extname(filePath);\n if (ext === '.json') {\n // Load JSON file\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n }\n else if (['.js', '.mjs', '.cjs', '.ts'].includes(ext)) {\n // Dynamic import for JS/TS modules\n const imported = await import(filePath);\n // Handle both default export and named exports\n return imported.default || imported;\n }\n return null;\n }\n catch {\n // Return null on any error - caller will handle\n return null;\n }\n}\n/**\n * Searches for and loads an AriaEase config file\n * Checks for config files in this order:\n * - ariaease.config.js\n * - ariaease.config.mjs\n * - ariaease.config.cjs\n * - ariaease.config.json\n * - ariaease.config.ts\n *\n * @param cwd - Current working directory to search in\n * @returns Object containing the config and any errors\n */\nexport async function loadConfig(cwd = process.cwd()) {\n const configNames = [\n 'ariaease.config.js',\n 'ariaease.config.mjs',\n 'ariaease.config.cjs',\n 'ariaease.config.json',\n 'ariaease.config.ts'\n ];\n let loadedConfig = null;\n let foundPath = null;\n const errors = [];\n // Try to find and load config\n for (const name of configNames) {\n const configPath = path.resolve(cwd, name);\n if (await fs.pathExists(configPath)) {\n foundPath = configPath;\n loadedConfig = await loadConfigFile(configPath);\n if (loadedConfig === null) {\n errors.push(`Found config at ${name} but failed to load it. Check for syntax errors.`);\n continue;\n }\n // Validate the loaded config\n const validation = validateConfig(loadedConfig);\n if (!validation.valid) {\n errors.push(`Config validation failed in ${name}:`);\n errors.push(...validation.errors.map(err => ` - ${err}`));\n loadedConfig = null;\n continue;\n }\n // Successfully loaded and validated\n break;\n }\n }\n return {\n config: loadedConfig || {},\n configPath: loadedConfig ? foundPath : null,\n errors\n };\n}\n"],"mappings":"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","names":["import_path","import_fs_extra","import_playwright","axe","AxeBuilder","path","fs","chalk","path","format","fs"]}
|
|
1
|
+
{"version":3,"sources":["cli.ts","../src/utils/audit/src/audit/audit.js","../src/utils/audit/src/formatters/formatters.js","../src/utils/test/src/test.ts","configLoader.js"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { AxeResult } from \"Types\";\nimport { runAudit } from \"../src/utils/audit/src/audit/audit.js\";\nimport { formatResults } from \"../src/utils/audit/src/formatters/formatters.js\";\nimport { runTest } from \"../src/utils/test/index.js\";\nimport { loadConfig } from \"./configLoader.js\";\n\nconst program = new Command();\n\nprogram.name('aria-ease').description('Run accessibility tests and audits').version('2.2.3');\n\nprogram.command('audit')\n.description('Run axe-core powered accessibility audit on webpages')\n.option('-u, --url <url>', 'Single URL to audit')\n.option('-f, --format <format>', 'Output format for the audit report: json | csv | html | all', 'all')\n.option('-o, --out <path>', 'Directory to save the audit report', './accessibility-reports/audit')\n.action(async (opts) => {\n console.log(chalk.cyanBright('๐ Starting accessibility audit...\\n'));\n\n // Load config with robust discovery and validation\n const { config, configPath, errors } = await loadConfig(process.cwd());\n \n if (configPath) {\n console.log(chalk.green(`โ
Loaded config from ${path.basename(configPath)}\\n`));\n } else if (errors.length > 0) {\n console.log(chalk.red('โ Config file errors:\\n'));\n errors.forEach(err => console.log(chalk.red(` ${err}`)));\n console.log('');\n process.exit(1);\n } else {\n console.log(chalk.yellow('โน๏ธ No config file found, using CLI options.\\n'));\n }\n\n const urls: string[] = [];\n if(opts.url) urls.push(opts.url);\n if(config.audit?.urls && Array.isArray(config.audit.urls)) urls.push(...config.audit.urls);\n\n const format: string = (config.audit?.output && (config.audit.output as { format?: string }).format) || opts.format;\n if(!['json', 'csv', 'html', 'all'].includes(format)) {\n console.log(chalk.red('โ Invalid format. Use \"json\", \"csv\", \"html\" or \"all\".'));\n process.exit(1);\n }\n\n if(urls.length === 0) {\n console.log(chalk.red('โ No URLs provided. Use --url option or add \"urls\" in config file'));\n process.exit(1);\n }\n\n const allResults: { url: string, result?: AxeResult }[] = [];\n const auditOptions = {\n timeout: config.audit?.timeout,\n waitUntil: config.audit?.waitUntil\n };\n \n for (const url of urls) {\n console.log(chalk.yellow(`๐ Auditing: ${url}`));\n try {\n const result: AxeResult = await runAudit(url, auditOptions);\n allResults.push({ url: url, result });\n console.log(chalk.green(`โ
Completed audit for ${url}\\n`));\n } catch (error: unknown) {\n if(error instanceof Error && error.message) {\n console.log(chalk.red(`โ Failed auditing ${url}: ${error.message}`));\n }\n }\n }\n\n const hasResults = allResults.some(r => r.result && r.result.violations && r.result.violations.length > 0);\n if (!hasResults) {\n const auditedCount = allResults.filter(r => r.result).length;\n if (auditedCount === 0) {\n console.log(chalk.red('โ No pages were successfully audited.'));\n process.exit(1);\n }\n console.log(chalk.green('\\n๐ Great news! No static accessibility violations found!'));\n console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? 's' : ''} successfully.\\n`));\n process.exit(0);\n }\n\n async function createReport(format: string) {\n const formatted = formatResults(allResults, format);\n\n const out = (config.audit?.output && (config.audit.output as { out?: string }).out) || opts.out;\n\n await fs.ensureDir(out);\n const d = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const timestamp = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const fileName = `ariaease-report-${timestamp}.${format}`;\n const filePath = path.join(out, fileName);\n\n await fs.writeFile(filePath, formatted, 'utf-8');\n console.log(chalk.magentaBright(`๐ Report saved to ${filePath}`));\n }\n\n if(['json', 'csv', 'html'].includes(format)) {\n await createReport(format);\n } else if(format === 'all') {\n await Promise.all(['json', 'csv', 'html'].map((format) => createReport(format)));\n }\n\n console.log(chalk.green('\\n๐ All audits completed.'));\n})\n\nprogram.command('test')\n.description('Run core a11y accessibility standard tests on UI components')\n.action(() => {\n runTest();\n})\n\nprogram.command('help')\n.description('Display help information')\n.action(() => {\n program.outputHelp();\n});\n\nprogram.parse(process.argv);","import AxeBuilder from \"@axe-core/playwright\";\nimport { chromium } from \"playwright\";\nexport async function runAudit(url, options) {\n let browser;\n // Default to 60s timeout and domcontentloaded for better reliability\n const timeout = options?.timeout || 60000;\n const waitUntil = options?.waitUntil || 'domcontentloaded';\n try {\n browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page = await context.newPage();\n await page.goto(url, { waitUntil, timeout });\n const axe = new AxeBuilder({ page });\n const axeResults = await axe.analyze();\n return axeResults;\n }\n catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"Executable doesn't exist\")) {\n console.error('\\nโ Playwright browsers not found!\\n');\n console.log('๐ฆ First-time setup required:');\n console.log(' Run: npx playwright install chromium\\n');\n console.log('๐ก This downloads the browser needed for auditing (~200MB)');\n console.log(' You only need to do this once.\\n');\n }\n else if (error.message.includes(\"page.goto: net::ERR_CONNECTION_REFUSED\")) {\n console.error('\\nโ Server Not Running!\\n');\n console.log(' Make sure your server is running before auditing URL');\n console.log(' Run: npm run dev # or your start command');\n }\n else if (error.message.includes(\"page.goto: Protocol error (Page.navigate): Cannot navigate to invalid URL\")) {\n console.error('\\nโ Cannot audit invalid URL\\n');\n }\n else {\n console.error('โ Audit error:', error.message);\n console.log(' Make sure you provide a valid URL');\n }\n }\n else {\n console.error('โ Audit error (non-Error):', String(error));\n }\n throw error;\n }\n finally {\n if (browser)\n await browser.close();\n }\n}\n","export function formatResults(allResults, format) {\n switch (format) {\n case 'json':\n return JSON.stringify(allResults.flatMap(({ url, result }) => result\n ? result.violations.flatMap(v => v.nodes.map(n => ({\n URL: url,\n Rule: v.id,\n Impact: v.impact,\n Description: v.description,\n Target: n.target,\n FailureSummary: n.failureSummary\n })))\n : []), null, 2);\n case 'csv':\n return toCSV(allResults);\n case 'html':\n return toHTML(allResults);\n default:\n return '';\n }\n}\nfunction toCSV(allResults) {\n const rows = ['URL,Rule,Impact,Description,Target,FailureSummary'];\n allResults.forEach(({ url, result }) => {\n if (result) {\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n rows.push(escapeCSV(url) + ',' +\n escapeCSV(v.id) + ',' +\n escapeCSV(v.impact) + ',' +\n escapeCSV(v.description) + ',' +\n escapeCSV(Array.isArray(n.target) ? n.target.join('; ') : String(n.target)) + ',' +\n escapeCSV(n.failureSummary ?? ''));\n });\n });\n }\n });\n return rows.join('\\n');\n}\nfunction escapeCSV(value) {\n const s = String(value ?? '');\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\nfunction toHTML(allResults) {\n const summary = {\n pagesAudited: 0,\n pagesWithViolations: 0,\n totalViolations: 0,\n distinctRules: new Set(),\n impactCounts: new Map()\n };\n allResults.forEach(({ result }) => {\n if (!result)\n return;\n summary.pagesAudited++;\n const pageViolations = result.violations.reduce((acc, v) => {\n const nodesCount = (v.nodes || []).length;\n if (nodesCount > 0) {\n summary.distinctRules.add(v.id);\n summary.totalViolations += nodesCount;\n acc += nodesCount;\n const impact = String(v.impact ?? 'unknown');\n summary.impactCounts.set(impact, (summary.impactCounts.get(impact) || 0) + nodesCount);\n }\n return acc;\n }, 0);\n if (pageViolations > 0)\n summary.pagesWithViolations++;\n });\n const rows = [];\n allResults.forEach(({ url, result }) => {\n if (!result)\n return;\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n const target = Array.isArray(n.target) ? n.target.join('; ') : String(n.target);\n rows.push(`\n <tr>\n <td class=\"nowrap\">${escapeHTML(url)}</td>\n <td class=\"nowrap\">${escapeHTML(v.id)}</td>\n <td class=\"impact ${escapeClass(String(v.impact ?? 'unknown'))}\">${escapeHTML(String(v.impact ?? ''))}</td>\n <td class=\"desc\">${escapeHTML(v.description ?? '')}</td>\n <td class=\"target\"><code>${escapeHTML(target)}</code></td>\n <td class=\"fail\">${escapeHTML(n.failureSummary ?? '').split(/\\r?\\n/).join('<br/>')}</td>\n </tr>\n `);\n });\n });\n });\n const impactSummary = Array.from(summary.impactCounts.entries()).map(([impact, count]) => `<li><strong class=\"impact ${escapeClass(impact)}\">${escapeHTML(impact)}</strong>: ${count}</li>`).join('\\n');\n const d = new Date();\n const pad = (n) => String(n).padStart(2, '0');\n const reportDateTime = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const headerSummary = `\n <section class=\"summary\">\n <h2>Report summary</h2>\n <ul>\n <li><strong>Date:</strong> ${reportDateTime}</li>\n <li><strong>Pages audited:</strong> ${summary.pagesAudited}</li>\n <li><strong>Pages with violations:</strong> ${summary.pagesWithViolations}</li>\n <li><strong>Total violations:</strong> ${summary.totalViolations}</li>\n <li><strong>Distinct rules:</strong> ${summary.distinctRules.size}</li>\n </ul>\n <div class=\"impact-summary\">\n <h3>By impact</h3>\n <ul class=\"summary-list\">\n ${impactSummary || '<li>None</li>'}\n </ul>\n </div>\n </section>\n `.trim();\n const html = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <title>Aria-Ease Accessibility Audit Report</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <style>\n :root{\n --bg:#ffffff; --muted:#6b7280; --border:#e6e9ee;\n --impact-critical: red; --impact-moderate:#fff4dd; --impact-serious:rgb(255, 123, 0);\n }\n body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:#111827; padding:24px; line-height:1.4}\n h1{margin:0 0 8px}\n .summary{background:#f8fafc;border:1px solid var(--border);padding:12px 16px;border-radius:8px;margin-bottom:18px}\n .summary ul{margin:6px 0 0 0;padding:0 18px}\n .impact-summary h3{margin:12px 0 6px}\n table{width:100%; border-collapse:collapse; margin-top:12px}\n th,td{border:1px solid var(--border); padding:10px; text-align:left; vertical-align:top}\n th{background:#f3f4f6; font-weight:600; position:sticky; top:0; z-index:1}\n .nowrap{white-space:nowrap}\n .target code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, \"Roboto Mono\", \"Courier New\", monospace; white-space:pre-wrap}\n .desc{max-width:380px}\n tr:nth-child(even){background:#fbfbfb}\n td.fail{color:#7b1e1e}\n .impact.critical{background:var(--impact-critical); font-weight:600}\n .impact.moderate{background:var(--impact-moderate); font-weight:600}\n .impact.serious{background:var(--impact-serious); font-weight:600}\n @media (max-width:900px){\n .desc{max-width:200px}\n table, thead, tbody, th, td, tr{display:block}\n thead{display:none}\n tr{margin-bottom:10px; border: 1px solid var(--border);}\n td{border:1px solid var(--border); padding:6px}\n td::before{font-weight:600; display:inline-block; width:120px}\n }\n .summary-list strong,\n .summary-list li {\n padding: 2px 4px;\n }\n </style>\n </head>\n <body>\n <h1>Aria-Ease Accessibility Audit Report</h1>\n ${headerSummary}\n <table>\n <thead>\n <tr>\n <th>URL</th><th>Rule</th><th>Impact</th><th>Description</th><th>Target</th><th>FailureSummary</th>\n </tr>\n </thead>\n <tbody>\n ${rows.join('\\n') || '<tr><td colspan=\"6\"><em>No violations found.</em></td></tr>'}\n </tbody>\n </table>\n </body>\n </html>\n `.trim();\n return html;\n}\nfunction escapeHTML(str) {\n return String(str ?? '')\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\nfunction escapeClass(s) {\n return String(s ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-');\n}\n","/**\n * Runs static and interactions accessibility test on UI components. \n * @param {HTMLElement} component The UI component to be tested\n * @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)\n*/\n\nimport { axe } from \"jest-axe\";\nimport type { JestAxeResult } from \"Types\";\nimport { runContractTests } from \"../contract/contractTestRunner\";\n\n\nexport async function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult> {\n const results = await axe(component);\n \n let contract;\n \n if (url) {\n console.log(`๐ญ Running Playwright E2E tests on ${url}`);\n const { runContractTestsPlaywright } = await import(\"../contract/contractTestRunnerPlaywright\");\n contract = await runContractTestsPlaywright(componentName, url);\n } else {\n console.log(`๐งช Running jsdom tests (limited event handling)`);\n contract = await runContractTests(componentName, component);\n }\n \n const result = {\n violations: results.violations,\n raw: results,\n contract\n };\n \n // Throw helpful error if there are failures (use counts from reporter, not raw arrays)\n if (contract.failures.length > 0) {\n const mode = url ? 'Playwright' : 'jsdom';\n \n throw new Error(\n `\\nโ ${contract.failures.length} assertion${contract.failures.length > 1 ? 's' : ''} failed (${mode} mode)\\n` +\n `โ
${contract.passes.length} assertion${contract.passes.length > 1 ? 's' : ''} passed\\n\\n` +\n `๐ Review the detailed test report above for specific failures.`\n );\n }\n \n if (results.violations.length > 0) {\n const violationCount = results.violations.length;\n throw new Error(\n `\\nโ ${violationCount} axe accessibility violation${violationCount > 1 ? 's' : ''} detected\\n\\n` +\n `๐ Check result.violations for details`\n );\n }\n \n return result;\n}\n\nlet runTest = async () => {}\n\nif (typeof window === \"undefined\") {\n runTest = async () => {\n console.log(`๐ Running component accessibility tests...\\n`);\n\n const { exec } = await import(\"child_process\");\n\n exec(\n `npx vitest --run --reporter verbose`,\n { cwd: process.cwd() },\n (error, stdout, stderr) => {\n // Always output stdout (test results)\n if (stdout) {\n console.log(stdout);\n }\n \n // Always output stderr (ContractReporter output)\n if (stderr) {\n console.error(stderr);\n }\n \n // Exit with proper code (error.code will be set if vitest failed)\n if (error && error.code) {\n process.exit(error.code);\n }\n }\n );\n }\n}\n\nexport { runTest }","import path from \"path\";\nimport fs from \"fs-extra\";\n/**\n * Validates the structure of an AriaEase config object\n * @param config - The config object to validate\n * @returns Validation result with errors if any\n */\nfunction validateConfig(config) {\n const errors = [];\n if (!config || typeof config !== 'object') {\n errors.push('Config must be an object');\n return { valid: false, errors };\n }\n const cfg = config;\n // Validate audit config if present\n if (cfg.audit !== undefined) {\n if (typeof cfg.audit !== 'object' || cfg.audit === null) {\n errors.push('audit must be an object');\n }\n else {\n // Validate urls\n if (cfg.audit.urls !== undefined) {\n if (!Array.isArray(cfg.audit.urls)) {\n errors.push('audit.urls must be an array');\n }\n else if (cfg.audit.urls.some(url => typeof url !== 'string')) {\n errors.push('audit.urls must contain only strings');\n }\n }\n // Validate output format\n if (cfg.audit.output !== undefined) {\n if (typeof cfg.audit.output !== 'object') {\n errors.push('audit.output must be an object');\n }\n else {\n const output = cfg.audit.output;\n if (output.format !== undefined) {\n if (!['json', 'csv', 'html', 'all'].includes(output.format)) {\n errors.push('audit.output.format must be one of: json, csv, html, all');\n }\n }\n if (output.out !== undefined && typeof output.out !== 'string') {\n errors.push('audit.output.out must be a string');\n }\n }\n }\n }\n }\n // Validate test config if present\n if (cfg.test !== undefined) {\n if (typeof cfg.test !== 'object' || cfg.test === null) {\n errors.push('test must be an object');\n }\n else {\n if (cfg.test.components !== undefined) {\n if (!Array.isArray(cfg.test.components)) {\n errors.push('test.components must be an array');\n }\n else {\n cfg.test.components.forEach((comp, idx) => {\n if (typeof comp !== 'object' || comp === null) {\n errors.push(`test.components[${idx}] must be an object`);\n }\n else {\n if (typeof comp.name !== 'string') {\n errors.push(`test.components[${idx}].name must be a string`);\n }\n if (typeof comp.path !== 'string') {\n errors.push(`test.components[${idx}].path must be a string`);\n }\n }\n });\n }\n }\n }\n }\n return { valid: errors.length === 0, errors };\n}\n/**\n * Attempts to load and parse a config file\n * @param filePath - Absolute path to the config file\n * @returns The parsed config or null if loading fails\n */\nasync function loadConfigFile(filePath) {\n try {\n const ext = path.extname(filePath);\n if (ext === '.json') {\n // Load JSON file\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n }\n else if (['.js', '.mjs', '.cjs', '.ts'].includes(ext)) {\n // Dynamic import for JS/TS modules\n const imported = await import(filePath);\n // Handle both default export and named exports\n return imported.default || imported;\n }\n return null;\n }\n catch {\n // Return null on any error - caller will handle\n return null;\n }\n}\n/**\n * Searches for and loads an AriaEase config file\n * Checks for config files in this order:\n * - ariaease.config.js\n * - ariaease.config.mjs\n * - ariaease.config.cjs\n * - ariaease.config.json\n * - ariaease.config.ts\n *\n * @param cwd - Current working directory to search in\n * @returns Object containing the config and any errors\n */\nexport async function loadConfig(cwd = process.cwd()) {\n const configNames = [\n 'ariaease.config.js',\n 'ariaease.config.mjs',\n 'ariaease.config.cjs',\n 'ariaease.config.json',\n 'ariaease.config.ts'\n ];\n let loadedConfig = null;\n let foundPath = null;\n const errors = [];\n // Try to find and load config\n for (const name of configNames) {\n const configPath = path.resolve(cwd, name);\n if (await fs.pathExists(configPath)) {\n foundPath = configPath;\n loadedConfig = await loadConfigFile(configPath);\n if (loadedConfig === null) {\n errors.push(`Found config at ${name} but failed to load it. Check for syntax errors.`);\n continue;\n }\n // Validate the loaded config\n const validation = validateConfig(loadedConfig);\n if (!validation.valid) {\n errors.push(`Config validation failed in ${name}:`);\n errors.push(...validation.errors.map(err => ` - ${err}`));\n loadedConfig = null;\n continue;\n }\n // Successfully loaded and validated\n break;\n }\n }\n return {\n config: loadedConfig || {},\n configPath: loadedConfig ? foundPath : null,\n errors\n };\n}\n"],"mappings":"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","names":["import_path","import_fs_extra","import_playwright","axe","AxeBuilder","path","fs","chalk","path","format","fs"]}
|
package/bin/cli.js
CHANGED
|
@@ -418,7 +418,7 @@ program.command("audit").description("Run axe-core powered accessibility audit o
|
|
|
418
418
|
console.log(chalk.red("\u274C No pages were successfully audited."));
|
|
419
419
|
process.exit(1);
|
|
420
420
|
}
|
|
421
|
-
console.log(chalk.green("\n\u{1F389} Great news! No accessibility violations found!"));
|
|
421
|
+
console.log(chalk.green("\n\u{1F389} Great news! No static accessibility violations found!"));
|
|
422
422
|
console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? "s" : ""} successfully.
|
|
423
423
|
`));
|
|
424
424
|
process.exit(0);
|
package/bin/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["cli.ts","../src/utils/audit/src/audit/audit.js","../src/utils/audit/src/formatters/formatters.js","../src/utils/test/src/test.ts","configLoader.js"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { AxeResult } from \"Types\";\nimport { runAudit } from \"../src/utils/audit/src/audit/audit.js\";\nimport { formatResults } from \"../src/utils/audit/src/formatters/formatters.js\";\nimport { runTest } from \"../src/utils/test/index.js\";\nimport { loadConfig } from \"./configLoader.js\";\n\nconst program = new Command();\n\nprogram.name('aria-ease').description('Run accessibility tests and audits').version('2.2.3');\n\nprogram.command('audit')\n.description('Run axe-core powered accessibility audit on webpages')\n.option('-u, --url <url>', 'Single URL to audit')\n.option('-f, --format <format>', 'Output format for the audit report: json | csv | html | all', 'all')\n.option('-o, --out <path>', 'Directory to save the audit report', './accessibility-reports/audit')\n.action(async (opts) => {\n console.log(chalk.cyanBright('๐ Starting accessibility audit...\\n'));\n\n // Load config with robust discovery and validation\n const { config, configPath, errors } = await loadConfig(process.cwd());\n \n if (configPath) {\n console.log(chalk.green(`โ
Loaded config from ${path.basename(configPath)}\\n`));\n } else if (errors.length > 0) {\n console.log(chalk.red('โ Config file errors:\\n'));\n errors.forEach(err => console.log(chalk.red(` ${err}`)));\n console.log('');\n process.exit(1);\n } else {\n console.log(chalk.yellow('โน๏ธ No config file found, using CLI options.\\n'));\n }\n\n const urls: string[] = [];\n if(opts.url) urls.push(opts.url);\n if(config.audit?.urls && Array.isArray(config.audit.urls)) urls.push(...config.audit.urls);\n\n const format: string = (config.audit?.output && (config.audit.output as { format?: string }).format) || opts.format;\n if(!['json', 'csv', 'html', 'all'].includes(format)) {\n console.log(chalk.red('โ Invalid format. Use \"json\", \"csv\", \"html\" or \"all\".'));\n process.exit(1);\n }\n\n if(urls.length === 0) {\n console.log(chalk.red('โ No URLs provided. Use --url option or add \"urls\" in config file'));\n process.exit(1);\n }\n\n const allResults: { url: string, result?: AxeResult }[] = [];\n const auditOptions = {\n timeout: config.audit?.timeout,\n waitUntil: config.audit?.waitUntil\n };\n \n for (const url of urls) {\n console.log(chalk.yellow(`๐ Auditing: ${url}`));\n try {\n const result: AxeResult = await runAudit(url, auditOptions);\n allResults.push({ url: url, result });\n console.log(chalk.green(`โ
Completed audit for ${url}\\n`));\n } catch (error: unknown) {\n if(error instanceof Error && error.message) {\n console.log(chalk.red(`โ Failed auditing ${url}: ${error.message}`));\n }\n }\n }\n\n const hasResults = allResults.some(r => r.result && r.result.violations && r.result.violations.length > 0);\n if (!hasResults) {\n const auditedCount = allResults.filter(r => r.result).length;\n if (auditedCount === 0) {\n console.log(chalk.red('โ No pages were successfully audited.'));\n process.exit(1);\n }\n console.log(chalk.green('\\n๐ Great news! No accessibility violations found!'));\n console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? 's' : ''} successfully.\\n`));\n process.exit(0);\n }\n\n async function createReport(format: string) {\n const formatted = formatResults(allResults, format);\n\n const out = (config.audit?.output && (config.audit.output as { out?: string }).out) || opts.out;\n\n await fs.ensureDir(out);\n const d = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const timestamp = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const fileName = `ariaease-report-${timestamp}.${format}`;\n const filePath = path.join(out, fileName);\n\n await fs.writeFile(filePath, formatted, 'utf-8');\n console.log(chalk.magentaBright(`๐ Report saved to ${filePath}`));\n }\n\n if(['json', 'csv', 'html'].includes(format)) {\n await createReport(format);\n } else if(format === 'all') {\n await Promise.all(['json', 'csv', 'html'].map((format) => createReport(format)));\n }\n\n console.log(chalk.green('\\n๐ All audits completed.'));\n})\n\nprogram.command('test')\n.description('Run core a11y accessibility standard tests on UI components')\n.action(() => {\n runTest();\n})\n\nprogram.command('help')\n.description('Display help information')\n.action(() => {\n program.outputHelp();\n});\n\nprogram.parse(process.argv);","import AxeBuilder from \"@axe-core/playwright\";\nimport { chromium } from \"playwright\";\nexport async function runAudit(url, options) {\n let browser;\n // Default to 60s timeout and domcontentloaded for better reliability\n const timeout = options?.timeout || 60000;\n const waitUntil = options?.waitUntil || 'domcontentloaded';\n try {\n browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page = await context.newPage();\n await page.goto(url, { waitUntil, timeout });\n const axe = new AxeBuilder({ page });\n const axeResults = await axe.analyze();\n return axeResults;\n }\n catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"Executable doesn't exist\")) {\n console.error('\\nโ Playwright browsers not found!\\n');\n console.log('๐ฆ First-time setup required:');\n console.log(' Run: npx playwright install chromium\\n');\n console.log('๐ก This downloads the browser needed for auditing (~200MB)');\n console.log(' You only need to do this once.\\n');\n }\n else if (error.message.includes(\"page.goto: net::ERR_CONNECTION_REFUSED\")) {\n console.error('\\nโ Server Not Running!\\n');\n console.log(' Make sure your server is running before auditing URL');\n console.log(' Run: npm run dev # or your start command');\n }\n else if (error.message.includes(\"page.goto: Protocol error (Page.navigate): Cannot navigate to invalid URL\")) {\n console.error('\\nโ Cannot audit invalid URL\\n');\n }\n else {\n console.error('โ Audit error:', error.message);\n console.log(' Make sure you provide a valid URL');\n }\n }\n else {\n console.error('โ Audit error (non-Error):', String(error));\n }\n throw error;\n }\n finally {\n if (browser)\n await browser.close();\n }\n}\n","export function formatResults(allResults, format) {\n switch (format) {\n case 'json':\n return JSON.stringify(allResults.flatMap(({ url, result }) => result\n ? result.violations.flatMap(v => v.nodes.map(n => ({\n URL: url,\n Rule: v.id,\n Impact: v.impact,\n Description: v.description,\n Target: n.target,\n FailureSummary: n.failureSummary\n })))\n : []), null, 2);\n case 'csv':\n return toCSV(allResults);\n case 'html':\n return toHTML(allResults);\n default:\n return '';\n }\n}\nfunction toCSV(allResults) {\n const rows = ['URL,Rule,Impact,Description,Target,FailureSummary'];\n allResults.forEach(({ url, result }) => {\n if (result) {\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n rows.push(escapeCSV(url) + ',' +\n escapeCSV(v.id) + ',' +\n escapeCSV(v.impact) + ',' +\n escapeCSV(v.description) + ',' +\n escapeCSV(Array.isArray(n.target) ? n.target.join('; ') : String(n.target)) + ',' +\n escapeCSV(n.failureSummary ?? ''));\n });\n });\n }\n });\n return rows.join('\\n');\n}\nfunction escapeCSV(value) {\n const s = String(value ?? '');\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\nfunction toHTML(allResults) {\n const summary = {\n pagesAudited: 0,\n pagesWithViolations: 0,\n totalViolations: 0,\n distinctRules: new Set(),\n impactCounts: new Map()\n };\n allResults.forEach(({ result }) => {\n if (!result)\n return;\n summary.pagesAudited++;\n const pageViolations = result.violations.reduce((acc, v) => {\n const nodesCount = (v.nodes || []).length;\n if (nodesCount > 0) {\n summary.distinctRules.add(v.id);\n summary.totalViolations += nodesCount;\n acc += nodesCount;\n const impact = String(v.impact ?? 'unknown');\n summary.impactCounts.set(impact, (summary.impactCounts.get(impact) || 0) + nodesCount);\n }\n return acc;\n }, 0);\n if (pageViolations > 0)\n summary.pagesWithViolations++;\n });\n const rows = [];\n allResults.forEach(({ url, result }) => {\n if (!result)\n return;\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n const target = Array.isArray(n.target) ? n.target.join('; ') : String(n.target);\n rows.push(`\n <tr>\n <td class=\"nowrap\">${escapeHTML(url)}</td>\n <td class=\"nowrap\">${escapeHTML(v.id)}</td>\n <td class=\"impact ${escapeClass(String(v.impact ?? 'unknown'))}\">${escapeHTML(String(v.impact ?? ''))}</td>\n <td class=\"desc\">${escapeHTML(v.description ?? '')}</td>\n <td class=\"target\"><code>${escapeHTML(target)}</code></td>\n <td class=\"fail\">${escapeHTML(n.failureSummary ?? '').split(/\\r?\\n/).join('<br/>')}</td>\n </tr>\n `);\n });\n });\n });\n const impactSummary = Array.from(summary.impactCounts.entries()).map(([impact, count]) => `<li><strong class=\"impact ${escapeClass(impact)}\">${escapeHTML(impact)}</strong>: ${count}</li>`).join('\\n');\n const d = new Date();\n const pad = (n) => String(n).padStart(2, '0');\n const reportDateTime = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const headerSummary = `\n <section class=\"summary\">\n <h2>Report summary</h2>\n <ul>\n <li><strong>Date:</strong> ${reportDateTime}</li>\n <li><strong>Pages audited:</strong> ${summary.pagesAudited}</li>\n <li><strong>Pages with violations:</strong> ${summary.pagesWithViolations}</li>\n <li><strong>Total violations:</strong> ${summary.totalViolations}</li>\n <li><strong>Distinct rules:</strong> ${summary.distinctRules.size}</li>\n </ul>\n <div class=\"impact-summary\">\n <h3>By impact</h3>\n <ul class=\"summary-list\">\n ${impactSummary || '<li>None</li>'}\n </ul>\n </div>\n </section>\n `.trim();\n const html = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <title>Aria-Ease Accessibility Audit Report</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <style>\n :root{\n --bg:#ffffff; --muted:#6b7280; --border:#e6e9ee;\n --impact-critical: red; --impact-moderate:#fff4dd; --impact-serious:rgb(255, 123, 0);\n }\n body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:#111827; padding:24px; line-height:1.4}\n h1{margin:0 0 8px}\n .summary{background:#f8fafc;border:1px solid var(--border);padding:12px 16px;border-radius:8px;margin-bottom:18px}\n .summary ul{margin:6px 0 0 0;padding:0 18px}\n .impact-summary h3{margin:12px 0 6px}\n table{width:100%; border-collapse:collapse; margin-top:12px}\n th,td{border:1px solid var(--border); padding:10px; text-align:left; vertical-align:top}\n th{background:#f3f4f6; font-weight:600; position:sticky; top:0; z-index:1}\n .nowrap{white-space:nowrap}\n .target code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, \"Roboto Mono\", \"Courier New\", monospace; white-space:pre-wrap}\n .desc{max-width:380px}\n tr:nth-child(even){background:#fbfbfb}\n td.fail{color:#7b1e1e}\n .impact.critical{background:var(--impact-critical); font-weight:600}\n .impact.moderate{background:var(--impact-moderate); font-weight:600}\n .impact.serious{background:var(--impact-serious); font-weight:600}\n @media (max-width:900px){\n .desc{max-width:200px}\n table, thead, tbody, th, td, tr{display:block}\n thead{display:none}\n tr{margin-bottom:10px; border: 1px solid var(--border);}\n td{border:1px solid var(--border); padding:6px}\n td::before{font-weight:600; display:inline-block; width:120px}\n }\n .summary-list strong,\n .summary-list li {\n padding: 2px 4px;\n }\n </style>\n </head>\n <body>\n <h1>Aria-Ease Accessibility Audit Report</h1>\n ${headerSummary}\n <table>\n <thead>\n <tr>\n <th>URL</th><th>Rule</th><th>Impact</th><th>Description</th><th>Target</th><th>FailureSummary</th>\n </tr>\n </thead>\n <tbody>\n ${rows.join('\\n') || '<tr><td colspan=\"6\"><em>No violations found.</em></td></tr>'}\n </tbody>\n </table>\n </body>\n </html>\n `.trim();\n return html;\n}\nfunction escapeHTML(str) {\n return String(str ?? '')\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\nfunction escapeClass(s) {\n return String(s ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-');\n}\n","/**\n * Runs static and interactions accessibility test on UI components. \n * @param {HTMLElement} component The UI component to be tested\n * @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)\n*/\n\nimport { axe } from \"jest-axe\";\nimport type { JestAxeResult } from \"Types\";\nimport { runContractTests } from \"../contract/contractTestRunner\";\n\n\nexport async function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult> {\n const results = await axe(component);\n \n let contract;\n \n if (url) {\n console.log(`๐ญ Running Playwright E2E tests on ${url}`);\n const { runContractTestsPlaywright } = await import(\"../contract/contractTestRunnerPlaywright\");\n contract = await runContractTestsPlaywright(componentName, url);\n } else {\n console.log(`๐งช Running jsdom tests (limited event handling)`);\n contract = await runContractTests(componentName, component);\n }\n \n const result = {\n violations: results.violations,\n raw: results,\n contract\n };\n \n // Throw helpful error if there are failures (use counts from reporter, not raw arrays)\n if (contract.failures.length > 0) {\n const mode = url ? 'Playwright' : 'jsdom';\n \n throw new Error(\n `\\nโ ${contract.failures.length} assertion${contract.failures.length > 1 ? 's' : ''} failed (${mode} mode)\\n` +\n `โ
${contract.passes.length} assertion${contract.passes.length > 1 ? 's' : ''} passed\\n\\n` +\n `๐ Review the detailed test report above for specific failures.`\n );\n }\n \n if (results.violations.length > 0) {\n const violationCount = results.violations.length;\n throw new Error(\n `\\nโ ${violationCount} axe accessibility violation${violationCount > 1 ? 's' : ''} detected\\n\\n` +\n `๐ Check result.violations for details`\n );\n }\n \n return result;\n}\n\nlet runTest = async () => {}\n\nif (typeof window === \"undefined\") {\n runTest = async () => {\n console.log(`๐ Running component accessibility tests...\\n`);\n\n const { exec } = await import(\"child_process\");\n\n exec(\n `npx vitest --run --reporter verbose`,\n { cwd: process.cwd() },\n (error, stdout, stderr) => {\n // Always output stdout (test results)\n if (stdout) {\n console.log(stdout);\n }\n \n // Always output stderr (ContractReporter output)\n if (stderr) {\n console.error(stderr);\n }\n \n // Exit with proper code (error.code will be set if vitest failed)\n if (error && error.code) {\n process.exit(error.code);\n }\n }\n );\n }\n}\n\nexport { runTest }","import path from \"path\";\nimport fs from \"fs-extra\";\n/**\n * Validates the structure of an AriaEase config object\n * @param config - The config object to validate\n * @returns Validation result with errors if any\n */\nfunction validateConfig(config) {\n const errors = [];\n if (!config || typeof config !== 'object') {\n errors.push('Config must be an object');\n return { valid: false, errors };\n }\n const cfg = config;\n // Validate audit config if present\n if (cfg.audit !== undefined) {\n if (typeof cfg.audit !== 'object' || cfg.audit === null) {\n errors.push('audit must be an object');\n }\n else {\n // Validate urls\n if (cfg.audit.urls !== undefined) {\n if (!Array.isArray(cfg.audit.urls)) {\n errors.push('audit.urls must be an array');\n }\n else if (cfg.audit.urls.some(url => typeof url !== 'string')) {\n errors.push('audit.urls must contain only strings');\n }\n }\n // Validate output format\n if (cfg.audit.output !== undefined) {\n if (typeof cfg.audit.output !== 'object') {\n errors.push('audit.output must be an object');\n }\n else {\n const output = cfg.audit.output;\n if (output.format !== undefined) {\n if (!['json', 'csv', 'html', 'all'].includes(output.format)) {\n errors.push('audit.output.format must be one of: json, csv, html, all');\n }\n }\n if (output.out !== undefined && typeof output.out !== 'string') {\n errors.push('audit.output.out must be a string');\n }\n }\n }\n }\n }\n // Validate test config if present\n if (cfg.test !== undefined) {\n if (typeof cfg.test !== 'object' || cfg.test === null) {\n errors.push('test must be an object');\n }\n else {\n if (cfg.test.components !== undefined) {\n if (!Array.isArray(cfg.test.components)) {\n errors.push('test.components must be an array');\n }\n else {\n cfg.test.components.forEach((comp, idx) => {\n if (typeof comp !== 'object' || comp === null) {\n errors.push(`test.components[${idx}] must be an object`);\n }\n else {\n if (typeof comp.name !== 'string') {\n errors.push(`test.components[${idx}].name must be a string`);\n }\n if (typeof comp.path !== 'string') {\n errors.push(`test.components[${idx}].path must be a string`);\n }\n }\n });\n }\n }\n }\n }\n return { valid: errors.length === 0, errors };\n}\n/**\n * Attempts to load and parse a config file\n * @param filePath - Absolute path to the config file\n * @returns The parsed config or null if loading fails\n */\nasync function loadConfigFile(filePath) {\n try {\n const ext = path.extname(filePath);\n if (ext === '.json') {\n // Load JSON file\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n }\n else if (['.js', '.mjs', '.cjs', '.ts'].includes(ext)) {\n // Dynamic import for JS/TS modules\n const imported = await import(filePath);\n // Handle both default export and named exports\n return imported.default || imported;\n }\n return null;\n }\n catch {\n // Return null on any error - caller will handle\n return null;\n }\n}\n/**\n * Searches for and loads an AriaEase config file\n * Checks for config files in this order:\n * - ariaease.config.js\n * - ariaease.config.mjs\n * - ariaease.config.cjs\n * - ariaease.config.json\n * - ariaease.config.ts\n *\n * @param cwd - Current working directory to search in\n * @returns Object containing the config and any errors\n */\nexport async function loadConfig(cwd = process.cwd()) {\n const configNames = [\n 'ariaease.config.js',\n 'ariaease.config.mjs',\n 'ariaease.config.cjs',\n 'ariaease.config.json',\n 'ariaease.config.ts'\n ];\n let loadedConfig = null;\n let foundPath = null;\n const errors = [];\n // Try to find and load config\n for (const name of configNames) {\n const configPath = path.resolve(cwd, name);\n if (await fs.pathExists(configPath)) {\n foundPath = configPath;\n loadedConfig = await loadConfigFile(configPath);\n if (loadedConfig === null) {\n errors.push(`Found config at ${name} but failed to load it. Check for syntax errors.`);\n continue;\n }\n // Validate the loaded config\n const validation = validateConfig(loadedConfig);\n if (!validation.valid) {\n errors.push(`Config validation failed in ${name}:`);\n errors.push(...validation.errors.map(err => ` - ${err}`));\n loadedConfig = null;\n continue;\n }\n // Successfully loaded and validated\n break;\n }\n }\n return {\n config: loadedConfig || {},\n configPath: loadedConfig ? foundPath : null,\n errors\n };\n}\n"],"mappings":"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","names":["path","fs","axe","path","format","fs"]}
|
|
1
|
+
{"version":3,"sources":["cli.ts","../src/utils/audit/src/audit/audit.js","../src/utils/audit/src/formatters/formatters.js","../src/utils/test/src/test.ts","configLoader.js"],"sourcesContent":["#!/usr/bin/env node\n\nimport { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport path from \"path\";\nimport fs from \"fs-extra\";\nimport { AxeResult } from \"Types\";\nimport { runAudit } from \"../src/utils/audit/src/audit/audit.js\";\nimport { formatResults } from \"../src/utils/audit/src/formatters/formatters.js\";\nimport { runTest } from \"../src/utils/test/index.js\";\nimport { loadConfig } from \"./configLoader.js\";\n\nconst program = new Command();\n\nprogram.name('aria-ease').description('Run accessibility tests and audits').version('2.2.3');\n\nprogram.command('audit')\n.description('Run axe-core powered accessibility audit on webpages')\n.option('-u, --url <url>', 'Single URL to audit')\n.option('-f, --format <format>', 'Output format for the audit report: json | csv | html | all', 'all')\n.option('-o, --out <path>', 'Directory to save the audit report', './accessibility-reports/audit')\n.action(async (opts) => {\n console.log(chalk.cyanBright('๐ Starting accessibility audit...\\n'));\n\n // Load config with robust discovery and validation\n const { config, configPath, errors } = await loadConfig(process.cwd());\n \n if (configPath) {\n console.log(chalk.green(`โ
Loaded config from ${path.basename(configPath)}\\n`));\n } else if (errors.length > 0) {\n console.log(chalk.red('โ Config file errors:\\n'));\n errors.forEach(err => console.log(chalk.red(` ${err}`)));\n console.log('');\n process.exit(1);\n } else {\n console.log(chalk.yellow('โน๏ธ No config file found, using CLI options.\\n'));\n }\n\n const urls: string[] = [];\n if(opts.url) urls.push(opts.url);\n if(config.audit?.urls && Array.isArray(config.audit.urls)) urls.push(...config.audit.urls);\n\n const format: string = (config.audit?.output && (config.audit.output as { format?: string }).format) || opts.format;\n if(!['json', 'csv', 'html', 'all'].includes(format)) {\n console.log(chalk.red('โ Invalid format. Use \"json\", \"csv\", \"html\" or \"all\".'));\n process.exit(1);\n }\n\n if(urls.length === 0) {\n console.log(chalk.red('โ No URLs provided. Use --url option or add \"urls\" in config file'));\n process.exit(1);\n }\n\n const allResults: { url: string, result?: AxeResult }[] = [];\n const auditOptions = {\n timeout: config.audit?.timeout,\n waitUntil: config.audit?.waitUntil\n };\n \n for (const url of urls) {\n console.log(chalk.yellow(`๐ Auditing: ${url}`));\n try {\n const result: AxeResult = await runAudit(url, auditOptions);\n allResults.push({ url: url, result });\n console.log(chalk.green(`โ
Completed audit for ${url}\\n`));\n } catch (error: unknown) {\n if(error instanceof Error && error.message) {\n console.log(chalk.red(`โ Failed auditing ${url}: ${error.message}`));\n }\n }\n }\n\n const hasResults = allResults.some(r => r.result && r.result.violations && r.result.violations.length > 0);\n if (!hasResults) {\n const auditedCount = allResults.filter(r => r.result).length;\n if (auditedCount === 0) {\n console.log(chalk.red('โ No pages were successfully audited.'));\n process.exit(1);\n }\n console.log(chalk.green('\\n๐ Great news! No static accessibility violations found!'));\n console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? 's' : ''} successfully.\\n`));\n process.exit(0);\n }\n\n async function createReport(format: string) {\n const formatted = formatResults(allResults, format);\n\n const out = (config.audit?.output && (config.audit.output as { out?: string }).out) || opts.out;\n\n await fs.ensureDir(out);\n const d = new Date();\n const pad = (n: number) => String(n).padStart(2, '0');\n const timestamp = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const fileName = `ariaease-report-${timestamp}.${format}`;\n const filePath = path.join(out, fileName);\n\n await fs.writeFile(filePath, formatted, 'utf-8');\n console.log(chalk.magentaBright(`๐ Report saved to ${filePath}`));\n }\n\n if(['json', 'csv', 'html'].includes(format)) {\n await createReport(format);\n } else if(format === 'all') {\n await Promise.all(['json', 'csv', 'html'].map((format) => createReport(format)));\n }\n\n console.log(chalk.green('\\n๐ All audits completed.'));\n})\n\nprogram.command('test')\n.description('Run core a11y accessibility standard tests on UI components')\n.action(() => {\n runTest();\n})\n\nprogram.command('help')\n.description('Display help information')\n.action(() => {\n program.outputHelp();\n});\n\nprogram.parse(process.argv);","import AxeBuilder from \"@axe-core/playwright\";\nimport { chromium } from \"playwright\";\nexport async function runAudit(url, options) {\n let browser;\n // Default to 60s timeout and domcontentloaded for better reliability\n const timeout = options?.timeout || 60000;\n const waitUntil = options?.waitUntil || 'domcontentloaded';\n try {\n browser = await chromium.launch({ headless: true });\n const context = await browser.newContext();\n const page = await context.newPage();\n await page.goto(url, { waitUntil, timeout });\n const axe = new AxeBuilder({ page });\n const axeResults = await axe.analyze();\n return axeResults;\n }\n catch (error) {\n if (error instanceof Error) {\n if (error.message.includes(\"Executable doesn't exist\")) {\n console.error('\\nโ Playwright browsers not found!\\n');\n console.log('๐ฆ First-time setup required:');\n console.log(' Run: npx playwright install chromium\\n');\n console.log('๐ก This downloads the browser needed for auditing (~200MB)');\n console.log(' You only need to do this once.\\n');\n }\n else if (error.message.includes(\"page.goto: net::ERR_CONNECTION_REFUSED\")) {\n console.error('\\nโ Server Not Running!\\n');\n console.log(' Make sure your server is running before auditing URL');\n console.log(' Run: npm run dev # or your start command');\n }\n else if (error.message.includes(\"page.goto: Protocol error (Page.navigate): Cannot navigate to invalid URL\")) {\n console.error('\\nโ Cannot audit invalid URL\\n');\n }\n else {\n console.error('โ Audit error:', error.message);\n console.log(' Make sure you provide a valid URL');\n }\n }\n else {\n console.error('โ Audit error (non-Error):', String(error));\n }\n throw error;\n }\n finally {\n if (browser)\n await browser.close();\n }\n}\n","export function formatResults(allResults, format) {\n switch (format) {\n case 'json':\n return JSON.stringify(allResults.flatMap(({ url, result }) => result\n ? result.violations.flatMap(v => v.nodes.map(n => ({\n URL: url,\n Rule: v.id,\n Impact: v.impact,\n Description: v.description,\n Target: n.target,\n FailureSummary: n.failureSummary\n })))\n : []), null, 2);\n case 'csv':\n return toCSV(allResults);\n case 'html':\n return toHTML(allResults);\n default:\n return '';\n }\n}\nfunction toCSV(allResults) {\n const rows = ['URL,Rule,Impact,Description,Target,FailureSummary'];\n allResults.forEach(({ url, result }) => {\n if (result) {\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n rows.push(escapeCSV(url) + ',' +\n escapeCSV(v.id) + ',' +\n escapeCSV(v.impact) + ',' +\n escapeCSV(v.description) + ',' +\n escapeCSV(Array.isArray(n.target) ? n.target.join('; ') : String(n.target)) + ',' +\n escapeCSV(n.failureSummary ?? ''));\n });\n });\n }\n });\n return rows.join('\\n');\n}\nfunction escapeCSV(value) {\n const s = String(value ?? '');\n return `\"${s.replace(/\"/g, '\"\"')}\"`;\n}\nfunction toHTML(allResults) {\n const summary = {\n pagesAudited: 0,\n pagesWithViolations: 0,\n totalViolations: 0,\n distinctRules: new Set(),\n impactCounts: new Map()\n };\n allResults.forEach(({ result }) => {\n if (!result)\n return;\n summary.pagesAudited++;\n const pageViolations = result.violations.reduce((acc, v) => {\n const nodesCount = (v.nodes || []).length;\n if (nodesCount > 0) {\n summary.distinctRules.add(v.id);\n summary.totalViolations += nodesCount;\n acc += nodesCount;\n const impact = String(v.impact ?? 'unknown');\n summary.impactCounts.set(impact, (summary.impactCounts.get(impact) || 0) + nodesCount);\n }\n return acc;\n }, 0);\n if (pageViolations > 0)\n summary.pagesWithViolations++;\n });\n const rows = [];\n allResults.forEach(({ url, result }) => {\n if (!result)\n return;\n result.violations.forEach(v => {\n v.nodes.forEach(n => {\n const target = Array.isArray(n.target) ? n.target.join('; ') : String(n.target);\n rows.push(`\n <tr>\n <td class=\"nowrap\">${escapeHTML(url)}</td>\n <td class=\"nowrap\">${escapeHTML(v.id)}</td>\n <td class=\"impact ${escapeClass(String(v.impact ?? 'unknown'))}\">${escapeHTML(String(v.impact ?? ''))}</td>\n <td class=\"desc\">${escapeHTML(v.description ?? '')}</td>\n <td class=\"target\"><code>${escapeHTML(target)}</code></td>\n <td class=\"fail\">${escapeHTML(n.failureSummary ?? '').split(/\\r?\\n/).join('<br/>')}</td>\n </tr>\n `);\n });\n });\n });\n const impactSummary = Array.from(summary.impactCounts.entries()).map(([impact, count]) => `<li><strong class=\"impact ${escapeClass(impact)}\">${escapeHTML(impact)}</strong>: ${count}</li>`).join('\\n');\n const d = new Date();\n const pad = (n) => String(n).padStart(2, '0');\n const reportDateTime = `${pad(d.getDate())}-${pad(d.getMonth() + 1)}-${d.getFullYear()} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}`;\n const headerSummary = `\n <section class=\"summary\">\n <h2>Report summary</h2>\n <ul>\n <li><strong>Date:</strong> ${reportDateTime}</li>\n <li><strong>Pages audited:</strong> ${summary.pagesAudited}</li>\n <li><strong>Pages with violations:</strong> ${summary.pagesWithViolations}</li>\n <li><strong>Total violations:</strong> ${summary.totalViolations}</li>\n <li><strong>Distinct rules:</strong> ${summary.distinctRules.size}</li>\n </ul>\n <div class=\"impact-summary\">\n <h3>By impact</h3>\n <ul class=\"summary-list\">\n ${impactSummary || '<li>None</li>'}\n </ul>\n </div>\n </section>\n `.trim();\n const html = `\n <!DOCTYPE html>\n <html lang=\"en\">\n <head>\n <meta charset=\"utf-8\"/>\n <title>Aria-Ease Accessibility Audit Report</title>\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"/>\n <style>\n :root{\n --bg:#ffffff; --muted:#6b7280; --border:#e6e9ee;\n --impact-critical: red; --impact-moderate:#fff4dd; --impact-serious:rgb(255, 123, 0);\n }\n body{font-family:Inter,ui-sans-serif,system-ui,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:#111827; padding:24px; line-height:1.4}\n h1{margin:0 0 8px}\n .summary{background:#f8fafc;border:1px solid var(--border);padding:12px 16px;border-radius:8px;margin-bottom:18px}\n .summary ul{margin:6px 0 0 0;padding:0 18px}\n .impact-summary h3{margin:12px 0 6px}\n table{width:100%; border-collapse:collapse; margin-top:12px}\n th,td{border:1px solid var(--border); padding:10px; text-align:left; vertical-align:top}\n th{background:#f3f4f6; font-weight:600; position:sticky; top:0; z-index:1}\n .nowrap{white-space:nowrap}\n .target code{font-family:ui-monospace, SFMono-Regular, Menlo, Monaco, \"Roboto Mono\", \"Courier New\", monospace; white-space:pre-wrap}\n .desc{max-width:380px}\n tr:nth-child(even){background:#fbfbfb}\n td.fail{color:#7b1e1e}\n .impact.critical{background:var(--impact-critical); font-weight:600}\n .impact.moderate{background:var(--impact-moderate); font-weight:600}\n .impact.serious{background:var(--impact-serious); font-weight:600}\n @media (max-width:900px){\n .desc{max-width:200px}\n table, thead, tbody, th, td, tr{display:block}\n thead{display:none}\n tr{margin-bottom:10px; border: 1px solid var(--border);}\n td{border:1px solid var(--border); padding:6px}\n td::before{font-weight:600; display:inline-block; width:120px}\n }\n .summary-list strong,\n .summary-list li {\n padding: 2px 4px;\n }\n </style>\n </head>\n <body>\n <h1>Aria-Ease Accessibility Audit Report</h1>\n ${headerSummary}\n <table>\n <thead>\n <tr>\n <th>URL</th><th>Rule</th><th>Impact</th><th>Description</th><th>Target</th><th>FailureSummary</th>\n </tr>\n </thead>\n <tbody>\n ${rows.join('\\n') || '<tr><td colspan=\"6\"><em>No violations found.</em></td></tr>'}\n </tbody>\n </table>\n </body>\n </html>\n `.trim();\n return html;\n}\nfunction escapeHTML(str) {\n return String(str ?? '')\n .replaceAll('&', '&')\n .replaceAll('<', '<')\n .replaceAll('>', '>')\n .replaceAll('\"', '"')\n .replaceAll(\"'\", ''');\n}\nfunction escapeClass(s) {\n return String(s ?? '').toLowerCase().replace(/[^a-z0-9]+/g, '-');\n}\n","/**\n * Runs static and interactions accessibility test on UI components. \n * @param {HTMLElement} component The UI component to be tested\n * @param {string} url Optional URL to run full Playwright E2E tests (requires dev server running)\n*/\n\nimport { axe } from \"jest-axe\";\nimport type { JestAxeResult } from \"Types\";\nimport { runContractTests } from \"../contract/contractTestRunner\";\n\n\nexport async function testUiComponent(componentName: string, component: HTMLElement, url?: string): Promise<JestAxeResult> {\n const results = await axe(component);\n \n let contract;\n \n if (url) {\n console.log(`๐ญ Running Playwright E2E tests on ${url}`);\n const { runContractTestsPlaywright } = await import(\"../contract/contractTestRunnerPlaywright\");\n contract = await runContractTestsPlaywright(componentName, url);\n } else {\n console.log(`๐งช Running jsdom tests (limited event handling)`);\n contract = await runContractTests(componentName, component);\n }\n \n const result = {\n violations: results.violations,\n raw: results,\n contract\n };\n \n // Throw helpful error if there are failures (use counts from reporter, not raw arrays)\n if (contract.failures.length > 0) {\n const mode = url ? 'Playwright' : 'jsdom';\n \n throw new Error(\n `\\nโ ${contract.failures.length} assertion${contract.failures.length > 1 ? 's' : ''} failed (${mode} mode)\\n` +\n `โ
${contract.passes.length} assertion${contract.passes.length > 1 ? 's' : ''} passed\\n\\n` +\n `๐ Review the detailed test report above for specific failures.`\n );\n }\n \n if (results.violations.length > 0) {\n const violationCount = results.violations.length;\n throw new Error(\n `\\nโ ${violationCount} axe accessibility violation${violationCount > 1 ? 's' : ''} detected\\n\\n` +\n `๐ Check result.violations for details`\n );\n }\n \n return result;\n}\n\nlet runTest = async () => {}\n\nif (typeof window === \"undefined\") {\n runTest = async () => {\n console.log(`๐ Running component accessibility tests...\\n`);\n\n const { exec } = await import(\"child_process\");\n\n exec(\n `npx vitest --run --reporter verbose`,\n { cwd: process.cwd() },\n (error, stdout, stderr) => {\n // Always output stdout (test results)\n if (stdout) {\n console.log(stdout);\n }\n \n // Always output stderr (ContractReporter output)\n if (stderr) {\n console.error(stderr);\n }\n \n // Exit with proper code (error.code will be set if vitest failed)\n if (error && error.code) {\n process.exit(error.code);\n }\n }\n );\n }\n}\n\nexport { runTest }","import path from \"path\";\nimport fs from \"fs-extra\";\n/**\n * Validates the structure of an AriaEase config object\n * @param config - The config object to validate\n * @returns Validation result with errors if any\n */\nfunction validateConfig(config) {\n const errors = [];\n if (!config || typeof config !== 'object') {\n errors.push('Config must be an object');\n return { valid: false, errors };\n }\n const cfg = config;\n // Validate audit config if present\n if (cfg.audit !== undefined) {\n if (typeof cfg.audit !== 'object' || cfg.audit === null) {\n errors.push('audit must be an object');\n }\n else {\n // Validate urls\n if (cfg.audit.urls !== undefined) {\n if (!Array.isArray(cfg.audit.urls)) {\n errors.push('audit.urls must be an array');\n }\n else if (cfg.audit.urls.some(url => typeof url !== 'string')) {\n errors.push('audit.urls must contain only strings');\n }\n }\n // Validate output format\n if (cfg.audit.output !== undefined) {\n if (typeof cfg.audit.output !== 'object') {\n errors.push('audit.output must be an object');\n }\n else {\n const output = cfg.audit.output;\n if (output.format !== undefined) {\n if (!['json', 'csv', 'html', 'all'].includes(output.format)) {\n errors.push('audit.output.format must be one of: json, csv, html, all');\n }\n }\n if (output.out !== undefined && typeof output.out !== 'string') {\n errors.push('audit.output.out must be a string');\n }\n }\n }\n }\n }\n // Validate test config if present\n if (cfg.test !== undefined) {\n if (typeof cfg.test !== 'object' || cfg.test === null) {\n errors.push('test must be an object');\n }\n else {\n if (cfg.test.components !== undefined) {\n if (!Array.isArray(cfg.test.components)) {\n errors.push('test.components must be an array');\n }\n else {\n cfg.test.components.forEach((comp, idx) => {\n if (typeof comp !== 'object' || comp === null) {\n errors.push(`test.components[${idx}] must be an object`);\n }\n else {\n if (typeof comp.name !== 'string') {\n errors.push(`test.components[${idx}].name must be a string`);\n }\n if (typeof comp.path !== 'string') {\n errors.push(`test.components[${idx}].path must be a string`);\n }\n }\n });\n }\n }\n }\n }\n return { valid: errors.length === 0, errors };\n}\n/**\n * Attempts to load and parse a config file\n * @param filePath - Absolute path to the config file\n * @returns The parsed config or null if loading fails\n */\nasync function loadConfigFile(filePath) {\n try {\n const ext = path.extname(filePath);\n if (ext === '.json') {\n // Load JSON file\n const content = await fs.readFile(filePath, 'utf-8');\n return JSON.parse(content);\n }\n else if (['.js', '.mjs', '.cjs', '.ts'].includes(ext)) {\n // Dynamic import for JS/TS modules\n const imported = await import(filePath);\n // Handle both default export and named exports\n return imported.default || imported;\n }\n return null;\n }\n catch {\n // Return null on any error - caller will handle\n return null;\n }\n}\n/**\n * Searches for and loads an AriaEase config file\n * Checks for config files in this order:\n * - ariaease.config.js\n * - ariaease.config.mjs\n * - ariaease.config.cjs\n * - ariaease.config.json\n * - ariaease.config.ts\n *\n * @param cwd - Current working directory to search in\n * @returns Object containing the config and any errors\n */\nexport async function loadConfig(cwd = process.cwd()) {\n const configNames = [\n 'ariaease.config.js',\n 'ariaease.config.mjs',\n 'ariaease.config.cjs',\n 'ariaease.config.json',\n 'ariaease.config.ts'\n ];\n let loadedConfig = null;\n let foundPath = null;\n const errors = [];\n // Try to find and load config\n for (const name of configNames) {\n const configPath = path.resolve(cwd, name);\n if (await fs.pathExists(configPath)) {\n foundPath = configPath;\n loadedConfig = await loadConfigFile(configPath);\n if (loadedConfig === null) {\n errors.push(`Found config at ${name} but failed to load it. Check for syntax errors.`);\n continue;\n }\n // Validate the loaded config\n const validation = validateConfig(loadedConfig);\n if (!validation.valid) {\n errors.push(`Config validation failed in ${name}:`);\n errors.push(...validation.errors.map(err => ` - ${err}`));\n loadedConfig = null;\n continue;\n }\n // Successfully loaded and validated\n break;\n }\n }\n return {\n config: loadedConfig || {},\n configPath: loadedConfig ? foundPath : null,\n errors\n };\n}\n"],"mappings":"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","names":["path","fs","axe","path","format","fs"]}
|
package/bin/cli.ts
CHANGED
|
@@ -77,7 +77,7 @@ program.command('audit')
|
|
|
77
77
|
console.log(chalk.red('โ No pages were successfully audited.'));
|
|
78
78
|
process.exit(1);
|
|
79
79
|
}
|
|
80
|
-
console.log(chalk.green('\n๐ Great news! No accessibility violations found!'));
|
|
80
|
+
console.log(chalk.green('\n๐ Great news! No static accessibility violations found!'));
|
|
81
81
|
console.log(chalk.gray(` Audited ${auditedCount} page${auditedCount > 1 ? 's' : ''} successfully.\n`));
|
|
82
82
|
process.exit(0);
|
|
83
83
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -9717,7 +9717,7 @@ function moveFocus(elementItems, currentIndex, direction) {
|
|
|
9717
9717
|
function isClickableButNotSemantic(el) {
|
|
9718
9718
|
return el.getAttribute("data-custom-click") !== null && el.getAttribute("data-custom-click") !== void 0;
|
|
9719
9719
|
}
|
|
9720
|
-
function
|
|
9720
|
+
function handleMenuClose(menuElement, menuTriggerButton) {
|
|
9721
9721
|
menuElement.style.display = "none";
|
|
9722
9722
|
const menuTriggerButtonId = menuTriggerButton.getAttribute("id");
|
|
9723
9723
|
if (!menuTriggerButtonId) {
|
|
@@ -9788,7 +9788,7 @@ function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, t
|
|
|
9788
9788
|
event.preventDefault();
|
|
9789
9789
|
if (menuElementDiv && triggerButton) {
|
|
9790
9790
|
if (getComputedStyle(menuElementDiv).display === "block") {
|
|
9791
|
-
|
|
9791
|
+
handleMenuClose(menuElementDiv, triggerButton);
|
|
9792
9792
|
}
|
|
9793
9793
|
triggerButton.focus();
|
|
9794
9794
|
}
|
|
@@ -9805,6 +9805,12 @@ function handleKeyPress(event, elementItems, elementItemIndex, menuElementDiv, t
|
|
|
9805
9805
|
}
|
|
9806
9806
|
break;
|
|
9807
9807
|
}
|
|
9808
|
+
case "Tab": {
|
|
9809
|
+
if (menuElementDiv && triggerButton && (!event.shiftKey || event.shiftKey)) {
|
|
9810
|
+
handleMenuClose(menuElementDiv, triggerButton);
|
|
9811
|
+
}
|
|
9812
|
+
break;
|
|
9813
|
+
}
|
|
9808
9814
|
default:
|
|
9809
9815
|
break;
|
|
9810
9816
|
}
|
|
@@ -9902,12 +9908,55 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9902
9908
|
const handlerMap = /* @__PURE__ */ new Map();
|
|
9903
9909
|
const submenuInstances = /* @__PURE__ */ new Map();
|
|
9904
9910
|
let cachedItems = null;
|
|
9911
|
+
let filteredItems = null;
|
|
9905
9912
|
function getItems() {
|
|
9906
9913
|
if (!cachedItems) {
|
|
9907
|
-
cachedItems = menuDiv.querySelectorAll(
|
|
9914
|
+
cachedItems = menuDiv.querySelectorAll(`.${menuItemsClass}`);
|
|
9908
9915
|
}
|
|
9909
9916
|
return cachedItems;
|
|
9910
9917
|
}
|
|
9918
|
+
function getFilteredItems() {
|
|
9919
|
+
if (!filteredItems) {
|
|
9920
|
+
const allItems = getItems();
|
|
9921
|
+
filteredItems = [];
|
|
9922
|
+
for (let i = 0; i < allItems.length; i++) {
|
|
9923
|
+
const item = allItems.item(i);
|
|
9924
|
+
const isNested = isItemInNestedSubmenu(item);
|
|
9925
|
+
if (!isNested) {
|
|
9926
|
+
if (!item.hasAttribute("tabindex")) {
|
|
9927
|
+
item.setAttribute("tabindex", "-1");
|
|
9928
|
+
}
|
|
9929
|
+
filteredItems.push(item);
|
|
9930
|
+
}
|
|
9931
|
+
}
|
|
9932
|
+
}
|
|
9933
|
+
return filteredItems;
|
|
9934
|
+
}
|
|
9935
|
+
function toNodeListLike(items) {
|
|
9936
|
+
const nodeListLike = {
|
|
9937
|
+
length: items.length,
|
|
9938
|
+
item: (index) => items[index],
|
|
9939
|
+
forEach: (callback) => {
|
|
9940
|
+
items.forEach(callback);
|
|
9941
|
+
},
|
|
9942
|
+
[Symbol.iterator]: function* () {
|
|
9943
|
+
for (const item of items) {
|
|
9944
|
+
yield item;
|
|
9945
|
+
}
|
|
9946
|
+
}
|
|
9947
|
+
};
|
|
9948
|
+
return nodeListLike;
|
|
9949
|
+
}
|
|
9950
|
+
function isItemInNestedSubmenu(item) {
|
|
9951
|
+
let parent = item.parentElement;
|
|
9952
|
+
while (parent && parent !== menuDiv) {
|
|
9953
|
+
if (parent.getAttribute("role") === "menu") {
|
|
9954
|
+
return true;
|
|
9955
|
+
}
|
|
9956
|
+
parent = parent.parentElement;
|
|
9957
|
+
}
|
|
9958
|
+
return false;
|
|
9959
|
+
}
|
|
9911
9960
|
function setAria(isOpen) {
|
|
9912
9961
|
triggerButton.setAttribute("aria-expanded", isOpen ? "true" : "false");
|
|
9913
9962
|
}
|
|
@@ -9942,12 +9991,13 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9942
9991
|
closeMenu();
|
|
9943
9992
|
}
|
|
9944
9993
|
function addListeners() {
|
|
9945
|
-
const
|
|
9946
|
-
|
|
9994
|
+
const items = getFilteredItems();
|
|
9995
|
+
const nodeListLike = toNodeListLike(items);
|
|
9996
|
+
items.forEach((menuItem, index) => {
|
|
9947
9997
|
if (!handlerMap.has(menuItem)) {
|
|
9948
9998
|
const handler = (event) => handleKeyPress(
|
|
9949
9999
|
event,
|
|
9950
|
-
|
|
10000
|
+
nodeListLike,
|
|
9951
10001
|
index,
|
|
9952
10002
|
menuDiv,
|
|
9953
10003
|
triggerButton,
|
|
@@ -9960,8 +10010,8 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9960
10010
|
});
|
|
9961
10011
|
}
|
|
9962
10012
|
function removeListeners() {
|
|
9963
|
-
const
|
|
9964
|
-
|
|
10013
|
+
const items = getFilteredItems();
|
|
10014
|
+
items.forEach((menuItem) => {
|
|
9965
10015
|
const handler = handlerMap.get(menuItem);
|
|
9966
10016
|
if (handler) {
|
|
9967
10017
|
menuItem.removeEventListener("keydown", handler);
|
|
@@ -9972,9 +10022,11 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9972
10022
|
function openMenu() {
|
|
9973
10023
|
menuDiv.style.display = "block";
|
|
9974
10024
|
setAria(true);
|
|
10025
|
+
const items = getFilteredItems();
|
|
9975
10026
|
addListeners();
|
|
9976
|
-
|
|
9977
|
-
|
|
10027
|
+
if (items.length > 0) {
|
|
10028
|
+
items[0].focus();
|
|
10029
|
+
}
|
|
9978
10030
|
}
|
|
9979
10031
|
function closeMenu() {
|
|
9980
10032
|
removeListeners();
|
|
@@ -9991,6 +10043,7 @@ function makeMenuAccessible({ menuId, menuItemsClass, triggerId }) {
|
|
|
9991
10043
|
}
|
|
9992
10044
|
function refresh() {
|
|
9993
10045
|
cachedItems = null;
|
|
10046
|
+
filteredItems = null;
|
|
9994
10047
|
}
|
|
9995
10048
|
return { openMenu, closeMenu, cleanup, refresh };
|
|
9996
10049
|
}
|