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

pa11y

Package Overview
Dependencies
Maintainers
7
Versions
103
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

pa11y - npm Package Compare versions

Comparing version 5.3.0 to 6.0.0-alpha

67

bin/pa11y.js

@@ -6,2 +6,3 @@ #!/usr/bin/env node

const extend = require('node.extend');
const envinfo = require('envinfo');
const path = require('path');

@@ -14,3 +15,7 @@ const pkg = require('../package.json');

configureProgram();
runProgram();
if (program.environment) {
outputEnvironmentInfo();
} else {
runProgram();
}

@@ -30,3 +35,4 @@ /**

'-s, --standard <name>',
'the accessibility standard to use: Section508, WCAG2A, WCAG2AA (default), WCAG2AAA – only used by htmlcs runner'
'the accessibility standard to use: Section508, WCAG2A, WCAG2AA (default), ' +
'WCAG2AAA – only used by htmlcs runner'
)

@@ -97,3 +103,4 @@ .option(

'-A, --add-rule <rule>',
'WCAG 2.0 rules to include, a repeatable value or separated by semi-colons – only used by htmlcs runner',
'WCAG 2.0 rules to include, a repeatable value or separated by semi-colons ' +
'– only used by htmlcs runner',
collectOptions,

@@ -107,13 +114,17 @@ []

/**
* Test the page and generate the results
* Handle help
* @returns {void}
*/
async function runProgram() {
if (program.environment) {
outputEnvironmentInfo();
process.exit(0);
}
function handleHelp() {
if (!program.url || program.args[1]) {
program.help();
}
}
/**
* Test the page and generate the results
* @returns {void}
*/
async function runProgram() {
handleHelp();
const options = processOptions();

@@ -123,3 +134,3 @@ const report = loadReporter(options.reporter);

if (!program.debug) {
options.log.debug = () => {};
options.log.debug = () => { /* NoOp */ };
}

@@ -199,3 +210,6 @@ await report.begin(program.url);

} catch (error) {
console.error(`An error occurred when loading the "${name}" reporter. This is not an error`);
console.error(
`An error occurred when loading the "${name}" reporter. ` +
'This is not an error'
);
console.error('with Pa11y itself, please contact the creator of this reporter\n');

@@ -223,3 +237,6 @@ console.error(error.stack);

if (!reporterSupportString || !semver.satisfies(pa11yVersion, reporterSupportString)) {
console.error(`Error: The installed "${reporterName}" reporter does not support Pa11y ${pa11yVersion}`);
console.error(
`Error: The installed "${reporterName}" reporter does not support ` +
`Pa11y ${pa11yVersion}`
);
console.error('Please update your version of Pa11y or the reporter');

@@ -293,20 +310,14 @@ console.error(`Reporter Support: ${reporterSupportString}`);

* Output environment info for debugging purposes
* @param {Object} pkg - The package.json object
* @returns {void}
* @returns {Promise} - resolves a string with environment information from envinfo
*/
function outputEnvironmentInfo() {
const versions = {
pa11y: pkg.version,
node: process.version.replace('v', ''),
npm: '[unavailable]',
os: require('os').release()
};
try {
versions.npm = require('child_process').execSync('npm -v').toString().trim();
} catch (error) {}
async function outputEnvironmentInfo() {
const envData = await envinfo.run({
System: ['OS', 'CPU', 'Memory', 'Shell'],
Binaries: ['Node', 'Yarn', 'npm'],
npmPackages: ['pa11y']
});
console.log(`Pa11y: ${versions.pa11y}`);
console.log(`Node.js: ${versions.node}`);
console.log(`npm: ${versions.npm}`);
console.log(`OS: ${versions.os} (${process.platform})`);
console.log(envData);
process.exit(0);
}

@@ -1,481 +0,485 @@

# Changelog
## 6.0.0-alpha (2020-04-28)
* Update HTML_CodeSniffer to 2.5.1, which includes support for WCAG 2.1
* Drop support for Node.js versions older than 10.
## 5.3.0 (2019-09-30)
* Adds support for [aXe](https://www.deque.com/axe/) test runner (thanks @rowanmanning)
* Adds support for multiple test runners (thanks @rowanmanning)
* Adds support for sites using `AMD` (thanks @joeyciechanowicz)
* Removes dependency on `fs-extra` (thanks @timnovis)
* Improves JSDoc typings (thanks @josebolos)
* Inverts the order of `setViewport` and `goto` to prevent accidental page reloads (thanks @josebolos)
* Minor documentation updates (thanks @sjparkinson, @josebolos)
* Adds support for [aXe](https://www.deque.com/axe/) test runner (thanks @rowanmanning)
* Adds support for multiple test runners (thanks @rowanmanning)
* Adds support for sites using `AMD` (thanks @joeyciechanowicz)
* Removes dependency on `fs-extra` (thanks @timnovis)
* Improves JSDoc typings (thanks @josebolos)
* Inverts the order of `setViewport` and `goto` to prevent accidental page reloads (thanks @josebolos)
* Minor documentation updates (thanks @sjparkinson, @josebolos)
## 5.2.0 (2019-07-04)
* Allow pa11y to use an existing puppeteer page instance (thanks @kevinatown)
* Fixed a bug where `set field` may fail if the text contains the string " to " (thanks @kkoskelin)
* Use npm version of HTML_CodeSniffer instead of a static one (thanks @paazmaya) and update to version 2.4.0
* Add a `package-lock.json` file to the package
* Several dependency and tooling updates (thanks @leeroyrose and others)
* Other bugfixes (thanks @joeyciechanowicz)
* Minor documentation updates
* Allow pa11y to use an existing puppeteer page instance (thanks @kevinatown)
* Fixed a bug where `set field` may fail if the text contains the string " to " (thanks @kkoskelin)
* Use npm version of HTML_CodeSniffer instead of a static one (thanks @paazmaya) and update to version 2.4.0
* Add a `package-lock.json` file to the package
* Several dependency and tooling updates (thanks @leeroyrose and others)
* Other bugfixes (thanks @joeyciechanowicz)
* Minor documentation updates
## 5.1.0 (2018-10-18)
* Intercept first page requests only when necessary, to [work around a Puppeteer bug](https://github.com/pa11y/pa11y/issues/421).
* Add an .nvmrc file to specify the minimum Node version already [listed in the requirements](https://github.com/pa11y/pa11y#requirements)
* Update dependencies
* commander: ^2.14.1 to ^2.19.0
* eslint: ^4.17.0 to ^4.19.1
* mocha: ^5.0.1 to ^5.2.0
* nyc: ^11.4.1 to ^11.9.0
* puppeteer: ^1.4.0 to ^1.9.0
* semver: ^5.5.0 to ^5.6.0
* sinon: ^4.3.0 to ^4.5.0
* HTML CodeSniffer: 2.1.1 to 2.2.0
* Intercept first page requests only when necessary, to [work around a Puppeteer bug](https://github.com/pa11y/pa11y/issues/421).
* Add an .nvmrc file to specify the minimum Node version already [listed in the requirements](https://github.com/pa11y/pa11y#requirements)
* Update dependencies
* commander: ^2.14.1 to ^2.19.0
* eslint: ^4.17.0 to ^4.19.1
* mocha: ^5.0.1 to ^5.2.0
* nyc: ^11.4.1 to ^11.9.0
* puppeteer: ^1.4.0 to ^1.9.0
* semver: ^5.5.0 to ^5.6.0
* sinon: ^4.3.0 to ^4.5.0
* HTML CodeSniffer: 2.1.1 to 2.2.0
## 5.0.4 (2018-05-21)
* Update dependencies
* puppeteer: 1.0.0 to ^1.4.0
* Correct and clarify some of the documentation
* Update dependencies
* puppeteer: 1.0.0 to ^1.4.0
* Correct and clarify some of the documentation
## 5.0.3 (2018-03-09)
* Fix an issue caused by a site having a global `module.exports` property
* Fix an issue caused by a site having a global `module.exports` property
## 5.0.2 (2018-03-08)
* Pin puppeteer at 1.0.0 to fix file URL issues
* Pin puppeteer at 1.0.0 to fix file URL issues
## 5.0.1 (2018-02-16)
* Update dependencies
* commander: ^2.9.0 to ^2.14.1
* p-timeout: ^1.2.0 to ^2.0.1
* semver: ^5.4.1 to ^5.5.0
* eslint: ^3.1.8 to ^4.17.0
* mocha: ^3.2.0 to ^5.0.1
* nyc: ^10.1.2 to ^11.4.1
* proclaim: ^3.4.4 to ^3.5.1
* sinon: ^3.2.0 to ^4.3.0
* Update dependencies
* commander: ^2.9.0 to ^2.14.1
* p-timeout: ^1.2.0 to ^2.0.1
* semver: ^5.4.1 to ^5.5.0
* eslint: ^3.1.8 to ^4.17.0
* mocha: ^3.2.0 to ^5.0.1
* nyc: ^10.1.2 to ^11.4.1
* proclaim: ^3.4.4 to ^3.5.1
* sinon: ^3.2.0 to ^4.3.0
## 5.0.0 (2018-02-15)
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-40-to-50) for details
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-40-to-50) for details
## 5.0.0-beta.10 pre-release (2018-02-14)
* Allow passing in a Chrome page instance to a test
* Allow passing in a Chrome page instance to a test
## 5.0.0-beta.9 pre-release (2018-01-30)
* Update dependencies
* pa11y-reporter-cli: ^1.0.0 to ^1.0.1
* Update dependencies
* pa11y-reporter-cli: ^1.0.0 to ^1.0.1
## 5.0.0-beta.8 pre-release (2018-01-22)
* Allow sharing a Chrome browser instance between test runs
* Fix Content-Security-Policy issues
* Allow sharing a Chrome browser instance between test runs
* Fix Content-Security-Policy issues
## 5.0.0-beta.7 pre-release (2018-01-17)
* Fix browser logging
* Fix browser logging
## 5.0.0-beta.6 pre-release (2018-01-16)
* Add the `navigate-url` action
* Correct documentation on `isValidAction`
* Update dependencies
* puppeteer: ^0.13.0 to ^1.0.0
* Add the `navigate-url` action
* Correct documentation on `isValidAction`
* Update dependencies
* puppeteer: ^0.13.0 to ^1.0.0
## 5.0.0-beta.5 pre-release (2017-12-11)
* Update dependencies
* puppeteer: ^0.11.0 to ^0.13.0
* Update dependencies
* puppeteer: ^0.11.0 to ^0.13.0
## 5.0.0-beta.4 pre-release (2017-12-06)
* Add reporter, threshold and level as configuration options
* Clarify some documentation
* Add reporter, threshold and level as configuration options
* Clarify some documentation
## 5.0.0-beta.3 pre-release (2017-11-26)
* Fix a timeout issue
* Fix an issue with the built in copy of HTML CodeSniffer
* Fix a timeout issue
* Fix an issue with the built in copy of HTML CodeSniffer
## 5.0.0-beta.2 pre-release (2017-10-04)
* Output browser console messages to the debug log
* Add the `screen-capture` action
* Add the `wait-for-element-event` action
* Update dependencies
* puppeteer: ^0.10.2 to ^0.11.0
* pa11y-lint-config: ^1.2.0 to ^1.2.1
* Output browser console messages to the debug log
* Add the `screen-capture` action
* Add the `wait-for-element-event` action
* Update dependencies
* puppeteer: ^0.10.2 to ^0.11.0
* pa11y-lint-config: ^1.2.0 to ^1.2.1
## 5.0.0-beta.1 pre-release (2017-09-11)
* See the [migration guide](https://github.com/pa11y/pa11y/blob/5.x/MIGRATION.md#migrating-from-40-to-50) for details
* See the [migration guide](https://github.com/pa11y/pa11y/blob/5.x/MIGRATION.md#migrating-from-40-to-50) for details
## 4.13.2 (2017-11-26)
* Fix an issue with the built in copy of HTML CodeSniffer
* Fix an issue with the built in copy of HTML CodeSniffer
## 4.13.1 (2017-10-16)
* Trigger correct change/input events for check-field and set-field-value actions
* Trigger correct change/input events for check-field and set-field-value actions
## 4.13.0 (2017-09-15)
* Update dependencies
* HTML CodeSniffer: 2.0.7 to 2.1.1
* Update dependencies
* HTML CodeSniffer: 2.0.7 to 2.1.1
## 4.12.2 (2017-09-11)
* Exit with an error when using an incompatible command-line reporter
* Exit with an error when using an incompatible command-line reporter
## 4.12.1 (2017-08-23)
* Roll back dependencies
* HTML CodeSniffer: 2.1.0 to 2.0.7
* Roll back dependencies
* HTML CodeSniffer: 2.1.0 to 2.0.7
## 4.12.0 (2017-08-23)
* Add the `wait-for-element-state` action
* Update the `wait-for-url` action to support waiting for hostname
* Update dependencies
* HTML CodeSniffer: 2.0.7 to 2.1.0
* Lots of updates to the README and trouble-shooting guide
* Support Node.js 8.x
* Add the `wait-for-element-state` action
* Update the `wait-for-url` action to support waiting for hostname
* Update dependencies
* HTML CodeSniffer: 2.0.7 to 2.1.0
* Lots of updates to the README and trouble-shooting guide
* Support Node.js 8.x
## 4.11.0 (2017-06-02)
* Add the ability to make Pa11y perform POST requests
* Documentation improvements
* Update dependencies
* truffler: ^3.0.1 to ^3.1.0
* Add the ability to make Pa11y perform POST requests
* Documentation improvements
* Update dependencies
* truffler: ^3.0.1 to ^3.1.0
## 4.10.0 (2017-04-18)
* Update example URLs across the project for clarity
* Add a TSV reporter
* Update example URLs across the project for clarity
* Add a TSV reporter
## 4.9.0 (2017-03-29)
* Add the ability to add additional WCAG rules to the selected standard
* Update dependencies
* async: ~1.4 to ^2.2.0
* bfj: ~1.2 to ^2.1.2
* chalk: ~1.1 to ^1.1.3
* commander: ~2.8 to ^2.9.0
* lower-case: ~1.1 to ^1.1.4
* node.extend: ~1.1 to ^1.1.6
* once: ~1.3 to ^1.4.0
* truffler: ~3.0 to ^3.0.1
* mocha: ^3 to ^3.2.0
* mockery: ~1.4 to ^2.0.0
* proclaim: ^3 to ^3.4.4
* sinon: ^1 to ^2.1.0
* Use the standard Pa11y lint config
* Update the tooling for consistency with other projects
* Add the ability to add additional WCAG rules to the selected standard
* Update dependencies
* async: ~1.4 to ^2.2.0
* bfj: ~1.2 to ^2.1.2
* chalk: ~1.1 to ^1.1.3
* commander: ~2.8 to ^2.9.0
* lower-case: ~1.1 to ^1.1.4
* node.extend: ~1.1 to ^1.1.6
* once: ~1.3 to ^1.4.0
* truffler: ~3.0 to ^3.0.1
* mocha: ^3 to ^3.2.0
* mockery: ~1.4 to ^2.0.0
* proclaim: ^3 to ^3.4.4
* sinon: ^1 to ^2.1.0
* Use the standard Pa11y lint config
* Update the tooling for consistency with other projects
## 4.8.0 (2017-03-17)
* Add the `--environment` flag for easier debugging
* Update the Windows requirements to include Windows 10
* Update the trouble-shooting guide and common questions
* Add the `--environment` flag for easier debugging
* Update the Windows requirements to include Windows 10
* Update the trouble-shooting guide and common questions
## 4.7.0 (2017-03-08)
* Add the ability to screen capture the tested page
* Move the main bin to a .js file
* Clean up coveralls
* Add the ability to screen capture the tested page
* Move the main bin to a .js file
* Clean up coveralls
## 4.6.0 (2017-01-30)
* Add negation to the "wait for..." actions
* Add negation to the "wait for..." actions
## 4.5.0 (2017-01-25)
* Expose action validation for use in dependent projects
* Expose action validation for use in dependent projects
## 4.4.0 (2017-01-19)
* Add support for actions
* Add support for actions
## 4.3.0 (2016-12-15)
* Add a `verifyPage` option, and a `--verify-page` flag
* Switch from JSHint/JSCS to ESLint
* Add a contributing guide
* Update dependencies
* istanbul: ~0.3 to ~0.4
* Add a `verifyPage` option, and a `--verify-page` flag
* Switch from JSHint/JSCS to ESLint
* Add a contributing guide
* Update dependencies
* istanbul: ~0.3 to ~0.4
## 4.2.0 (2016-11-25)
* Display the page title in the logs to help with debugging
* Display the page title in the logs to help with debugging
## 4.1.1 (2016-11-24)
* Update dependencies
* truffler: ~2.3 to ~3.0
* Update dependencies
* truffler: ~2.3 to ~3.0
## 4.1.0 (2016-11-21)
* Install PhantomJS as a dependency if the latest version isn't present
* Remove the SSL protocol from the default PhantomJS config
* Install PhantomJS as a dependency if the latest version isn't present
* Remove the SSL protocol from the default PhantomJS config
## 4.0.3 (2016-11-20)
* Add protocols to URLs, make path instructions explicit
* Add protocols to URLs, make path instructions explicit
## 4.0.2 (2016-11-10)
* Update dependencies
* truffler: ~2.2 to ~2.3
* Fix typos and mistakes across the documentation
* Update dependencies
* truffler: ~2.2 to ~2.3
* Fix typos and mistakes across the documentation
## 4.0.1 (2016-08-18)
* Upgrade mocha to version 3. This fixes a security vuln with versions of minimatch older than
* Upgrade mocha to version 3. This fixes a security vuln with versions of minimatch older than
3.0.2. Minimatch is one of mocha's dependencies. This only affects `devDependencies`.
* Documentation updates.
* Documentation updates.
## 4.0.0 (2016-06-05)
* Drop Node.js 0.12 support
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-30-to-40) for details
* Drop Node.js 0.12 support
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-30-to-40) for details
## 3.8.1 (2016-06-03)
* Fixes the `hideElements` option
* Fixes the `hideElements` option
## 3.8.0 (2016-05-25)
* Make the built-in reporters usable in JavaScript
* Tidy up the examples
* Make the built-in reporters usable in JavaScript
* Tidy up the examples
## 3.7.1 (2016-05-03)
* Support Node.js 6.x
* Support Node.js 6.x
## 3.7.0 (2016-04-27)
* Update dependencies
* truffler: ~2.1 to ~2.2
* HTML CodeSniffer: 2.0.1 to 2.0.7
* Update dependencies
* truffler: ~2.1 to ~2.2
* HTML CodeSniffer: 2.0.1 to 2.0.7
## 3.6.0 (2016-03-01)
* Adding the `rootElement` option so a subset of the document can be tested
* Adding the `hideElements` option so elements can be hidden from testing
* Adding the `rootElement` option so a subset of the document can be tested
* Adding the `hideElements` option so elements can be hidden from testing
## 3.5.1 (2016-02-09)
* Update repository references to springernature
* Update the license
* Update repository references to springernature
* Update the license
## 3.5.0 (2016-02-09)
* Adding the `beforeScript` option so JavaScript can be run on the page before testing
* Re-license under the LGPL 3.0
* Adding the `beforeScript` option so JavaScript can be run on the page before testing
* Re-license under the LGPL 3.0
## 3.4.0 (2016-02-01)
* Document running Pa11y against local files
* Add a trouble-shooting guide for Windows
* Make allowed standards configurable
* Document running Pa11y against local files
* Add a trouble-shooting guide for Windows
* Make allowed standards configurable
## 3.3.0 (2016-01-11)
* Add the ability to use the `--ignore` command line more than once
* Add the ability to use the `--ignore` command line more than once
## 3.2.1 (2016-01-05)
* Fix an issue where JSON output was truncated
* Fix an issue where JSON output was truncated
## 3.2.0 (2015-12-17)
* Add a threshold CLI parameter to allow a certain number of errors before failing
* Add a threshold CLI parameter to allow a certain number of errors before failing
## 3.1.0 (2015-12-14)
* Add the ability to specify the path to the PhantomJS binary
* Add the ability to specify the path to the PhantomJS binary
## 3.0.1 (2015-11-09)
* Support Node.js 5.x
* Support Node.js 5.x
## 3.0.0 (2015-10-16)
* Initial 3.0 release
* Overhaul the API (now uses Truffler 2.0)
* Drop Node.js 0.10 support
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-20-to-30) for details
* Initial 3.0 release
* Overhaul the API (now uses Truffler 2.0)
* Drop Node.js 0.10 support
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-20-to-30) for details
## 2.4.5 (2016-01-05)
* Fix an issue where JSON output was truncated
* Fix an issue where JSON output was truncated
## 2.4.4 (2015-08-20)
* Handle PhantomJS exits better when a timeout occurs
* Handle PhantomJS exits better when a timeout occurs
## 2.4.3 (2015-08-18)
* Add code coverage reporting and increase coverage
* Add code coverage reporting and increase coverage
## 2.4.2 (2015-08-09)
* Update dependencies
* Increase linter coverage
* Update dependencies
* Increase linter coverage
## 2.4.1 (2015-07-13)
* Add a question about proxying to the README
* Add a question about proxying to the README
## 2.4.0 (2015-07-13)
* Add a Markdown reporter
* Update dependencies
* Add a Markdown reporter
* Update dependencies
## 2.3.0 (2015-06-23)
* Add a `wait` option for pages which take time to fully render
* Relax development dependencies
* Add a `wait` option for pages which take time to fully render
* Relax development dependencies
## 2.2.1 (2015-06-19)
* Update the migration guide
* Update the migration guide
## 2.2.0 (2015-06-18)
* Add the ability to specify a HTML CodeSniffer URL/path
* Make sure that the HTML reporter passes WCAG2AA
* Add the ability to specify a HTML CodeSniffer URL/path
* Make sure that the HTML reporter passes WCAG2AA
## 2.1.0 (2015-06-09)
* Add CSS selectors to the results, making it easier to find elements in the page
* Add CSS selectors to the results, making it easier to find elements in the page
## 2.0.2 (2015-06-09)
* Fix a bug caused by PhantomJS stdout
* Fix a bug caused by PhantomJS stdout
## 2.0.1 (2015-06-08)
* Update dependencies
* Update dependencies
## 2.0.0 (2015-06-08)
* Initial 2.0 release
* Full rewrite
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-10-to-20) for details
* Initial 2.0 release
* Full rewrite
* See the [migration guide](https://github.com/pa11y/pa11y/blob/master/MIGRATION.md#migrating-from-10-to-20) for details
## 1.7.0 (2015-05-08)
* Add HTML snippets to results for additional context
* Add HTML snippets to results for additional context
## 1.6.3 (2015-01-17)
* Fix memory issues by reducing data sent between node and phantom
* Fix memory issues by reducing data sent between node and phantom
## 1.6.2 (2014-10-07)
* Documentation updates
* Documentation updates
## 1.6.1 (2014-06-27)
* Document the viewport option
* Expose the viewport option to the CLI
* Document the viewport option
* Expose the viewport option to the CLI
## 1.6.0 (2014-06-27)
* Output debug messages to `stderr`
* Output debug messages in the JSON/CSV reporters
* Allow configuring viewport width/height
* Output debug messages to `stderr`
* Output debug messages in the JSON/CSV reporters
* Allow configuring viewport width/height
## 1.5.4 (2014-04-30)
* Increase the timeout for functional tests
* Increase the timeout for functional tests
## 1.5.3 (2014-02-10)
* Add the GPL preamble to all files
* Add the GPL preamble to all files
## 1.5.2 (2014-01-13)
* Fix a formatting issue which caused files generated by the CSV reporter to display incorrectly in Excel
* Fix a formatting issue which caused files generated by the CSV reporter to display incorrectly in Excel
## 1.5.1 (2013-11-26)
* Set default exit status to -1 to not conflict with error count status codes
* Throw a more helpful error when PhantomJS cannot be found
* Set default exit status to -1 to not conflict with error count status codes
* Throw a more helpful error when PhantomJS cannot be found
## 1.5.0 (2013-10-31)
* Allow cookies to be set in-browser, for testing pages which require authentication
* Add "strict mode", where warnings are treated as errors
* Move from Make to Grunt for easier development on Windows
* Full rewrite of the functional tests
* Allow cookies to be set in-browser, for testing pages which require authentication
* Add "strict mode", where warnings are treated as errors
* Move from Make to Grunt for easier development on Windows
* Full rewrite of the functional tests
## 1.4.3 (2013-10-03)
* Remove instances of `process.exit` from the library
* Remove instances of `process.exit` from the library
## 1.4.2 (2013-09-10)
* Fix an issue where a premature exit caused the timer to kill the parent process
* Fix an issue where a premature exit caused the timer to kill the parent process
## 1.4.1 (2013-09-09)
* Fix an issue where HTML CodeSniffer errors can derail Pa11y
* Fix an issue where HTML CodeSniffer errors can derail Pa11y
## 1.4.0 (2013-08-30)
* Allow users to specify a port to run PhantomJS on. This means you can run multiple Pa11y commands in parallel
* Allow users to specify a port to run PhantomJS on. This means you can run multiple Pa11y commands in parallel
## 1.3.0 (2013-08-23)
* Finalise and document the JavaScript API (for non-command-line use)
* Use a custom UserAgent string (pa11y/&lt;version&gt;)
* Allow users to specify their own UserAgent string
* Finalise and document the JavaScript API (for non-command-line use)
* Use a custom UserAgent string (pa11y/&lt;version&gt;)
* Allow users to specify their own UserAgent string
## 1.2.1 (2013-08-16)
* Sanitize local HTMLCS URLs for API consistency
* Sanitize local HTMLCS URLs for API consistency
## 1.2.0 (2013-07-18)
* Add the ability to ignore certain rules through a JSON config file
* Exit with a non-zero code if any "Error" level messages are present in the results
* Simplify the output of the default console reporter
* Large code overhaul and more complete test suite
* Add the ability to ignore certain rules through a JSON config file
* Exit with a non-zero code if any "Error" level messages are present in the results
* Simplify the output of the default console reporter
* Large code overhaul and more complete test suite
## 1.1.0 (2013-07-10)
* Add a CLI option for self-hosted HTML_CodeSniffer
* Fix broken tests on some ISPs
* Add a CLI option for self-hosted HTML_CodeSniffer
* Fix broken tests on some ISPs
## 1.0.1 (2013-06-26)
* Bug fixes
* Bug fixes
## 1.0.0 (2013-06-25)
* Test Windows support
* Final config tweaks for stable release
* Test Windows support
* Final config tweaks for stable release
## 1.0.0-beta.3 pre-release (2013-06-24)
* Documentation updates
* Large-scale refactoring and testing
* Documentation updates
* Large-scale refactoring and testing
## 1.0.0-beta.2 pre-release (2013-06-11)
* Add a `debug` command line option
* Node 0.10.x support
* Add a `debug` command line option
* Node 0.10.x support
## 1.0.0-beta.1 pre-release (2013-06-04)
* Initial release
* Initial release

@@ -90,5 +90,4 @@ 'use strict';

try {
/* eslint-disable no-shadow */
await page.evaluate((selector, value) => {
const target = document.querySelector(selector);
await page.evaluate((targetSelector, desiredValue) => {
const target = document.querySelector(targetSelector);
if (!target) {

@@ -101,5 +100,5 @@ return Promise.reject(new Error('No element found'));

if (prototypeValueSetter) {
prototypeValueSetter.call(target, value);
prototypeValueSetter.call(target, desiredValue);
} else {
target.value = value;
target.value = desiredValue;
}

@@ -111,3 +110,2 @@ target.dispatchEvent(new Event('input', {

}, selector, value);
/* eslint-enable no-shadow */
} catch (error) {

@@ -129,9 +127,8 @@ throw new Error(`Failed action: no element matching selector "${selector}"`);

try {
/* eslint-disable no-shadow */
await page.evaluate((selector, checked) => {
const target = document.querySelector(selector);
await page.evaluate((targetSelector, isChecked) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(new Error('No element found'));
}
target.checked = checked;
target.checked = isChecked;
target.dispatchEvent(new Event('change', {

@@ -142,3 +139,2 @@ bubbles: true

}, selector, checked);
/* eslint-enable no-shadow */
} catch (error) {

@@ -193,10 +189,16 @@ throw new Error(`Failed action: no element matching selector "${selector}"`);

/* eslint-disable no-shadow */
await page.waitForFunction((property, expectedValue, negated) => {
if (negated) {
return window.location[property] !== expectedValue;
}
return window.location[property] === expectedValue;
}, {}, property, expectedValue, negated);
/* eslint-enable no-shadow */
function locationHasProperty(locationProperty, value, isNegated) {
return isNegated ?
window.location[locationProperty] !== value :
window.location[locationProperty] === value;
}
await page.waitForFunction(
locationHasProperty,
{},
property,
expectedValue,
negated
);
}

@@ -215,38 +217,40 @@ },

/* eslint-disable no-shadow */
await page.waitForFunction((selector, state) => {
const targetElement = document.querySelector(selector);
await page.waitForFunction((targetSelector, desiredState) => {
const targetElement = document.querySelector(targetSelector);
const statusChecks = {
isAddedOrRemoved: el =>
Boolean(
(desiredState === 'added' && el) ||
(desiredState === 'removed' && !el)
),
isHiddenOrVisible: isVisible =>
Boolean(
(desiredState === 'visible' && isVisible) ||
(desiredState === 'hidden' && !isVisible)
),
isTargetVisible: el =>
Boolean(
el &&
(el.offsetWidth ||
el.offsetHeight ||
el.getClientRects().length)
)
};
// Check for added/removed states
if (state === 'added' && targetElement) {
if (statusChecks.isAddedOrRemoved(targetElement)) {
return true;
}
if (state === 'removed' && !targetElement) {
return true;
}
// Check element visibility
let targetElementVisible = false;
if (targetElement) {
targetElementVisible = Boolean(
targetElement.offsetWidth ||
targetElement.offsetHeight ||
targetElement.getClientRects().length
);
}
const isTargetVisible = statusChecks.isTargetVisible(targetElement);
// Check for visible/hidden states
if (state === 'visible' && targetElementVisible) {
return true;
}
if (state === 'hidden' && !targetElementVisible) {
return true;
}
const isInDesiredVisibilityState = statusChecks.isHiddenOrVisible(isTargetVisible);
// Default to false
return false;
return isInDesiredVisibilityState;
}, {
polling: 200
}, selector, state);
/* eslint-enable no-shadow */
}

@@ -265,14 +269,20 @@ },

try {
/* eslint-disable no-shadow, no-underscore-dangle */
await page.evaluate((selector, eventType) => {
const target = document.querySelector(selector);
if (!target) {
return Promise.reject(new Error('No element found'));
}
target.addEventListener(eventType, () => {
window._pa11yWaitForElementEventFired = true;
}, {
once: true
});
}, selector, eventType);
/* eslint-disable no-underscore-dangle */
await page.evaluate(
(targetSelector, desiredEvent) => {
const target = document.querySelector(targetSelector);
if (!target) {
return Promise.reject(
new Error('No element found')
);
}
target.addEventListener(desiredEvent, () => {
window._pa11yWaitForElementEventFired = true;
}, {
once: true
});
},
selector,
eventType
);
await page.waitForFunction(() => {

@@ -287,3 +297,3 @@ if (window._pa11yWaitForElementEventFired) {

});
/* eslint-enable no-shadow, no-underscore-dangle */
/* eslint-enable no-underscore-dangle */
} catch (error) {

@@ -290,0 +300,0 @@ throw new Error(`Failed action: no element matching selector "${selector}"`);

@@ -22,3 +22,3 @@ 'use strict';

* @public
* @param {String} [url] - The URL to run tests against.
* @param {String} url - The URL to run tests against.
* @param {Object} [options={}] - Options to change the way tests run.

@@ -30,23 +30,7 @@ * @param {Function} [callback] - An optional callback to use instead of promises.

const state = {};
let pa11yError;
let pa11yResults;
[url, options, callback] = parseArguments(url, options, callback);
/* eslint-disable prefer-rest-params */
// Check for presence of a callback function
if (typeof arguments[arguments.length - 1] === 'function') {
callback = arguments[arguments.length - 1];
} else {
callback = undefined;
}
/* eslint-enable prefer-rest-params */
try {
// Switch parameters if only an options object is provided,
// and default the options
if (typeof url !== 'string') {
options = url;
url = options.url;
}
url = sanitizeUrl(url);
options = defaultOptions(options);
// Verify that the given options are valid

@@ -57,3 +41,3 @@ verifyOptions(options);

// a timeout if it takes too long
const results = await promiseTimeout(
pa11yResults = await promiseTimeout(
runPa11yTest(url, options, state),

@@ -63,22 +47,57 @@ options.timeout,

);
// Run callback if present, and resolve with results
} catch (error) {
// Capture error if a callback is provided, otherwise reject with error
if (callback) {
return callback(null, results);
pa11yError = error;
} else {
throw error;
}
return results;
} finally {
await stateCleanup(state);
}
// Run callback if present, and resolve with pa11yResults
return callback ? callback(pa11yError, pa11yResults) : pa11yResults;
}
} catch (error) {
if (state.browser && state.autoClose) {
state.browser.close();
} else if (state.page && state.autoClosePage) {
state.page.close();
}
/**
* Parse arguments from the command-line to properly identify the url, options, and callback
* @private
* @param {String} url - The URL to run tests against.
* @param {Object} [options={}] - Options to change the way tests run.
* @param {Function} [callback] - An optional callback to use instead of promises.
* @returns {Array} the new values of url, options, and callback
*/
function parseArguments(url, options, callback) {
if (!callback && typeof options === 'function') {
callback = options;
options = {};
}
if (typeof url !== 'string') {
options = url;
url = options.url;
}
url = sanitizeUrl(url);
options = defaultOptions(options);
// Run callback if present, and reject with error
if (callback) {
return callback(error);
}
throw error;
return [url,
options,
callback];
}
/**
* Default the passed in options using Pa11y's defaults.
* @private
* @param {Object} [options] - The options to apply defaults to.
* @returns {Object} Returns the defaulted options.
*/
function defaultOptions(options) {
options = extend({}, pa11y.defaults, options);
options.ignore = options.ignore.map(ignored => ignored.toLowerCase());
if (!options.includeNotices) {
options.ignore.push('notice');
}
if (!options.includeWarnings) {
options.ignore.push('warning');
}
return options;
}

@@ -89,5 +108,6 @@

* @private
* @param {String} [url] - The URL to run tests against.
* @param {Object} [options] - Options to change the way tests run.
* @param {Object} [state] - An object state information will be added to.
* @param {String} url - The URL to run tests against.
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} Returns a promise which resolves with a results object.

@@ -99,8 +119,64 @@ */

// Check whether we have a browser already
let browser;
let page;
await setBrowser(options, state);
await setPage(options, state);
await interceptRequests(options, state);
await gotoUrl(url, options, state);
await runActionsList(options, state);
await injectRunners(options, state);
// Launch the test runner!
options.log.debug('Running Pa11y on the page');
/* istanbul ignore next */
if (options.wait > 0) {
options.log.debug(`Waiting for ${options.wait}ms`);
}
const results = await runPa11yWithOptions(options, state);
options.log.debug(`Document title: "${results.documentTitle}"`);
await saveScreenCapture(options, state);
return results;
}
/**
* Ensures that puppeteer resources are freed and listeners removed.
* @private
* @param {Object} state - The last-known state of the test-run.
* @returns {Promise} A promise which resolves when resources are released
*/
async function stateCleanup(state) {
if (state.browser && state.autoClose) {
await state.browser.close();
} else if (state.page) {
state.page.removeListener('request', state.requestInterceptCallback);
state.page.removeListener('console', state.consoleCallback);
if (state.autoClosePage) {
await state.page.close();
}
}
}
/**
* Sets or initialises the browser.
* @private
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when resources are released
*/
async function setBrowser(options, state) {
if (options.browser) {
options.log.debug('Using a pre-configured Headless Chrome instance, the `chromeLaunchConfig` option will be ignored');
browser = state.browser = options.browser;
options.log.debug(
'Using a pre-configured Headless Chrome instance, ' +
'the `chromeLaunchConfig` option will be ignored'
);
state.browser = options.browser;
state.autoClose = false;

@@ -112,14 +188,48 @@ } else {

options.log.debug('Launching Headless Chrome');
browser = state.browser = await puppeteer.launch(options.chromeLaunchConfig);
state.browser = await puppeteer.launch(
options.chromeLaunchConfig
);
state.autoClose = true;
}
}
/**
* Configures the browser page to be used for the test.
* @private
* @param {Object} [options] - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when the page has been configured.
*/
async function setPage(options, state) {
if (options.browser && options.page) {
page = state.page = options.page;
state.page = options.page;
state.autoClosePage = false;
} else {
page = state.page = await browser.newPage();
state.page = await state.browser.newPage();
state.autoClosePage = true;
}
// Listen for console logs on the page so that we can
// output them for debugging purposes
state.consoleCallback = message => {
options.log.debug(`Browser Console: ${message.text()}`);
};
state.page.on('console', state.consoleCallback);
options.log.debug('Opening URL in Headless Chrome');
if (options.userAgent) {
await state.page.setUserAgent(options.userAgent);
}
await state.page.setViewport(options.viewport);
}
/**
* Configures the browser page to intercept requests if necessary
* @private
* @param {Object} [options] - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves immediately if no listeners are necessary
* or after listener functions have been attached.
*/
async function interceptRequests(options, state) {
// Avoid to use `page.setRequestInterception` when not necessary

@@ -129,76 +239,92 @@ // because it occasionally stops page load:

// https://github.com/GoogleChrome/puppeteer/issues/3121
if ((options.headers && Object.keys(options.headers).length) ||
const shouldInterceptRequests =
(options.headers && Object.keys(options.headers).length) ||
(options.method && options.method.toLowerCase() !== 'get') ||
options.postData) {
options.postData;
// Intercept page requests, we need to do this in order
// to set the HTTP method or post data
await page.setRequestInterception(true);
if (!shouldInterceptRequests) {
return;
}
// Intercept page requests, we need to do this in order
// to set the HTTP method or post data
await state.page.setRequestInterception(true);
// Intercept requests so we can set the HTTP method
// and post data. We only want to make changes to the
// first request that's handled, which is the request
// for the page we're testing
let interceptionHandled = false;
page.on('request', interceptedRequest => {
const overrides = {};
if (!interceptionHandled) {
// Intercept requests so we can set the HTTP method
// and post data. We only want to make changes to the
// first request that's handled, which is the request
// for the page we're testing
let interceptionHandled = false;
state.requestInterceptCallback = interceptedRequest => {
const overrides = {};
if (!interceptionHandled) {
// Override the request method
options.log.debug('Setting request method');
overrides.method = options.method;
// Override the request method
options.log.debug('Setting request method');
overrides.method = options.method;
// Override the request headers (and include the user-agent)
options.log.debug('Setting request headers');
overrides.headers = {};
for (const [key, value] of Object.entries(options.headers)) {
overrides.headers[key.toLowerCase()] = value;
}
// Override the request headers (and include the user-agent)
options.log.debug('Setting request headers');
overrides.headers = {};
for (const [key, value] of Object.entries(options.headers)) {
overrides.headers[key.toLowerCase()] = value;
}
// Override the request POST data if present
if (options.postData) {
options.log.debug('Setting request POST data');
overrides.postData = options.postData;
}
interceptionHandled = true;
// Override the request POST data if present
if (options.postData) {
options.log.debug('Setting request POST data');
overrides.postData = options.postData;
}
interceptedRequest.continue(overrides);
});
}
// Listen for console logs on the page so that we can
// output them for debugging purposes
page.on('console', message => {
options.log.debug(`Browser Console: ${message.text()}`);
});
interceptionHandled = true;
}
interceptedRequest.continue(overrides);
};
state.page.on('request', state.requestInterceptCallback);
}
options.log.debug('Opening URL in Headless Chrome');
const gotoConfig = {waitUntil: 'networkidle2'};
gotoConfig.timeout = options.timeout;
if (options.userAgent) {
// Set the user agent
await page.setUserAgent(options.userAgent);
}
// Resize the viewport
await page.setViewport(options.viewport);
/**
* Instructs the page to go to the provided url unless options.ignoreUrl is true
* @private
* @param {String} [url] - The URL of the page to be tested.
* @param {Object} [options] - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when the page URL has been set
*/
async function gotoUrl(url, options, state) {
// Navigate to the URL we're going to test
if (!options.ignoreUrl) {
await page.goto(url, gotoConfig);
await state.page.goto(url, {
waitUntil: 'networkidle2',
timeout: options.timeout
});
}
}
// Run actions
/**
* Carries out a synchronous list of actions in the page
* @private
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when all actions have completed
*/
async function runActionsList(options, state) {
if (options.actions.length) {
options.log.info('Running actions');
for (const action of options.actions) {
await runAction(browser, page, options, action);
await runAction(state.browser, state.page, options, action);
}
options.log.info('Finished running actions');
}
}
// Load the test runners and Pa11y client-side scripts if required
/**
* Loads the test runners and Pa11y client-side scripts if required
* @private
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when all runners have been injected and evaluated
*/
async function injectRunners(options, state) {
// We only load these files once on the first run of Pa11y as they don't

@@ -218,18 +344,23 @@ // change between runs

options.log.debug('Injecting Pa11y');
await page.evaluate(await runnerJavascriptPromises.pa11y);
await state.page.evaluate(await runnerJavascriptPromises.pa11y);
for (const runner of options.runners) {
options.log.debug(`Injecting runner: ${runner}`);
const script = await runnerJavascriptPromises[runner];
await page.evaluate(script);
await state.page.evaluate(script);
}
}
// Launch the test runner!
options.log.debug('Running Pa11y on the page');
/* istanbul ignore next */
if (options.wait > 0) {
options.log.debug(`Waiting for ${options.wait}ms`);
}
/* eslint-disable no-shadow, no-underscore-dangle */
const results = await page.evaluate(options => {
return window.__pa11y.run(options);
/**
* Sends a request to the page to instruct the injected pa11y script to run with the
* provided options
* @private
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves with the results of the pa11y evaluation
*/
function runPa11yWithOptions(options, state) {
/* eslint-disable no-underscore-dangle */
return state.page.evaluate(runOptions => {
return window.__pa11y.run(runOptions);
}, {

@@ -245,11 +376,21 @@ hideElements: options.hideElements,

});
/* eslint-enable no-shadow, no-underscore-dangle */
/* eslint-enable no-underscore-dangle */
}
options.log.debug(`Document title: "${results.documentTitle}"`);
/**
* Generates a screen capture if required by the provided options
* @private
* @param {Object} options - Options to change the way tests run.
* @param {Object} state - The current pa11y internal state, fields will be mutated by
* this function.
* @returns {Promise} A promise which resolves when the screenshot is complete
*/
async function saveScreenCapture(options, state) {
// Generate a screen capture
if (options.screenCapture) {
options.log.info(`Capturing screen, saving to "${options.screenCapture}"`);
options.log.info(
`Capturing screen, saving to "${options.screenCapture}"`
);
try {
await page.screenshot({
await state.page.screenshot({
path: options.screenCapture,

@@ -262,34 +403,8 @@ fullPage: true

}
// Close the browser and return the Pa11y results
if (state.autoClose) {
await browser.close();
} else if (state.autoClosePage) {
await page.close();
}
return results;
}
/**
* Default the passed in options using Pa11y's defaults.
* @private
* @param {Object} [options={}] - The options to apply defaults to.
* @returns {Object} Returns the defaulted options.
*/
function defaultOptions(options) {
options = extend({}, pa11y.defaults, options);
options.ignore = options.ignore.map(ignored => ignored.toLowerCase());
if (!options.includeNotices) {
options.ignore.push('notice');
}
if (!options.includeWarnings) {
options.ignore.push('warning');
}
return options;
}
/**
* Verify that passed in options are valid.
* @private
* @param {Object} [options={}] - The options to verify.
* @param {Object} options - The options to verify.
* @returns {Undefined} Returns nothing.

@@ -365,3 +480,3 @@ * @throws {Error} Throws if options are not valid.

* Loads a runner script
* @param runner
* @param {String} runner - The name of the runner.
* @throws {Error} Throws an error if the reporter does not support the given version of Pa11y

@@ -388,5 +503,3 @@ * @returns {Promise<String>} Promise

/* istanbul ignore next */
/* eslint-disable no-empty-function */
const noop = () => {};
/* eslint-enable no-empty-function */
const noop = () => { /* No-op */ };

@@ -423,3 +536,3 @@ /**

screenCapture: null,
standard: 'WCAG2AA', // DONE
standard: 'WCAG2AA',
timeout: 30000,

@@ -426,0 +539,0 @@ userAgent: `pa11y/${pkg.version}`,

@@ -34,3 +34,3 @@ 'use strict';

if (typeof method !== 'function') {
method = () => {};
method = () => { /* NoOp */ };
}

@@ -37,0 +37,0 @@ return async input => {

{
"name": "pa11y",
"version": "5.3.0",
"version": "6.0.0-alpha",
"description": "Pa11y is your automated accessibility testing pal",

@@ -36,21 +36,22 @@ "keywords": [

"commander": "^3.0.2",
"envinfo": "^7.5.0",
"node.extend": "^2.0.2",
"p-timeout": "^2.0.1",
"pa11y-reporter-cli": "^1.0.1",
"pa11y-reporter-csv": "^1.0.0",
"pa11y-reporter-json": "^1.0.0",
"pa11y-runner-axe": "^1.0.1",
"pa11y-runner-htmlcs": "^1.2.0",
"puppeteer": "^1.13.0",
"semver": "^5.6.0"
"pa11y-reporter-cli": "^2.0.0",
"pa11y-reporter-csv": "^2.0.0",
"pa11y-reporter-json": "^2.0.0",
"pa11y-runner-axe": "^2.0.0",
"pa11y-runner-htmlcs": "^2.0.0",
"puppeteer": "^2.1.1",
"semver": "^5.7.1"
},
"devDependencies": {
"@rowanmanning/make": "^1.0.1",
"eslint": "^6.0.1",
"mocha": "^6.1.4",
"mockery": "^2.0.0",
"nyc": "~13.2.0",
"@rowanmanning/make": "^2.1.0",
"eslint": "^6.8.0",
"mocha": "^7.1.1",
"mockery": "^2.1.0",
"nyc": "^15.0.1",
"pa11y-lint-config": "^1.2.1",
"proclaim": "^3.5.1",
"sinon": "^7.0.0"
"proclaim": "^3.6.0",
"sinon": "^9.0.2"
},

@@ -57,0 +58,0 @@ "main": "./lib/pa11y.js",

@@ -12,8 +12,2 @@

---
:sparkles: ☑️ 👩‍🎨 **Hi! We’re working on improving the design and usability of the Pa11y website. You can help us enormously by [filling in our survey](https://forms.gle/ZJzFwbC7DCVT2CNh7). Thanks!**
---
On the command line:

@@ -61,4 +55,9 @@

On a Mac, you can install the required dependency with [Homebrew][brew]:
To install [Node.js][node] you can use [nvm][nvm]:
```sh
$ nvm install node
```
Alternatively on a Mac, you can install the required dependency with [Homebrew][brew]:
```sh

@@ -68,3 +67,3 @@ $ brew install node

Alternatively download pre-built packages from the [Node.js][node] website.
You can also download pre-built packages from the [Node.js][node] website.

@@ -1023,2 +1022,3 @@ ### Linux

[npm]: https://www.npmjs.com/
[nvm]: https://github.com/nvm-sh/nvm
[promise]: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise

@@ -1025,0 +1025,0 @@ [puppeteer-browser]: https://github.com/GoogleChrome/puppeteer/blob/master/docs/api.md#class-browser

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