Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

a11y-ai

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

a11y-ai - npm Package Compare versions

Comparing version 0.11.0 to 0.12.0

scan/base/base.spec.js

2

lib/cli.js

@@ -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
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc