Comparing version 0.11.0 to 0.12.0
@@ -63,3 +63,3 @@ import process from 'node:process'; | ||
if (options.verbose) { | ||
debug.enable('*,-puppeteer:*'); | ||
debug.enable('*,-puppeteer:*,-babel:*,-pw:*,-agentkeepalive'); | ||
} | ||
@@ -66,0 +66,0 @@ if (options.api) { |
import path, { dirname } from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
import createDebug from 'debug'; | ||
// Import puppeteer from 'puppeteer'; | ||
import { isHtmlPartial, isUrl, pathExists, runCommand } from '../util/index.js'; | ||
import { isHtmlPartial, isUrl, runCommand } from '../util/index.js'; | ||
const debug = createDebug('axe'); | ||
const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
async function getChromeDriverPath() { | ||
const targetPath = 'node_modules/chromedriver/bin/chromedriver'; | ||
let chromedriverPath = path.join(__dirname, '..', targetPath); | ||
if (!(await pathExists(chromedriverPath))) { | ||
// Try one level up | ||
chromedriverPath = path.join(__dirname, '..', '..', targetPath); | ||
} | ||
if (!(await pathExists(chromedriverPath))) { | ||
throw new Error('Could not find chromedriver'); | ||
} | ||
debug('chromedriver path: %s', chromedriverPath); | ||
return chromedriverPath; | ||
} | ||
// Function getChromePath() { | ||
// const chromePath = puppeteer.executablePath(); | ||
// debug('chrome path: %s', chromePath); | ||
// return chromePath; | ||
// } | ||
const urlEnvProperty = 'A11Y_AI_URL'; | ||
const disabledRulesEnvProperty = 'A11Y_AI_DISABLED_RULES'; | ||
const configPath = path.resolve(__dirname, '../../scan/playwright.config.cjs'); | ||
const issuesRegex = /===ISSUES_BEGIN===\n([\s\S]*?)===ISSUES_END===/m; | ||
export async function scanIssues(file) { | ||
@@ -30,15 +15,14 @@ try { | ||
const inputFilePath = isFileUrl ? file : `file://${path.resolve(file)}`; | ||
// TODO: not working! find a way to make Axe use this binary | ||
// process.env.CHROME_BIN = getChromePath(); | ||
const axeOptions = [`--chromedriver-path "${await getChromeDriverPath()}"`, '--stdout']; | ||
let disabledRules = ''; | ||
const isPartial = !isFileUrl && (await isHtmlPartial(file)); | ||
if (isPartial) { | ||
// Disable rules that require a full HTML document | ||
axeOptions.push('--disable html-has-lang,document-title,landmark-one-main,region,page-has-heading-one'); | ||
disabledRules = 'html-has-lang,document-title,landmark-one-main,region,page-has-heading-one'; | ||
} | ||
const command = `axe ${axeOptions.join(' ')} "${inputFilePath}"`; | ||
debug(`Running axe command: ${command}`); | ||
const results = await runCommand(command); | ||
const json = JSON.parse(results); | ||
const issues = json[0].violations; | ||
const command = `npx playwright test --config "${configPath}"`; | ||
debug(`Running command: ${command}`); | ||
const stdout = await runCommand(command, { | ||
[urlEnvProperty]: inputFilePath, | ||
[disabledRulesEnvProperty]: disabledRules | ||
}, true); | ||
const issues = getViolationFromOutput(stdout); | ||
debug(`Found ${issues.length} issues`); | ||
@@ -50,3 +34,3 @@ debug('Issues details: %o', issues); | ||
const error_ = error; | ||
const message = `Error while running axe: ${error_.message ?? error_}`; | ||
const message = `Error while running axe scan: ${error_.message ?? error_}`; | ||
debug(message); | ||
@@ -56,1 +40,11 @@ throw new Error(message); | ||
} | ||
function getViolationFromOutput(output) { | ||
const match = issuesRegex.exec(output); | ||
if (!match) { | ||
console.log(output); | ||
throw new Error('Could not find issues in command output'); | ||
} | ||
const rawIssues = match[1]; | ||
const issues = JSON.parse(rawIssues); | ||
return issues; | ||
} |
@@ -1,1 +0,1 @@ | ||
export declare function runCommand(command: string): Promise<string>; | ||
export declare function runCommand(command: string, env?: Record<string, string>, runInProjectRoot?: boolean): Promise<string>; |
@@ -0,6 +1,17 @@ | ||
import path, { dirname } from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
import { promisify } from 'node:util'; | ||
import { exec } from 'node:child_process'; | ||
export async function runCommand(command) { | ||
const result = await promisify(exec)(command); | ||
const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
const projectRoot = path.resolve(__dirname, '../../'); | ||
export async function runCommand(command, env = {}, runInProjectRoot = false) { | ||
const result = await promisify(exec)(command, { | ||
env: { | ||
...process.env, | ||
...env, | ||
}, | ||
maxBuffer: 1024 * 1024 * 10, | ||
...(runInProjectRoot ? { cwd: projectRoot } : {}), | ||
}); | ||
return result.stdout.toString(); | ||
} |
{ | ||
"name": "a11y-ai", | ||
"version": "0.11.0", | ||
"version": "0.12.0", | ||
"description": "Experimental tool to automatically detect accessibility issues in web pages using OpenAI and provide suggestions for fixing them", | ||
@@ -38,7 +38,7 @@ "type": "module", | ||
"dependencies": { | ||
"@axe-core/cli": "^4.6.0", | ||
"@dqbd/tiktoken": "^1.0.6", | ||
"@playwright/test": "^1.33.0", | ||
"ansi-to-html": "^0.7.2", | ||
"axe-playwright": "^1.2.3", | ||
"chalk": "^5.2.0", | ||
"chromedriver": "^111.0.0", | ||
"debug": "^4.3.4", | ||
@@ -91,4 +91,5 @@ "diff": "^5.1.0", | ||
"bin", | ||
"lib" | ||
"lib", | ||
"scan" | ||
] | ||
} |
@@ -83,5 +83,5 @@ # :robot: a11y-ai | ||
## Troubleshooting | ||
### Accessibility issues scanning | ||
WIP | ||
Accessibility issues scan is done using [Playwright](https://playwright.dev/) with the [axe-playwright](https://www.npmjs.com/package/axe-playwright) plugin. | ||
@@ -94,7 +94,5 @@ <!-- ## Automated reports | ||
## Limitations | ||
## Known limitations | ||
- Windows support outside of WSL2 is currently not working due to a bug in Axe CLI (WIP) | ||
- It needs a matching Chrome version to work (WIP) | ||
- Issue scanning is only supported for HTML files, not for JS/TS components (but fixing is supported) | ||
- `--gpt-diff` options is experimental and may not work well in some cases |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 4 instances in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
46674
42
1023
97
8
+ Added@playwright/test@^1.33.0
+ Addedaxe-playwright@^1.2.3
+ Added@playwright/test@1.49.0(transitive)
+ Addedaxe-html-reporter@2.2.3(transitive)
+ Addedaxe-playwright@1.2.3(transitive)
+ Addedbalanced-match@1.0.2(transitive)
+ Addedbrace-expansion@1.1.11(transitive)
+ Addedconcat-map@0.0.1(transitive)
+ Addedfs.realpath@1.0.0(transitive)
+ Addedfsevents@2.3.2(transitive)
+ Addedglob@7.2.3(transitive)
+ Addedinflight@1.0.6(transitive)
+ Addedminimatch@3.1.2(transitive)
+ Addedmustache@4.2.0(transitive)
+ Addedpath-is-absolute@1.0.1(transitive)
+ Addedpicocolors@1.1.1(transitive)
+ Addedplaywright@1.49.0(transitive)
+ Addedplaywright-core@1.49.0(transitive)
+ Addedrimraf@3.0.2(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedstring_decoder@1.3.0(transitive)
- Removed@axe-core/cli@^4.6.0
- Removedchromedriver@^111.0.0
- Removed@axe-core/cli@4.10.1(transitive)
- Removed@axe-core/webdriverjs@4.10.1(transitive)
- Removed@testim/chrome-version@1.1.4(transitive)
- Removed@tootallnate/quickjs-emscripten@0.23.0(transitive)
- Removed@types/node@22.9.3(transitive)
- Removed@types/yauzl@2.10.3(transitive)
- Removedagent-base@6.0.27.1.1(transitive)
- Removedast-types@0.13.4(transitive)
- Removedasynckit@0.4.0(transitive)
- Removedaxios@1.7.7(transitive)
- Removedbasic-ftp@5.0.5(transitive)
- Removedbuffer-crc32@0.2.13(transitive)
- Removedchromedriver@111.0.0131.0.1(transitive)
- Removedcolors@1.4.0(transitive)
- Removedcombined-stream@1.0.8(transitive)
- Removedcommander@9.5.0(transitive)
- Removedcompare-versions@5.0.36.1.1(transitive)
- Removedcore-util-is@1.0.3(transitive)
- Removeddata-uri-to-buffer@6.0.2(transitive)
- Removeddebug@4.3.1(transitive)
- Removeddeep-is@0.1.4(transitive)
- Removeddegenerator@5.0.1(transitive)
- Removeddelayed-stream@1.0.0(transitive)
- Removeddotenv@16.4.5(transitive)
- Removedend-of-stream@1.4.4(transitive)
- Removedescodegen@2.1.0(transitive)
- Removedesprima@4.0.1(transitive)
- Removedestraverse@5.3.0(transitive)
- Removedesutils@2.0.3(transitive)
- Removedextract-zip@2.0.1(transitive)
- Removedfd-slicer@1.1.0(transitive)
- Removedfollow-redirects@1.15.9(transitive)
- Removedform-data@4.0.1(transitive)
- Removedfs-extra@11.2.0(transitive)
- Removedget-stream@5.2.0(transitive)
- Removedget-uri@6.0.3(transitive)
- Removedhttp-proxy-agent@7.0.2(transitive)
- Removedhttps-proxy-agent@5.0.17.0.5(transitive)
- Removedimmediate@3.0.6(transitive)
- Removedip-address@9.0.5(transitive)
- Removedip-regex@4.3.0(transitive)
- Removedis-url@1.2.4(transitive)
- Removedis2@2.0.9(transitive)
- Removedisarray@1.0.0(transitive)
- Removedjsbn@1.1.0(transitive)
- Removedjsonfile@6.1.0(transitive)
- Removedjszip@3.10.1(transitive)
- Removedlie@3.3.0(transitive)
- Removedlru-cache@7.18.3(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedms@2.1.2(transitive)
- Removednetmask@2.0.2(transitive)
- Removedpac-proxy-agent@7.0.2(transitive)
- Removedpac-resolver@7.0.1(transitive)
- Removedpako@1.0.11(transitive)
- Removedpend@1.2.0(transitive)
- Removedprocess-nextick-args@2.0.1(transitive)
- Removedproxy-agent@6.4.0(transitive)
- Removedproxy-from-env@1.1.0(transitive)
- Removedpump@3.0.2(transitive)
- Removedreadable-stream@2.3.8(transitive)
- Removedsafe-buffer@5.1.2(transitive)
- Removedselenium-webdriver@4.22.0(transitive)
- Removedsetimmediate@1.0.5(transitive)
- Removedsmart-buffer@4.2.0(transitive)
- Removedsocks@2.8.3(transitive)
- Removedsocks-proxy-agent@8.0.4(transitive)
- Removedsource-map@0.6.1(transitive)
- Removedsprintf-js@1.1.3(transitive)
- Removedstring_decoder@1.1.1(transitive)
- Removedtcp-port-used@1.0.2(transitive)
- Removedtmp@0.2.3(transitive)
- Removedtslib@2.8.1(transitive)
- Removedundici-types@6.19.8(transitive)
- Removeduniversalify@2.0.1(transitive)
- Removedws@8.18.0(transitive)
- Removedyauzl@2.10.0(transitive)