├── .eslintignore
├── .eslintrc.json
├── .github
└── workflows
│ └── ci.yml
├── .gitignore
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── extensions.json
└── settings.json
├── CONTRIBUTING.md
├── LICENSE.txt
├── README.md
├── lerna.json
├── package-lock.json
├── package.json
└── packages
├── check-es-compat
├── README.md
├── bin
│ └── cli.js
├── package-lock.json
└── package.json
├── eslint-plugin-ecmascript-compat-example
├── .browserslistrc
├── .eslintrc.json
├── package-lock.json
├── package.json
└── src
│ └── app.js
└── eslint-plugin-ecmascript-compat
├── .gitignore
├── README.md
├── lib
├── compareVersions.js
├── compareVersions.test.js
├── compatibility.js
├── compatibility.test.js
├── delegation.js
├── delegation.test.js
├── features
│ ├── es-versions.md
│ ├── es2016.js
│ ├── es2016.test.js
│ ├── es2017.js
│ ├── es2017.test.js
│ ├── es2018.js
│ ├── es2018.test.js
│ ├── es2019.js
│ ├── es2019.test.js
│ ├── es2020.js
│ ├── es2020.test.js
│ ├── es2021.js
│ ├── es2021.test.js
│ ├── es2022.js
│ ├── es2022.test.js
│ ├── es2023.js
│ ├── es2023.test.js
│ ├── index.js
│ └── ruleOptionsUtil.js
├── index.js
├── rule.js
├── rule.test.js
├── targetRuntimes.js
└── targetRuntimes.test.js
├── package-lock.json
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Example has deliberate errors for demonstration purposes
2 | /packages/eslint-plugin-ecmascript-compat-example
3 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | // Prettier presets are partial "anti-presets" for other presets, that disable unnecessary/conflicting rules.
4 |
5 | /*
6 | * Enable all rules:
7 | * 1. Majority of rules and default options are good
8 | * 2. eslint:recommended is only a small subset
9 | * 3. We automatically gain new rules when they are released
10 | */
11 | "eslint:all",
12 | "prettier",
13 |
14 | // Need to be specific, because this config is one level above the package.jsons that have type:module
15 | "plugin:n/recommended-module"
16 | ],
17 | "plugins": ["import"],
18 | "parserOptions": {
19 | "ecmaVersion": 2022,
20 | "sourceType": "module"
21 | },
22 | "env": {
23 | "es2021": true,
24 | "node": true
25 | },
26 | "reportUnusedDisableDirectives": true,
27 | "rules": {
28 | // eslint:all - Disable unwanted rules. Add appropriate others as and when they're discovered.
29 | "capitalized-comments": "off",
30 | "global-require": "off",
31 | "init-declarations": "off",
32 | "line-comment-position": "off",
33 | "multiline-comment-style": "off",
34 | "no-eq-null": "off",
35 | "no-inline-comments": "off",
36 | "no-magic-numbers": "off",
37 | "no-plusplus": "off",
38 | "no-ternary": "off",
39 | "no-undefined": "off",
40 | "one-var": "off",
41 | "sort-imports": "off", // using import/order instead
42 | "sort-keys": "off",
43 | "strict": "off",
44 |
45 | // eslint:all - Modify default options
46 | "eqeqeq": ["error", "always", { "null": "never" }],
47 | "func-names": ["error", "as-needed"],
48 | "func-style": ["error", "declaration"],
49 | "id-length": ["error", { "exceptions": ["_", "a", "b", "i"] }],
50 | "no-unused-vars": ["error", { "ignoreRestSiblings": true }],
51 | "no-use-before-define": ["error", "nofunc"],
52 | "spaced-comment": ["error", "always", { "block": { "balanced": true } }],
53 |
54 | // eslint:all & prettier - Re-enable some of the rules that are compatible when certain options are used
55 | // (https://github.com/prettier/eslint-config-prettier#special-rules)
56 | "curly": "error",
57 | "max-len": ["error", { "code": 1000, "comments": 90, "ignoreUrls": true }],
58 | "quotes": [
59 | "error",
60 | "single",
61 | { "avoidEscape": true, "allowTemplateLiterals": false }
62 | ],
63 |
64 | // eslint:all - Rules whose default options do nothing. Options need to be compatible with Prettier.
65 | "padding-line-between-statements": [
66 | "error",
67 | { "blankLine": "always", "prev": "*", "next": ["cjs-export"] },
68 |
69 | { "blankLine": "always", "prev": "*", "next": "block-like" },
70 | { "blankLine": "always", "prev": "block-like", "next": "*" }
71 | ],
72 |
73 | // eslint-plugin-import - selection (not comprehensive)
74 | "import/newline-after-import": "error",
75 | "import/no-extraneous-dependencies": "error",
76 | "import/order": ["error", { "newlines-between": "never" }]
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: Node CI
2 |
3 | on:
4 | push:
5 | branches:
6 | - 'master'
7 | pull_request:
8 | types: [opened, synchronize, reopened]
9 |
10 | jobs:
11 | ci:
12 | runs-on: ubuntu-latest
13 |
14 | strategy:
15 | matrix:
16 | node-version: [16.x, 18.x, 20.x]
17 |
18 | steps:
19 | - uses: actions/checkout@v3
20 | - name: Use Node.js ${{ matrix.node-version }}
21 | uses: actions/setup-node@v3
22 | with:
23 | node-version: ${{ matrix.node-version }}
24 |
25 | - run: npm install
26 | - run: npm run ci
27 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules
2 | /packages/*/node_modules
3 |
4 | # Patterns for /packages must go in the individual packages, as that's the only place
5 | # where lerna publish will look. See https://github.com/robatwilliams/es-compat/issues/8 .
6 | # Not using .npmignore files, to avoid possibility of getting out of sync.
7 |
8 | # Adding something? Might also need to go in .prettierignore
9 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | lerna.json
2 | package-lock.json
3 |
4 | /packages/*/coverage
5 |
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "printWidth": 90,
3 | "singleQuote": true,
4 | "overrides": [
5 | {
6 | "files": "*.md",
7 | "options": {
8 | "printWidth": 120,
9 | "proseWrap": "never"
10 | }
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.defaultFormatter": "esbenp.prettier-vscode",
3 | "editor.formatOnSave": true,
4 | "editor.rulers": [90], // Prettier: printWidth
5 |
6 | "files.associations": {
7 | ".eslintrc.json": "jsonc"
8 | },
9 |
10 | "files.eol": "\n",
11 | "files.insertFinalNewline": true,
12 | "files.trimFinalNewlines": true,
13 | "files.trimTrailingWhitespace": true,
14 |
15 | // Prevent ESLint extension getting confused in monorepo
16 | // https://github.com/microsoft/vscode-eslint/issues/696#issuecomment-553697002
17 | "eslint.workingDirectories": ["./"],
18 |
19 | "[markdown]": {
20 | "editor.rulers": [120] // Prettier: *.md printWidth
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | Please get in touch before spending any significant time preparing contributions.
4 |
5 | ## Prerequisites
6 |
7 | - Node.js and NPM, versions as per the root `package.json` `engines` field
8 | - Lerna 4, just install it globally and [it'll use this project's local version](https://github.com/lerna/lerna/pull/1122) when run
9 |
10 | Different versions may work, but majorly newer/older tooling versions are likely to cause upheaval in `package-lock.json` files.
11 |
12 | ## Workflow
13 |
14 | - Self-explanatory NPM scripts in root and packages
15 | - Prettier and ESLint for code hygiene
16 |
17 | ## Pre-release checks
18 |
19 | - Verify there are no uncommitted changes
20 | - `npm run ci` in root
21 | - `npm run lint` in the example project, check number of errors and presence of new expected ones
22 | - `../check-es-compat/bin/cli.js .` in the example project, it should produce the same errors
23 | - `lerna clean` then `lerna bootstrap`, verify no changes were introduced (e.g. to `package-lock.json`)
24 |
25 | ## Releasing
26 |
27 | 1. `lerna version`, with arguments as appropriate for signifigance of release
28 | 1. Verify the commit that it made did what you expected
29 | 1. `lerna publish from-git`
30 | 1. In GitHub's Releases tab, open the new tag then create a release out of it
31 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Robat Williams
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://badge.fury.io/js/eslint-plugin-ecmascript-compat)
3 | [](http://www.npmtrends.com/eslint-plugin-ecmascript-compat)
4 |
5 |
6 | # es-compat
7 |
8 | > Check JavaScript code compatibility with target browsers and Node.js versions
9 |
10 | Checks that the language features used in your code/bundles are supported by your [browserslist](https://github.com/browserslist/browserslist) targets.
11 |
12 | ## Tools
13 |
14 | - [check-es-compat](/packages/check-es-compat/README.md) - standalone CLI tool
15 | - [eslint-plugin-ecmascript-compat](/packages/eslint-plugin-ecmascript-compat/README.md) - ESLint plugin
16 |
17 | ## Rationale
18 |
19 | You might not need a transpiler or polyfills.
20 |
21 | Or, you may be transpiling your own code but not prebuilt 3rd-party libraries - leaving you open to breakages when they use new language features.
22 |
23 | [ESLint](https://eslint.org) supports targeting a specific ECMAScript version, and [eslint-plugin-es-x](https://github.com/eslint-community/eslint-plugin-es-x) allows forbidding individual language features. However when building applications, what we target are particular browser/runtime versions. This project lets you check compatibility by specifying those targets directly via a browserslist. It will figure out which individual features you can use, by looking up those targets in the [MDN compatibility dataset](https://github.com/mdn/browser-compat-data).
24 |
25 | ## Usage scenario examples
26 |
27 | If you're not using a transpiler, run the tool/linter on your source code to ensure you're not using language features that aren't supported in your application's supported browsers.
28 |
29 | If you transpile your own code but not 3rd party libraries, run the tool/linter on your output bundles to ensure they're not using language features that aren't supported in your application's supported browsers.
30 |
31 | ## Scope
32 |
33 | ECMAScript language features only; this includes syntax, built-ins, and methods.
34 |
35 | It doesn't check browser/runtime-specific APIs (see [eslint-plugin-compat](https://github.com/amilajack/eslint-plugin-compat)), or CSS (see [doiuse](https://github.com/anandthakker/doiuse)).
36 |
37 | ## ECMAScript version coverage
38 |
39 | - ✅ [ES2023](https://pawelgrzybek.com/whats-new-in-ecmascript-2023)
40 | - ✅ [ES2022](https://exploringjs.com/impatient-js/ch_new-javascript-features.html#new-in-es2022)
41 | - ✅ [ES2021](https://v8.dev/features/tags/es2021)
42 | - ✅ [ES2020](https://v8.dev/features/tags/es2020)
43 | - ✅ [ES2019](https://flaviocopes.com/es2019)1, 2
44 | - ✅ [ES2018](https://flaviocopes.com/es2018)
45 | - ✅ [ES2017](https://flaviocopes.com/es2017)
46 | - ✅ [ES2016](https://flaviocopes.com/es2016)
47 | - ⛔ [ES2015 (ES6)](https://flaviocopes.com/es6)3
48 | - ⛔ ES54
49 |
50 |
51 | n Expand for footnotes...
52 |
53 | 1 Excluding features not statically detectable: revised `Function.prototype.toString`, stable `Array.prototype.sort`, well-formed `JSON.stringify`.
54 |
55 | 2 Excluding `Symbol.prototype.description`; as a debug feature, it's not worth the false positives that arise due to its name and not being a method.
56 |
57 | 3 ES2015 (ES6) is out of scope; it's been [supported](https://caniuse.com/#feat=es6) by evergreen browsers for many years. Assisting you to continue supporting [IE11](https://death-to-ie11.com/) is not a goal of this tool.
58 |
59 | 4 ES5 is out of scope; it's over 10 years old and [supported](https://caniuse.com/es6#feat=es5) even in IE10.
60 |
61 |
62 |
63 | ## Browser compatibility data
64 |
65 | We use a pinned version of `@mdn/browser-compat-data`, because their [SemVer policy](https://github.com/mdn/browser-compat-data#semantic-versioning-policy) allows for breaking changes to the data structure even in minor and patch releases. If you need to use more up to date data, use the `overrides` facility of `package.json` to specify a later version - but be aware that it might break.
66 |
67 | ## Limitations
68 |
69 | Because JavaScript is untyped, detection of some features' usage (namely prototype methods) through static analysis requires some assumptions to be made. This shouldn't be a problem as long as you avoid creating your own methods having the same names, or write code in an unusual way to deliberately evade detection.
70 |
71 | Support can only be checked for the [browsers and runtimes covered](https://github.com/mdn/browser-compat-data/tree/main/browsers) by the MDN compatibility dataset.
72 |
73 | The MDN compatibility dataset has very good feature coverage of the top ~6 desktop and mobile browsers, and Node.js (much more than [kangax/compat-table](https://github.com/kangax/compat-table)). In case of missing data for a feature (support unknown, or unknown in which version support was added), we currently assume support.
74 |
75 | ## Contributing
76 |
77 | [Contributions](CONTRIBUTING.md) and feedback welcome. Please see the GitHub issues or create one, as appropriate.
78 |
79 | ## Related
80 |
81 | - [eslint-plugin-compat](https://github.com/amilajack/eslint-plugin-compat) - for browser APIs
82 | - [doiuse](https://github.com/anandthakker/doiuse) - for CSS
83 | - [eslint-plugin-es-x](https://github.com/eslint-community/eslint-plugin-es-x) (formerly [eslint-plugin-es](https://github.com/mysticatea/eslint-plugin-es))\*
84 | - [@mdn/browser-compat-data](https://github.com/mdn/browser-compat-data)\*
85 |
86 | \* Thanks to these projects in particular (and many others) for making this project possible.
87 |
--------------------------------------------------------------------------------
/lerna.json:
--------------------------------------------------------------------------------
1 | {
2 | "packages": [
3 | "packages/*"
4 | ],
5 | "version": "3.2.1"
6 | }
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "es-compat",
3 | "private": true,
4 | "scripts": {
5 | "check": "npm-run-all --parallel check:*",
6 | "check:lint": "eslint --no-eslintrc --config=.eslintrc.json **/*.js",
7 | "check:prettier": "prettier --check **/*.{js,json,md}",
8 | "ci": "npm-run-all check test",
9 | "postinstall": "lerna bootstrap",
10 | "test": "lerna run test"
11 | },
12 | "devDependencies": {
13 | "eslint": "^8.56.0",
14 | "eslint-config-prettier": "^8.3.0",
15 | "eslint-plugin-import": "^2.25.4",
16 | "eslint-plugin-n": "^15.7.0",
17 | "lerna": "^4.0.0",
18 | "npm-run-all": "^4.1.5",
19 | "prettier": "^2.5.1"
20 | },
21 | "engines": {
22 | "node": ">=16.0.0",
23 | "npm": "^10.2.3"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/check-es-compat/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://badge.fury.io/js/check-es-compat)
3 | [](http://www.npmtrends.com/check-es-compat)
4 |
5 |
6 | # check-es-compat
7 |
8 | > CLI tool for checking JavaScript code compatibility with target browsers and Node.js versions
9 |
10 | ```bash
11 | $ npx check-es-compat .
12 | ```
13 |
14 | ```
15 | // .browserslistrc
16 | Chrome >= 64
17 | Firefox >= 58
18 | ```
19 |
20 |
21 |
22 | It [doesn't currently support](https://github.com/robatwilliams/es-compat/issues/69) ES modules.
23 |
24 |
25 |
26 | ➡ For more information, see the [main readme](https://github.com/robatwilliams/es-compat#readme).
27 |
--------------------------------------------------------------------------------
/packages/check-es-compat/bin/cli.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /* eslint-disable no-console */
3 | import { ESLint } from 'eslint';
4 |
5 | const args = process.argv.slice(2);
6 |
7 | if (args.length === 0) {
8 | console.log('Usage: check-es-compat file.js [file.js] [dir]');
9 | process.exitCode = 1;
10 | } else {
11 | const { hasErrors } = await execute(args);
12 |
13 | if (hasErrors) {
14 | process.exitCode = 1;
15 | } else {
16 | console.log('No issues found. Files are compatible with the target runtimes.');
17 | }
18 | }
19 |
20 | async function execute(files) {
21 | const eslint = new ESLint({
22 | // Ignore any config; it's for target's own linter setup rather than this tool.
23 | useEslintrc: false,
24 | ignore: false,
25 | allowInlineConfig: false,
26 |
27 | baseConfig: {
28 | plugins: ['ecmascript-compat'],
29 | parserOptions: {
30 | // Latest version, so all features work
31 | ecmaVersion: 2023,
32 | },
33 | env: {
34 | // Latest globals, so all features work
35 | es2023: true,
36 | },
37 | rules: {
38 | 'ecmascript-compat/compat': 'error',
39 | },
40 | },
41 | });
42 |
43 | const results = await eslint.lintFiles(files);
44 |
45 | const formatter = await eslint.loadFormatter();
46 | console.log(formatter.format(results));
47 |
48 | return { hasErrors: results.some((result) => result.errorCount > 0) };
49 | }
50 |
--------------------------------------------------------------------------------
/packages/check-es-compat/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "check-es-compat",
3 | "version": "3.2.1",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "check-es-compat",
9 | "version": "3.2.0",
10 | "license": "MIT",
11 | "dependencies": {
12 | "eslint": "^8.56.0"
13 | },
14 | "bin": {
15 | "check-es-compat": "bin/cli.mjs"
16 | },
17 | "engines": {
18 | "node": ">=16.0.0"
19 | }
20 | },
21 | "node_modules/@aashutoshrathi/word-wrap": {
22 | "version": "1.2.6",
23 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
24 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==",
25 | "engines": {
26 | "node": ">=0.10.0"
27 | }
28 | },
29 | "node_modules/@eslint-community/eslint-utils": {
30 | "version": "4.4.0",
31 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
32 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
33 | "dependencies": {
34 | "eslint-visitor-keys": "^3.3.0"
35 | },
36 | "engines": {
37 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
38 | },
39 | "peerDependencies": {
40 | "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
41 | }
42 | },
43 | "node_modules/@eslint-community/regexpp": {
44 | "version": "4.10.0",
45 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
46 | "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==",
47 | "engines": {
48 | "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
49 | }
50 | },
51 | "node_modules/@eslint/eslintrc": {
52 | "version": "2.1.4",
53 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
54 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
55 | "dependencies": {
56 | "ajv": "^6.12.4",
57 | "debug": "^4.3.2",
58 | "espree": "^9.6.0",
59 | "globals": "^13.19.0",
60 | "ignore": "^5.2.0",
61 | "import-fresh": "^3.2.1",
62 | "js-yaml": "^4.1.0",
63 | "minimatch": "^3.1.2",
64 | "strip-json-comments": "^3.1.1"
65 | },
66 | "engines": {
67 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
68 | },
69 | "funding": {
70 | "url": "https://opencollective.com/eslint"
71 | }
72 | },
73 | "node_modules/@eslint/js": {
74 | "version": "8.56.0",
75 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
76 | "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==",
77 | "engines": {
78 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
79 | }
80 | },
81 | "node_modules/@humanwhocodes/config-array": {
82 | "version": "0.11.14",
83 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
84 | "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
85 | "dependencies": {
86 | "@humanwhocodes/object-schema": "^2.0.2",
87 | "debug": "^4.3.1",
88 | "minimatch": "^3.0.5"
89 | },
90 | "engines": {
91 | "node": ">=10.10.0"
92 | }
93 | },
94 | "node_modules/@humanwhocodes/module-importer": {
95 | "version": "1.0.1",
96 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
97 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
98 | "engines": {
99 | "node": ">=12.22"
100 | },
101 | "funding": {
102 | "type": "github",
103 | "url": "https://github.com/sponsors/nzakas"
104 | }
105 | },
106 | "node_modules/@humanwhocodes/object-schema": {
107 | "version": "2.0.2",
108 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
109 | "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw=="
110 | },
111 | "node_modules/@nodelib/fs.scandir": {
112 | "version": "2.1.5",
113 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
114 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
115 | "dependencies": {
116 | "@nodelib/fs.stat": "2.0.5",
117 | "run-parallel": "^1.1.9"
118 | },
119 | "engines": {
120 | "node": ">= 8"
121 | }
122 | },
123 | "node_modules/@nodelib/fs.stat": {
124 | "version": "2.0.5",
125 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
126 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
127 | "engines": {
128 | "node": ">= 8"
129 | }
130 | },
131 | "node_modules/@nodelib/fs.walk": {
132 | "version": "1.2.8",
133 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
134 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
135 | "dependencies": {
136 | "@nodelib/fs.scandir": "2.1.5",
137 | "fastq": "^1.6.0"
138 | },
139 | "engines": {
140 | "node": ">= 8"
141 | }
142 | },
143 | "node_modules/@ungap/structured-clone": {
144 | "version": "1.2.0",
145 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
146 | "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
147 | },
148 | "node_modules/acorn": {
149 | "version": "8.11.3",
150 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
151 | "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==",
152 | "bin": {
153 | "acorn": "bin/acorn"
154 | },
155 | "engines": {
156 | "node": ">=0.4.0"
157 | }
158 | },
159 | "node_modules/acorn-jsx": {
160 | "version": "5.3.2",
161 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
162 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
163 | "peerDependencies": {
164 | "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
165 | }
166 | },
167 | "node_modules/ajv": {
168 | "version": "6.12.6",
169 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
170 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
171 | "dependencies": {
172 | "fast-deep-equal": "^3.1.1",
173 | "fast-json-stable-stringify": "^2.0.0",
174 | "json-schema-traverse": "^0.4.1",
175 | "uri-js": "^4.2.2"
176 | },
177 | "funding": {
178 | "type": "github",
179 | "url": "https://github.com/sponsors/epoberezkin"
180 | }
181 | },
182 | "node_modules/ansi-regex": {
183 | "version": "5.0.1",
184 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
185 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
186 | "engines": {
187 | "node": ">=8"
188 | }
189 | },
190 | "node_modules/ansi-styles": {
191 | "version": "4.3.0",
192 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
193 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
194 | "dependencies": {
195 | "color-convert": "^2.0.1"
196 | },
197 | "engines": {
198 | "node": ">=8"
199 | },
200 | "funding": {
201 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
202 | }
203 | },
204 | "node_modules/argparse": {
205 | "version": "2.0.1",
206 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
207 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
208 | },
209 | "node_modules/balanced-match": {
210 | "version": "1.0.2",
211 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
212 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
213 | },
214 | "node_modules/brace-expansion": {
215 | "version": "1.1.11",
216 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
217 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
218 | "dependencies": {
219 | "balanced-match": "^1.0.0",
220 | "concat-map": "0.0.1"
221 | }
222 | },
223 | "node_modules/callsites": {
224 | "version": "3.1.0",
225 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
226 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
227 | "engines": {
228 | "node": ">=6"
229 | }
230 | },
231 | "node_modules/chalk": {
232 | "version": "4.1.2",
233 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
234 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
235 | "dependencies": {
236 | "ansi-styles": "^4.1.0",
237 | "supports-color": "^7.1.0"
238 | },
239 | "engines": {
240 | "node": ">=10"
241 | },
242 | "funding": {
243 | "url": "https://github.com/chalk/chalk?sponsor=1"
244 | }
245 | },
246 | "node_modules/color-convert": {
247 | "version": "2.0.1",
248 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
249 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
250 | "dependencies": {
251 | "color-name": "~1.1.4"
252 | },
253 | "engines": {
254 | "node": ">=7.0.0"
255 | }
256 | },
257 | "node_modules/color-name": {
258 | "version": "1.1.4",
259 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
260 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
261 | },
262 | "node_modules/concat-map": {
263 | "version": "0.0.1",
264 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
265 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
266 | },
267 | "node_modules/cross-spawn": {
268 | "version": "7.0.3",
269 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
270 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
271 | "dependencies": {
272 | "path-key": "^3.1.0",
273 | "shebang-command": "^2.0.0",
274 | "which": "^2.0.1"
275 | },
276 | "engines": {
277 | "node": ">= 8"
278 | }
279 | },
280 | "node_modules/debug": {
281 | "version": "4.3.4",
282 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
283 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
284 | "dependencies": {
285 | "ms": "2.1.2"
286 | },
287 | "engines": {
288 | "node": ">=6.0"
289 | },
290 | "peerDependenciesMeta": {
291 | "supports-color": {
292 | "optional": true
293 | }
294 | }
295 | },
296 | "node_modules/deep-is": {
297 | "version": "0.1.4",
298 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
299 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
300 | },
301 | "node_modules/doctrine": {
302 | "version": "3.0.0",
303 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
304 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
305 | "dependencies": {
306 | "esutils": "^2.0.2"
307 | },
308 | "engines": {
309 | "node": ">=6.0.0"
310 | }
311 | },
312 | "node_modules/escape-string-regexp": {
313 | "version": "4.0.0",
314 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
315 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
316 | "engines": {
317 | "node": ">=10"
318 | },
319 | "funding": {
320 | "url": "https://github.com/sponsors/sindresorhus"
321 | }
322 | },
323 | "node_modules/eslint": {
324 | "version": "8.56.0",
325 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
326 | "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
327 | "dependencies": {
328 | "@eslint-community/eslint-utils": "^4.2.0",
329 | "@eslint-community/regexpp": "^4.6.1",
330 | "@eslint/eslintrc": "^2.1.4",
331 | "@eslint/js": "8.56.0",
332 | "@humanwhocodes/config-array": "^0.11.13",
333 | "@humanwhocodes/module-importer": "^1.0.1",
334 | "@nodelib/fs.walk": "^1.2.8",
335 | "@ungap/structured-clone": "^1.2.0",
336 | "ajv": "^6.12.4",
337 | "chalk": "^4.0.0",
338 | "cross-spawn": "^7.0.2",
339 | "debug": "^4.3.2",
340 | "doctrine": "^3.0.0",
341 | "escape-string-regexp": "^4.0.0",
342 | "eslint-scope": "^7.2.2",
343 | "eslint-visitor-keys": "^3.4.3",
344 | "espree": "^9.6.1",
345 | "esquery": "^1.4.2",
346 | "esutils": "^2.0.2",
347 | "fast-deep-equal": "^3.1.3",
348 | "file-entry-cache": "^6.0.1",
349 | "find-up": "^5.0.0",
350 | "glob-parent": "^6.0.2",
351 | "globals": "^13.19.0",
352 | "graphemer": "^1.4.0",
353 | "ignore": "^5.2.0",
354 | "imurmurhash": "^0.1.4",
355 | "is-glob": "^4.0.0",
356 | "is-path-inside": "^3.0.3",
357 | "js-yaml": "^4.1.0",
358 | "json-stable-stringify-without-jsonify": "^1.0.1",
359 | "levn": "^0.4.1",
360 | "lodash.merge": "^4.6.2",
361 | "minimatch": "^3.1.2",
362 | "natural-compare": "^1.4.0",
363 | "optionator": "^0.9.3",
364 | "strip-ansi": "^6.0.1",
365 | "text-table": "^0.2.0"
366 | },
367 | "bin": {
368 | "eslint": "bin/eslint.js"
369 | },
370 | "engines": {
371 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
372 | },
373 | "funding": {
374 | "url": "https://opencollective.com/eslint"
375 | }
376 | },
377 | "node_modules/eslint-scope": {
378 | "version": "7.2.2",
379 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
380 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
381 | "dependencies": {
382 | "esrecurse": "^4.3.0",
383 | "estraverse": "^5.2.0"
384 | },
385 | "engines": {
386 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
387 | },
388 | "funding": {
389 | "url": "https://opencollective.com/eslint"
390 | }
391 | },
392 | "node_modules/eslint-visitor-keys": {
393 | "version": "3.4.3",
394 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
395 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
396 | "engines": {
397 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
398 | },
399 | "funding": {
400 | "url": "https://opencollective.com/eslint"
401 | }
402 | },
403 | "node_modules/espree": {
404 | "version": "9.6.1",
405 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
406 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
407 | "dependencies": {
408 | "acorn": "^8.9.0",
409 | "acorn-jsx": "^5.3.2",
410 | "eslint-visitor-keys": "^3.4.1"
411 | },
412 | "engines": {
413 | "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
414 | },
415 | "funding": {
416 | "url": "https://opencollective.com/eslint"
417 | }
418 | },
419 | "node_modules/esquery": {
420 | "version": "1.5.0",
421 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
422 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
423 | "dependencies": {
424 | "estraverse": "^5.1.0"
425 | },
426 | "engines": {
427 | "node": ">=0.10"
428 | }
429 | },
430 | "node_modules/esrecurse": {
431 | "version": "4.3.0",
432 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
433 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
434 | "dependencies": {
435 | "estraverse": "^5.2.0"
436 | },
437 | "engines": {
438 | "node": ">=4.0"
439 | }
440 | },
441 | "node_modules/estraverse": {
442 | "version": "5.3.0",
443 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
444 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
445 | "engines": {
446 | "node": ">=4.0"
447 | }
448 | },
449 | "node_modules/esutils": {
450 | "version": "2.0.3",
451 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
452 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
453 | "engines": {
454 | "node": ">=0.10.0"
455 | }
456 | },
457 | "node_modules/fast-deep-equal": {
458 | "version": "3.1.3",
459 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
460 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
461 | },
462 | "node_modules/fast-json-stable-stringify": {
463 | "version": "2.1.0",
464 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
465 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
466 | },
467 | "node_modules/fast-levenshtein": {
468 | "version": "2.0.6",
469 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
470 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
471 | },
472 | "node_modules/fastq": {
473 | "version": "1.16.0",
474 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
475 | "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
476 | "dependencies": {
477 | "reusify": "^1.0.4"
478 | }
479 | },
480 | "node_modules/file-entry-cache": {
481 | "version": "6.0.1",
482 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
483 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
484 | "dependencies": {
485 | "flat-cache": "^3.0.4"
486 | },
487 | "engines": {
488 | "node": "^10.12.0 || >=12.0.0"
489 | }
490 | },
491 | "node_modules/find-up": {
492 | "version": "5.0.0",
493 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
494 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
495 | "dependencies": {
496 | "locate-path": "^6.0.0",
497 | "path-exists": "^4.0.0"
498 | },
499 | "engines": {
500 | "node": ">=10"
501 | },
502 | "funding": {
503 | "url": "https://github.com/sponsors/sindresorhus"
504 | }
505 | },
506 | "node_modules/flat-cache": {
507 | "version": "3.0.4",
508 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
509 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
510 | "dependencies": {
511 | "flatted": "^3.1.0",
512 | "rimraf": "^3.0.2"
513 | },
514 | "engines": {
515 | "node": "^10.12.0 || >=12.0.0"
516 | }
517 | },
518 | "node_modules/flatted": {
519 | "version": "3.2.4",
520 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
521 | "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
522 | },
523 | "node_modules/fs.realpath": {
524 | "version": "1.0.0",
525 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
526 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
527 | },
528 | "node_modules/glob": {
529 | "version": "7.2.0",
530 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
531 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
532 | "dependencies": {
533 | "fs.realpath": "^1.0.0",
534 | "inflight": "^1.0.4",
535 | "inherits": "2",
536 | "minimatch": "^3.0.4",
537 | "once": "^1.3.0",
538 | "path-is-absolute": "^1.0.0"
539 | },
540 | "engines": {
541 | "node": "*"
542 | },
543 | "funding": {
544 | "url": "https://github.com/sponsors/isaacs"
545 | }
546 | },
547 | "node_modules/glob-parent": {
548 | "version": "6.0.2",
549 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
550 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
551 | "dependencies": {
552 | "is-glob": "^4.0.3"
553 | },
554 | "engines": {
555 | "node": ">=10.13.0"
556 | }
557 | },
558 | "node_modules/globals": {
559 | "version": "13.24.0",
560 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
561 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
562 | "dependencies": {
563 | "type-fest": "^0.20.2"
564 | },
565 | "engines": {
566 | "node": ">=8"
567 | },
568 | "funding": {
569 | "url": "https://github.com/sponsors/sindresorhus"
570 | }
571 | },
572 | "node_modules/graphemer": {
573 | "version": "1.4.0",
574 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
575 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
576 | },
577 | "node_modules/has-flag": {
578 | "version": "4.0.0",
579 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
580 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
581 | "engines": {
582 | "node": ">=8"
583 | }
584 | },
585 | "node_modules/ignore": {
586 | "version": "5.3.0",
587 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
588 | "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
589 | "engines": {
590 | "node": ">= 4"
591 | }
592 | },
593 | "node_modules/import-fresh": {
594 | "version": "3.3.0",
595 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
596 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
597 | "dependencies": {
598 | "parent-module": "^1.0.0",
599 | "resolve-from": "^4.0.0"
600 | },
601 | "engines": {
602 | "node": ">=6"
603 | },
604 | "funding": {
605 | "url": "https://github.com/sponsors/sindresorhus"
606 | }
607 | },
608 | "node_modules/imurmurhash": {
609 | "version": "0.1.4",
610 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
611 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=",
612 | "engines": {
613 | "node": ">=0.8.19"
614 | }
615 | },
616 | "node_modules/inflight": {
617 | "version": "1.0.6",
618 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
619 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
620 | "dependencies": {
621 | "once": "^1.3.0",
622 | "wrappy": "1"
623 | }
624 | },
625 | "node_modules/inherits": {
626 | "version": "2.0.4",
627 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
628 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
629 | },
630 | "node_modules/is-extglob": {
631 | "version": "2.1.1",
632 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
633 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
634 | "engines": {
635 | "node": ">=0.10.0"
636 | }
637 | },
638 | "node_modules/is-glob": {
639 | "version": "4.0.3",
640 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
641 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
642 | "dependencies": {
643 | "is-extglob": "^2.1.1"
644 | },
645 | "engines": {
646 | "node": ">=0.10.0"
647 | }
648 | },
649 | "node_modules/is-path-inside": {
650 | "version": "3.0.3",
651 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
652 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==",
653 | "engines": {
654 | "node": ">=8"
655 | }
656 | },
657 | "node_modules/isexe": {
658 | "version": "2.0.0",
659 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
660 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
661 | },
662 | "node_modules/js-yaml": {
663 | "version": "4.1.0",
664 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
665 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
666 | "dependencies": {
667 | "argparse": "^2.0.1"
668 | },
669 | "bin": {
670 | "js-yaml": "bin/js-yaml.js"
671 | }
672 | },
673 | "node_modules/json-schema-traverse": {
674 | "version": "0.4.1",
675 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
676 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
677 | },
678 | "node_modules/json-stable-stringify-without-jsonify": {
679 | "version": "1.0.1",
680 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
681 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
682 | },
683 | "node_modules/levn": {
684 | "version": "0.4.1",
685 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
686 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
687 | "dependencies": {
688 | "prelude-ls": "^1.2.1",
689 | "type-check": "~0.4.0"
690 | },
691 | "engines": {
692 | "node": ">= 0.8.0"
693 | }
694 | },
695 | "node_modules/locate-path": {
696 | "version": "6.0.0",
697 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
698 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
699 | "dependencies": {
700 | "p-locate": "^5.0.0"
701 | },
702 | "engines": {
703 | "node": ">=10"
704 | },
705 | "funding": {
706 | "url": "https://github.com/sponsors/sindresorhus"
707 | }
708 | },
709 | "node_modules/lodash.merge": {
710 | "version": "4.6.2",
711 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
712 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
713 | },
714 | "node_modules/minimatch": {
715 | "version": "3.1.2",
716 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
717 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
718 | "dependencies": {
719 | "brace-expansion": "^1.1.7"
720 | },
721 | "engines": {
722 | "node": "*"
723 | }
724 | },
725 | "node_modules/ms": {
726 | "version": "2.1.2",
727 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
728 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
729 | },
730 | "node_modules/natural-compare": {
731 | "version": "1.4.0",
732 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
733 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
734 | },
735 | "node_modules/once": {
736 | "version": "1.4.0",
737 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
738 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
739 | "dependencies": {
740 | "wrappy": "1"
741 | }
742 | },
743 | "node_modules/optionator": {
744 | "version": "0.9.3",
745 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
746 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
747 | "dependencies": {
748 | "@aashutoshrathi/word-wrap": "^1.2.3",
749 | "deep-is": "^0.1.3",
750 | "fast-levenshtein": "^2.0.6",
751 | "levn": "^0.4.1",
752 | "prelude-ls": "^1.2.1",
753 | "type-check": "^0.4.0"
754 | },
755 | "engines": {
756 | "node": ">= 0.8.0"
757 | }
758 | },
759 | "node_modules/p-limit": {
760 | "version": "3.1.0",
761 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
762 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
763 | "dependencies": {
764 | "yocto-queue": "^0.1.0"
765 | },
766 | "engines": {
767 | "node": ">=10"
768 | },
769 | "funding": {
770 | "url": "https://github.com/sponsors/sindresorhus"
771 | }
772 | },
773 | "node_modules/p-locate": {
774 | "version": "5.0.0",
775 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
776 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
777 | "dependencies": {
778 | "p-limit": "^3.0.2"
779 | },
780 | "engines": {
781 | "node": ">=10"
782 | },
783 | "funding": {
784 | "url": "https://github.com/sponsors/sindresorhus"
785 | }
786 | },
787 | "node_modules/parent-module": {
788 | "version": "1.0.1",
789 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
790 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
791 | "dependencies": {
792 | "callsites": "^3.0.0"
793 | },
794 | "engines": {
795 | "node": ">=6"
796 | }
797 | },
798 | "node_modules/path-exists": {
799 | "version": "4.0.0",
800 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
801 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
802 | "engines": {
803 | "node": ">=8"
804 | }
805 | },
806 | "node_modules/path-is-absolute": {
807 | "version": "1.0.1",
808 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
809 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
810 | "engines": {
811 | "node": ">=0.10.0"
812 | }
813 | },
814 | "node_modules/path-key": {
815 | "version": "3.1.1",
816 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
817 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
818 | "engines": {
819 | "node": ">=8"
820 | }
821 | },
822 | "node_modules/prelude-ls": {
823 | "version": "1.2.1",
824 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
825 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
826 | "engines": {
827 | "node": ">= 0.8.0"
828 | }
829 | },
830 | "node_modules/punycode": {
831 | "version": "2.3.1",
832 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
833 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
834 | "engines": {
835 | "node": ">=6"
836 | }
837 | },
838 | "node_modules/queue-microtask": {
839 | "version": "1.2.3",
840 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
841 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
842 | "funding": [
843 | {
844 | "type": "github",
845 | "url": "https://github.com/sponsors/feross"
846 | },
847 | {
848 | "type": "patreon",
849 | "url": "https://www.patreon.com/feross"
850 | },
851 | {
852 | "type": "consulting",
853 | "url": "https://feross.org/support"
854 | }
855 | ]
856 | },
857 | "node_modules/resolve-from": {
858 | "version": "4.0.0",
859 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
860 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
861 | "engines": {
862 | "node": ">=4"
863 | }
864 | },
865 | "node_modules/reusify": {
866 | "version": "1.0.4",
867 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
868 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
869 | "engines": {
870 | "iojs": ">=1.0.0",
871 | "node": ">=0.10.0"
872 | }
873 | },
874 | "node_modules/rimraf": {
875 | "version": "3.0.2",
876 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
877 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
878 | "dependencies": {
879 | "glob": "^7.1.3"
880 | },
881 | "bin": {
882 | "rimraf": "bin.js"
883 | },
884 | "funding": {
885 | "url": "https://github.com/sponsors/isaacs"
886 | }
887 | },
888 | "node_modules/run-parallel": {
889 | "version": "1.2.0",
890 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
891 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
892 | "funding": [
893 | {
894 | "type": "github",
895 | "url": "https://github.com/sponsors/feross"
896 | },
897 | {
898 | "type": "patreon",
899 | "url": "https://www.patreon.com/feross"
900 | },
901 | {
902 | "type": "consulting",
903 | "url": "https://feross.org/support"
904 | }
905 | ],
906 | "dependencies": {
907 | "queue-microtask": "^1.2.2"
908 | }
909 | },
910 | "node_modules/shebang-command": {
911 | "version": "2.0.0",
912 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
913 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
914 | "dependencies": {
915 | "shebang-regex": "^3.0.0"
916 | },
917 | "engines": {
918 | "node": ">=8"
919 | }
920 | },
921 | "node_modules/shebang-regex": {
922 | "version": "3.0.0",
923 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
924 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
925 | "engines": {
926 | "node": ">=8"
927 | }
928 | },
929 | "node_modules/strip-ansi": {
930 | "version": "6.0.1",
931 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
932 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
933 | "dependencies": {
934 | "ansi-regex": "^5.0.1"
935 | },
936 | "engines": {
937 | "node": ">=8"
938 | }
939 | },
940 | "node_modules/strip-json-comments": {
941 | "version": "3.1.1",
942 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
943 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
944 | "engines": {
945 | "node": ">=8"
946 | },
947 | "funding": {
948 | "url": "https://github.com/sponsors/sindresorhus"
949 | }
950 | },
951 | "node_modules/supports-color": {
952 | "version": "7.2.0",
953 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
954 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
955 | "dependencies": {
956 | "has-flag": "^4.0.0"
957 | },
958 | "engines": {
959 | "node": ">=8"
960 | }
961 | },
962 | "node_modules/text-table": {
963 | "version": "0.2.0",
964 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
965 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
966 | },
967 | "node_modules/type-check": {
968 | "version": "0.4.0",
969 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
970 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
971 | "dependencies": {
972 | "prelude-ls": "^1.2.1"
973 | },
974 | "engines": {
975 | "node": ">= 0.8.0"
976 | }
977 | },
978 | "node_modules/type-fest": {
979 | "version": "0.20.2",
980 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
981 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
982 | "engines": {
983 | "node": ">=10"
984 | },
985 | "funding": {
986 | "url": "https://github.com/sponsors/sindresorhus"
987 | }
988 | },
989 | "node_modules/uri-js": {
990 | "version": "4.4.1",
991 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
992 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
993 | "dependencies": {
994 | "punycode": "^2.1.0"
995 | }
996 | },
997 | "node_modules/which": {
998 | "version": "2.0.2",
999 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1000 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1001 | "dependencies": {
1002 | "isexe": "^2.0.0"
1003 | },
1004 | "bin": {
1005 | "node-which": "bin/node-which"
1006 | },
1007 | "engines": {
1008 | "node": ">= 8"
1009 | }
1010 | },
1011 | "node_modules/wrappy": {
1012 | "version": "1.0.2",
1013 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1014 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1015 | },
1016 | "node_modules/yocto-queue": {
1017 | "version": "0.1.0",
1018 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1019 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
1020 | "engines": {
1021 | "node": ">=10"
1022 | },
1023 | "funding": {
1024 | "url": "https://github.com/sponsors/sindresorhus"
1025 | }
1026 | }
1027 | },
1028 | "dependencies": {
1029 | "@aashutoshrathi/word-wrap": {
1030 | "version": "1.2.6",
1031 | "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz",
1032 | "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA=="
1033 | },
1034 | "@eslint-community/eslint-utils": {
1035 | "version": "4.4.0",
1036 | "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz",
1037 | "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==",
1038 | "requires": {
1039 | "eslint-visitor-keys": "^3.3.0"
1040 | }
1041 | },
1042 | "@eslint-community/regexpp": {
1043 | "version": "4.10.0",
1044 | "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz",
1045 | "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA=="
1046 | },
1047 | "@eslint/eslintrc": {
1048 | "version": "2.1.4",
1049 | "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz",
1050 | "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==",
1051 | "requires": {
1052 | "ajv": "^6.12.4",
1053 | "debug": "^4.3.2",
1054 | "espree": "^9.6.0",
1055 | "globals": "^13.19.0",
1056 | "ignore": "^5.2.0",
1057 | "import-fresh": "^3.2.1",
1058 | "js-yaml": "^4.1.0",
1059 | "minimatch": "^3.1.2",
1060 | "strip-json-comments": "^3.1.1"
1061 | }
1062 | },
1063 | "@eslint/js": {
1064 | "version": "8.56.0",
1065 | "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.56.0.tgz",
1066 | "integrity": "sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A=="
1067 | },
1068 | "@humanwhocodes/config-array": {
1069 | "version": "0.11.14",
1070 | "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz",
1071 | "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==",
1072 | "requires": {
1073 | "@humanwhocodes/object-schema": "^2.0.2",
1074 | "debug": "^4.3.1",
1075 | "minimatch": "^3.0.5"
1076 | }
1077 | },
1078 | "@humanwhocodes/module-importer": {
1079 | "version": "1.0.1",
1080 | "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
1081 | "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="
1082 | },
1083 | "@humanwhocodes/object-schema": {
1084 | "version": "2.0.2",
1085 | "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz",
1086 | "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw=="
1087 | },
1088 | "@nodelib/fs.scandir": {
1089 | "version": "2.1.5",
1090 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
1091 | "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
1092 | "requires": {
1093 | "@nodelib/fs.stat": "2.0.5",
1094 | "run-parallel": "^1.1.9"
1095 | }
1096 | },
1097 | "@nodelib/fs.stat": {
1098 | "version": "2.0.5",
1099 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
1100 | "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="
1101 | },
1102 | "@nodelib/fs.walk": {
1103 | "version": "1.2.8",
1104 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
1105 | "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
1106 | "requires": {
1107 | "@nodelib/fs.scandir": "2.1.5",
1108 | "fastq": "^1.6.0"
1109 | }
1110 | },
1111 | "@ungap/structured-clone": {
1112 | "version": "1.2.0",
1113 | "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
1114 | "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ=="
1115 | },
1116 | "acorn": {
1117 | "version": "8.11.3",
1118 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz",
1119 | "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg=="
1120 | },
1121 | "acorn-jsx": {
1122 | "version": "5.3.2",
1123 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
1124 | "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
1125 | "requires": {}
1126 | },
1127 | "ajv": {
1128 | "version": "6.12.6",
1129 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
1130 | "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
1131 | "requires": {
1132 | "fast-deep-equal": "^3.1.1",
1133 | "fast-json-stable-stringify": "^2.0.0",
1134 | "json-schema-traverse": "^0.4.1",
1135 | "uri-js": "^4.2.2"
1136 | }
1137 | },
1138 | "ansi-regex": {
1139 | "version": "5.0.1",
1140 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
1141 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
1142 | },
1143 | "ansi-styles": {
1144 | "version": "4.3.0",
1145 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1146 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1147 | "requires": {
1148 | "color-convert": "^2.0.1"
1149 | }
1150 | },
1151 | "argparse": {
1152 | "version": "2.0.1",
1153 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1154 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
1155 | },
1156 | "balanced-match": {
1157 | "version": "1.0.2",
1158 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1159 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
1160 | },
1161 | "brace-expansion": {
1162 | "version": "1.1.11",
1163 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1164 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1165 | "requires": {
1166 | "balanced-match": "^1.0.0",
1167 | "concat-map": "0.0.1"
1168 | }
1169 | },
1170 | "callsites": {
1171 | "version": "3.1.0",
1172 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
1173 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="
1174 | },
1175 | "chalk": {
1176 | "version": "4.1.2",
1177 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1178 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1179 | "requires": {
1180 | "ansi-styles": "^4.1.0",
1181 | "supports-color": "^7.1.0"
1182 | }
1183 | },
1184 | "color-convert": {
1185 | "version": "2.0.1",
1186 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1187 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1188 | "requires": {
1189 | "color-name": "~1.1.4"
1190 | }
1191 | },
1192 | "color-name": {
1193 | "version": "1.1.4",
1194 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1195 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
1196 | },
1197 | "concat-map": {
1198 | "version": "0.0.1",
1199 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1200 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
1201 | },
1202 | "cross-spawn": {
1203 | "version": "7.0.3",
1204 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
1205 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
1206 | "requires": {
1207 | "path-key": "^3.1.0",
1208 | "shebang-command": "^2.0.0",
1209 | "which": "^2.0.1"
1210 | }
1211 | },
1212 | "debug": {
1213 | "version": "4.3.4",
1214 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1215 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1216 | "requires": {
1217 | "ms": "2.1.2"
1218 | }
1219 | },
1220 | "deep-is": {
1221 | "version": "0.1.4",
1222 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
1223 | "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
1224 | },
1225 | "doctrine": {
1226 | "version": "3.0.0",
1227 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
1228 | "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
1229 | "requires": {
1230 | "esutils": "^2.0.2"
1231 | }
1232 | },
1233 | "escape-string-regexp": {
1234 | "version": "4.0.0",
1235 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1236 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="
1237 | },
1238 | "eslint": {
1239 | "version": "8.56.0",
1240 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.56.0.tgz",
1241 | "integrity": "sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==",
1242 | "requires": {
1243 | "@eslint-community/eslint-utils": "^4.2.0",
1244 | "@eslint-community/regexpp": "^4.6.1",
1245 | "@eslint/eslintrc": "^2.1.4",
1246 | "@eslint/js": "8.56.0",
1247 | "@humanwhocodes/config-array": "^0.11.13",
1248 | "@humanwhocodes/module-importer": "^1.0.1",
1249 | "@nodelib/fs.walk": "^1.2.8",
1250 | "@ungap/structured-clone": "^1.2.0",
1251 | "ajv": "^6.12.4",
1252 | "chalk": "^4.0.0",
1253 | "cross-spawn": "^7.0.2",
1254 | "debug": "^4.3.2",
1255 | "doctrine": "^3.0.0",
1256 | "escape-string-regexp": "^4.0.0",
1257 | "eslint-scope": "^7.2.2",
1258 | "eslint-visitor-keys": "^3.4.3",
1259 | "espree": "^9.6.1",
1260 | "esquery": "^1.4.2",
1261 | "esutils": "^2.0.2",
1262 | "fast-deep-equal": "^3.1.3",
1263 | "file-entry-cache": "^6.0.1",
1264 | "find-up": "^5.0.0",
1265 | "glob-parent": "^6.0.2",
1266 | "globals": "^13.19.0",
1267 | "graphemer": "^1.4.0",
1268 | "ignore": "^5.2.0",
1269 | "imurmurhash": "^0.1.4",
1270 | "is-glob": "^4.0.0",
1271 | "is-path-inside": "^3.0.3",
1272 | "js-yaml": "^4.1.0",
1273 | "json-stable-stringify-without-jsonify": "^1.0.1",
1274 | "levn": "^0.4.1",
1275 | "lodash.merge": "^4.6.2",
1276 | "minimatch": "^3.1.2",
1277 | "natural-compare": "^1.4.0",
1278 | "optionator": "^0.9.3",
1279 | "strip-ansi": "^6.0.1",
1280 | "text-table": "^0.2.0"
1281 | }
1282 | },
1283 | "eslint-scope": {
1284 | "version": "7.2.2",
1285 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz",
1286 | "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==",
1287 | "requires": {
1288 | "esrecurse": "^4.3.0",
1289 | "estraverse": "^5.2.0"
1290 | }
1291 | },
1292 | "eslint-visitor-keys": {
1293 | "version": "3.4.3",
1294 | "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
1295 | "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="
1296 | },
1297 | "espree": {
1298 | "version": "9.6.1",
1299 | "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz",
1300 | "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==",
1301 | "requires": {
1302 | "acorn": "^8.9.0",
1303 | "acorn-jsx": "^5.3.2",
1304 | "eslint-visitor-keys": "^3.4.1"
1305 | }
1306 | },
1307 | "esquery": {
1308 | "version": "1.5.0",
1309 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz",
1310 | "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==",
1311 | "requires": {
1312 | "estraverse": "^5.1.0"
1313 | }
1314 | },
1315 | "esrecurse": {
1316 | "version": "4.3.0",
1317 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
1318 | "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
1319 | "requires": {
1320 | "estraverse": "^5.2.0"
1321 | }
1322 | },
1323 | "estraverse": {
1324 | "version": "5.3.0",
1325 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
1326 | "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="
1327 | },
1328 | "esutils": {
1329 | "version": "2.0.3",
1330 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
1331 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
1332 | },
1333 | "fast-deep-equal": {
1334 | "version": "3.1.3",
1335 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
1336 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
1337 | },
1338 | "fast-json-stable-stringify": {
1339 | "version": "2.1.0",
1340 | "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
1341 | "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
1342 | },
1343 | "fast-levenshtein": {
1344 | "version": "2.0.6",
1345 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
1346 | "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
1347 | },
1348 | "fastq": {
1349 | "version": "1.16.0",
1350 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz",
1351 | "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==",
1352 | "requires": {
1353 | "reusify": "^1.0.4"
1354 | }
1355 | },
1356 | "file-entry-cache": {
1357 | "version": "6.0.1",
1358 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
1359 | "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
1360 | "requires": {
1361 | "flat-cache": "^3.0.4"
1362 | }
1363 | },
1364 | "find-up": {
1365 | "version": "5.0.0",
1366 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1367 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1368 | "requires": {
1369 | "locate-path": "^6.0.0",
1370 | "path-exists": "^4.0.0"
1371 | }
1372 | },
1373 | "flat-cache": {
1374 | "version": "3.0.4",
1375 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
1376 | "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
1377 | "requires": {
1378 | "flatted": "^3.1.0",
1379 | "rimraf": "^3.0.2"
1380 | }
1381 | },
1382 | "flatted": {
1383 | "version": "3.2.4",
1384 | "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.4.tgz",
1385 | "integrity": "sha512-8/sOawo8tJ4QOBX8YlQBMxL8+RLZfxMQOif9o0KUKTNTjMYElWPE0r/m5VNFxTRd0NSw8qSy8dajrwX4RYI1Hw=="
1386 | },
1387 | "fs.realpath": {
1388 | "version": "1.0.0",
1389 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1390 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
1391 | },
1392 | "glob": {
1393 | "version": "7.2.0",
1394 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
1395 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
1396 | "requires": {
1397 | "fs.realpath": "^1.0.0",
1398 | "inflight": "^1.0.4",
1399 | "inherits": "2",
1400 | "minimatch": "^3.0.4",
1401 | "once": "^1.3.0",
1402 | "path-is-absolute": "^1.0.0"
1403 | }
1404 | },
1405 | "glob-parent": {
1406 | "version": "6.0.2",
1407 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
1408 | "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
1409 | "requires": {
1410 | "is-glob": "^4.0.3"
1411 | }
1412 | },
1413 | "globals": {
1414 | "version": "13.24.0",
1415 | "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
1416 | "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
1417 | "requires": {
1418 | "type-fest": "^0.20.2"
1419 | }
1420 | },
1421 | "graphemer": {
1422 | "version": "1.4.0",
1423 | "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
1424 | "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="
1425 | },
1426 | "has-flag": {
1427 | "version": "4.0.0",
1428 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1429 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
1430 | },
1431 | "ignore": {
1432 | "version": "5.3.0",
1433 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
1434 | "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg=="
1435 | },
1436 | "import-fresh": {
1437 | "version": "3.3.0",
1438 | "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
1439 | "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
1440 | "requires": {
1441 | "parent-module": "^1.0.0",
1442 | "resolve-from": "^4.0.0"
1443 | }
1444 | },
1445 | "imurmurhash": {
1446 | "version": "0.1.4",
1447 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
1448 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o="
1449 | },
1450 | "inflight": {
1451 | "version": "1.0.6",
1452 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1453 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1454 | "requires": {
1455 | "once": "^1.3.0",
1456 | "wrappy": "1"
1457 | }
1458 | },
1459 | "inherits": {
1460 | "version": "2.0.4",
1461 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1462 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
1463 | },
1464 | "is-extglob": {
1465 | "version": "2.1.1",
1466 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1467 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
1468 | },
1469 | "is-glob": {
1470 | "version": "4.0.3",
1471 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1472 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1473 | "requires": {
1474 | "is-extglob": "^2.1.1"
1475 | }
1476 | },
1477 | "is-path-inside": {
1478 | "version": "3.0.3",
1479 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz",
1480 | "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="
1481 | },
1482 | "isexe": {
1483 | "version": "2.0.0",
1484 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
1485 | "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
1486 | },
1487 | "js-yaml": {
1488 | "version": "4.1.0",
1489 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1490 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1491 | "requires": {
1492 | "argparse": "^2.0.1"
1493 | }
1494 | },
1495 | "json-schema-traverse": {
1496 | "version": "0.4.1",
1497 | "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
1498 | "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
1499 | },
1500 | "json-stable-stringify-without-jsonify": {
1501 | "version": "1.0.1",
1502 | "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
1503 | "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE="
1504 | },
1505 | "levn": {
1506 | "version": "0.4.1",
1507 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
1508 | "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
1509 | "requires": {
1510 | "prelude-ls": "^1.2.1",
1511 | "type-check": "~0.4.0"
1512 | }
1513 | },
1514 | "locate-path": {
1515 | "version": "6.0.0",
1516 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
1517 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
1518 | "requires": {
1519 | "p-locate": "^5.0.0"
1520 | }
1521 | },
1522 | "lodash.merge": {
1523 | "version": "4.6.2",
1524 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
1525 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
1526 | },
1527 | "minimatch": {
1528 | "version": "3.1.2",
1529 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1530 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1531 | "requires": {
1532 | "brace-expansion": "^1.1.7"
1533 | }
1534 | },
1535 | "ms": {
1536 | "version": "2.1.2",
1537 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1538 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
1539 | },
1540 | "natural-compare": {
1541 | "version": "1.4.0",
1542 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
1543 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc="
1544 | },
1545 | "once": {
1546 | "version": "1.4.0",
1547 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1548 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1549 | "requires": {
1550 | "wrappy": "1"
1551 | }
1552 | },
1553 | "optionator": {
1554 | "version": "0.9.3",
1555 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz",
1556 | "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==",
1557 | "requires": {
1558 | "@aashutoshrathi/word-wrap": "^1.2.3",
1559 | "deep-is": "^0.1.3",
1560 | "fast-levenshtein": "^2.0.6",
1561 | "levn": "^0.4.1",
1562 | "prelude-ls": "^1.2.1",
1563 | "type-check": "^0.4.0"
1564 | }
1565 | },
1566 | "p-limit": {
1567 | "version": "3.1.0",
1568 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
1569 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
1570 | "requires": {
1571 | "yocto-queue": "^0.1.0"
1572 | }
1573 | },
1574 | "p-locate": {
1575 | "version": "5.0.0",
1576 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
1577 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
1578 | "requires": {
1579 | "p-limit": "^3.0.2"
1580 | }
1581 | },
1582 | "parent-module": {
1583 | "version": "1.0.1",
1584 | "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
1585 | "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
1586 | "requires": {
1587 | "callsites": "^3.0.0"
1588 | }
1589 | },
1590 | "path-exists": {
1591 | "version": "4.0.0",
1592 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1593 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
1594 | },
1595 | "path-is-absolute": {
1596 | "version": "1.0.1",
1597 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1598 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
1599 | },
1600 | "path-key": {
1601 | "version": "3.1.1",
1602 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
1603 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="
1604 | },
1605 | "prelude-ls": {
1606 | "version": "1.2.1",
1607 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
1608 | "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="
1609 | },
1610 | "punycode": {
1611 | "version": "2.3.1",
1612 | "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
1613 | "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="
1614 | },
1615 | "queue-microtask": {
1616 | "version": "1.2.3",
1617 | "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
1618 | "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="
1619 | },
1620 | "resolve-from": {
1621 | "version": "4.0.0",
1622 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
1623 | "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g=="
1624 | },
1625 | "reusify": {
1626 | "version": "1.0.4",
1627 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
1628 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw=="
1629 | },
1630 | "rimraf": {
1631 | "version": "3.0.2",
1632 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
1633 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
1634 | "requires": {
1635 | "glob": "^7.1.3"
1636 | }
1637 | },
1638 | "run-parallel": {
1639 | "version": "1.2.0",
1640 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
1641 | "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
1642 | "requires": {
1643 | "queue-microtask": "^1.2.2"
1644 | }
1645 | },
1646 | "shebang-command": {
1647 | "version": "2.0.0",
1648 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
1649 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
1650 | "requires": {
1651 | "shebang-regex": "^3.0.0"
1652 | }
1653 | },
1654 | "shebang-regex": {
1655 | "version": "3.0.0",
1656 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
1657 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="
1658 | },
1659 | "strip-ansi": {
1660 | "version": "6.0.1",
1661 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1662 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1663 | "requires": {
1664 | "ansi-regex": "^5.0.1"
1665 | }
1666 | },
1667 | "strip-json-comments": {
1668 | "version": "3.1.1",
1669 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
1670 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="
1671 | },
1672 | "supports-color": {
1673 | "version": "7.2.0",
1674 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1675 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1676 | "requires": {
1677 | "has-flag": "^4.0.0"
1678 | }
1679 | },
1680 | "text-table": {
1681 | "version": "0.2.0",
1682 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
1683 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ="
1684 | },
1685 | "type-check": {
1686 | "version": "0.4.0",
1687 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
1688 | "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
1689 | "requires": {
1690 | "prelude-ls": "^1.2.1"
1691 | }
1692 | },
1693 | "type-fest": {
1694 | "version": "0.20.2",
1695 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
1696 | "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="
1697 | },
1698 | "uri-js": {
1699 | "version": "4.4.1",
1700 | "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
1701 | "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
1702 | "requires": {
1703 | "punycode": "^2.1.0"
1704 | }
1705 | },
1706 | "which": {
1707 | "version": "2.0.2",
1708 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
1709 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
1710 | "requires": {
1711 | "isexe": "^2.0.0"
1712 | }
1713 | },
1714 | "wrappy": {
1715 | "version": "1.0.2",
1716 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1717 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
1718 | },
1719 | "yocto-queue": {
1720 | "version": "0.1.0",
1721 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1722 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
1723 | }
1724 | }
1725 | }
1726 |
--------------------------------------------------------------------------------
/packages/check-es-compat/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "check-es-compat",
3 | "version": "3.2.1",
4 | "description": "CLI tool for checking JavaScript code compatibility with target browsers and Node.js versions",
5 | "keywords": [
6 | "browser",
7 | "compatibility",
8 | "compat",
9 | "support",
10 | "javascript",
11 | "ecmascript",
12 | "es",
13 | "checker",
14 | "browserslist",
15 | "browser-compat-data",
16 | "caniuse",
17 | "kangax"
18 | ],
19 | "homepage": "https://github.com/robatwilliams/es-compat#readme",
20 | "bugs": {
21 | "url": "https://github.com/robatwilliams/es-compat/issues"
22 | },
23 | "repository": {
24 | "type": "git",
25 | "url": "https://github.com/robatwilliams/es-compat.git"
26 | },
27 | "license": "MIT",
28 | "author": "Robat Williams",
29 | "type": "module",
30 | "bin": {
31 | "check-es-compat": "bin/cli.js"
32 | },
33 | "dependencies": {
34 | "eslint": "^8.56.0",
35 | "eslint-plugin-ecmascript-compat": "^3.2.1"
36 | },
37 | "engines": {
38 | "node": ">=16.0.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat-example/.browserslistrc:
--------------------------------------------------------------------------------
1 | #
2 | # Docs: https://github.com/browserslist/browserslist
3 | #
4 |
5 | # Supports no ES2016 features
6 | Chrome >= 46
7 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat-example/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "plugins": ["ecmascript-compat"],
4 | "parserOptions": {
5 | "ecmaVersion": 2023,
6 | "sourceType": "module"
7 | },
8 | "env": { "es2021": true },
9 | "rules": {
10 | "ecmascript-compat/compat": "error"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat-example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-plugin-ecmascript-compat-example",
3 | "private": true,
4 | "scripts": {
5 | "lint": "eslint src/"
6 | },
7 | "devDependencies": {
8 | "eslint": "^8.56.0",
9 | "eslint-plugin-ecmascript-compat": "^3.2.1"
10 | },
11 | "version": "3.2.1"
12 | }
13 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat-example/src/app.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ES2023
3 | */
4 | [].findLast('a');
5 | [].toReversed();
6 | [].toSorted();
7 | [].toSpliced(1);
8 | [].with(1, 'a');
9 |
10 | /**
11 | * ES2022
12 | */
13 | [].at(1);
14 | 'Foo'.at(1);
15 |
16 | class A {
17 | a = 0;
18 | }
19 |
20 | class B {
21 | static {}
22 | }
23 |
24 | Object.hasOwn({}, 'prop');
25 |
26 | class C {
27 | #field;
28 | foo() {
29 | #field in this;
30 | }
31 | }
32 |
33 | new Error('message', { cause: new Error('originalError') });
34 |
35 | /./d.test('d flag');
36 |
37 | /**
38 | * ES2021
39 | */
40 | foo = {};
41 | foo.replaceAll; // no error
42 |
43 | String.prototype.replaceAll;
44 |
45 | foo = foo &&= null;
46 | foo = foo ??= '';
47 | foo = foo ||= {};
48 |
49 | Promise.any();
50 |
51 | foo = 1_000_000_00;
52 | foo = new WeakRef();
53 | foo = new FinalizationRegistry(() => {});
54 |
55 | /**
56 | * ES2020 (all implemented, but these examples not complete)
57 | */
58 | foo = 100n;
59 | BigInt(100);
60 |
61 | async function interestingBitIsInside2() {
62 | await import('');
63 | }
64 |
65 | globalThis.foo;
66 |
67 | Promise.allSettled();
68 |
69 | foo.matchAll();
70 | String.prototype.matchAll;
71 |
72 | /**
73 | * ES2019
74 | */
75 | foo.flat();
76 | Array.prototype.flat;
77 | residentialAddress.flat; // no error please
78 | Array.prototype.flatMap;
79 | foo.flatMap();
80 |
81 | const u2028 = '
'; // line separator character \u2028 is in this string
82 |
83 | Object.fromEntries();
84 |
85 | try {
86 | } catch {}
87 |
88 | foo.trimLeft();
89 | String.prototype.trimLeft;
90 | foo.trimRight();
91 | String.prototype.trimRight;
92 | foo.trimStart();
93 | String.prototype.trimStart;
94 | foo.trimEnd();
95 | String.prototype.trimEnd;
96 |
97 | /**
98 | * ES2018
99 | */
100 | async function* asyncGenerator() {}
101 | async function interestingBitIsInside1() {
102 | for await (const bar of bar) {
103 | }
104 | }
105 |
106 | foo = { ...bar };
107 | const { a, ...rest } = foo;
108 |
109 | foo.finally();
110 | Promise.prototype.finally;
111 |
112 | /(?<=a)b/.test('look-behind assertion');
113 |
114 | /(?b)c/.test('named capture group');
115 |
116 | /./s.test('dotAll flag');
117 |
118 | /\p{Script=Hiragana}+/u.test('Unicode property escape');
119 |
120 | /**
121 | * ES2017
122 | */
123 | async function foo() {}
124 |
125 | Atomics.add(buffer, 0, 2);
126 |
127 | Object.getOwnPropertyDescriptors();
128 |
129 | Object.entries();
130 |
131 | Object.values();
132 |
133 | new SharedArrayBuffer();
134 |
135 | str.padStart();
136 | String.prototype.padStart;
137 | str.padEnd();
138 | String.prototype.padEnd;
139 |
140 | // prettier-ignore
141 | foo(bar,);
142 |
143 | /**
144 | * ES2016
145 | */
146 | foo.includes();
147 | Array.prototype.includes;
148 |
149 | foo ** bar;
150 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/.gitignore:
--------------------------------------------------------------------------------
1 | /coverage
2 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/README.md:
--------------------------------------------------------------------------------
1 |
2 | [](https://badge.fury.io/js/eslint-plugin-ecmascript-compat)
3 | [](http://www.npmtrends.com/eslint-plugin-ecmascript-compat)
4 |
5 |
6 | # eslint-plugin-ecmascript-compat
7 |
8 | > ESLint plugin for checking JavaScript code compatibility with target browsers and Node.js versions
9 |
10 | ```bash
11 | npm install --save-dev eslint-plugin-ecmascript-compat
12 | ```
13 |
14 | ```json
15 | // .eslintrc.json
16 | {
17 | "extends": ["plugin:ecmascript-compat/recommended"]
18 | }
19 |
20 | // Alternatively
21 | {
22 | "plugins": ["ecmascript-compat"],
23 | "rules": {
24 | "ecmascript-compat/compat": [
25 | "error",
26 | {
27 | // Optionally, specify provided polyfills
28 | "polyfills": [
29 | "Array.prototype.includes"
30 | ],
31 | // Optionally, provide a browserslist to use instead of the project one
32 | "overrideBrowserslist": "IE >= 11",
33 | // Optionally, specify browserslist options - see https://github.com/browserslist/browserslist#js-api
34 | "browserslistOptions": { "env": "legacy" }
35 | }
36 | ]
37 | }
38 | }
39 | ```
40 |
41 | ```
42 | // .browserslistrc
43 | Chrome >= 64
44 | Firefox >= 58
45 | ```
46 |
47 |
48 |
49 | The optional `polyfills` option is used to specify polyfills that your application loads. These features are therefore considered supported in all browsers. Features that are polyfillable and can be specified here can be found in the [rule schema](https://github.com/robatwilliams/es-compat/blob/master/packages/eslint-plugin-ecmascript-compat/lib/rule.js).
50 |
51 | For example usage, see sibling directory: `eslint-plugin-ecmascript-compat-example`
52 |
53 |
54 |
55 | ➡ For more information, see the [main readme](https://github.com/robatwilliams/es-compat#readme).
56 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/compareVersions.js:
--------------------------------------------------------------------------------
1 | export default function compareVersions(a, b) {
2 | const aParts = a.split('.').map(Number);
3 | const bParts = b.split('.').map(Number);
4 |
5 | for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
6 | if (aParts[i] === bParts[i]) {
7 | // eslint-disable-next-line no-continue
8 | continue;
9 | }
10 |
11 | return aParts[i] < bParts[i] ? -1 : 1;
12 | }
13 |
14 | return 0;
15 | }
16 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/compareVersions.test.js:
--------------------------------------------------------------------------------
1 | import assert from 'node:assert';
2 | import { test } from 'node:test';
3 | import compareVersions from './compareVersions.js';
4 |
5 | test('equal', () => {
6 | assert.strictEqual(compareVersions('1.2.3', '1.2.3'), 0);
7 | });
8 |
9 | test('smaller', () => {
10 | assert.strictEqual(compareVersions('1.2.0', '1.2.3'), -1);
11 | assert.strictEqual(compareVersions('1.2', '1.3'), -1);
12 | });
13 |
14 | test('larger', () => {
15 | assert.strictEqual(compareVersions('1.2.3', '1.2.0'), 1);
16 | });
17 |
18 | test('partial on one side', () => {
19 | assert.strictEqual(compareVersions('1.1', '1.2.3'), -1);
20 | assert.strictEqual(compareVersions('1.1.1', '1.2'), -1);
21 | });
22 |
23 | test('when it matters to treat parts as numbers', () => {
24 | assert.strictEqual(compareVersions('9', '10'), -1);
25 | });
26 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/compatibility.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable camelcase, no-underscore-dangle */
2 | import compareVersions from './compareVersions.js';
3 |
4 | export function unsupportedFeatures(features, targets) {
5 | return features.filter((feature) => !isFeatureSupportedByTargets(feature, targets));
6 | }
7 |
8 | function isFeatureSupportedByTargets(feature, targets) {
9 | return targets.every((target) => isFeatureSupportedByTarget(feature, target));
10 | }
11 |
12 | function isFeatureSupportedByTarget(feature, target) {
13 | if (feature.compatFeatures.includes(undefined)) {
14 | const summary = feature.compatFeatures.map((compatFeature) => typeof compatFeature);
15 | const ruleDescription = feature.ruleConfig.definition.meta.docs.description;
16 |
17 | throw new Error(`Sparse compatFeatures for rule '${ruleDescription}': ${summary}`);
18 | }
19 |
20 | return feature.compatFeatures.every((compatFeature) =>
21 | isCompatFeatureSupportedByTarget(compatFeature, target)
22 | );
23 | }
24 |
25 | function isCompatFeatureSupportedByTarget(compatFeature, target) {
26 | const versionAdded = getSimpleSupportStatement(compatFeature, target).version_added;
27 | const support = interpretSupport(versionAdded);
28 |
29 | if (support.isUnknown || support.isVersionUnknown) {
30 | // Assume optimistically; we can only be as good as the compatibility data
31 | return true;
32 | }
33 |
34 | return !support.isNone && compareVersions(target.version, versionAdded) >= 0;
35 | }
36 |
37 | function getSimpleSupportStatement(compatFeature, target) {
38 | const statement = compatFeature.__compat.support[target.name];
39 |
40 | // Take the most relevant and general entry when there are ones for behind-a-flag etc.
41 | // https://github.com/mdn/browser-compat-data/blob/master/schemas/compat-data-schema.md#the-support_statement-object
42 | const simpleStatement = Array.isArray(statement) ? statement[0] : statement;
43 |
44 | // Only mandatory for desktop browsers
45 | // https://github.com/mdn/browser-compat-data/blob/master/schemas/compat-data-schema.md#browser-identifiers
46 | return simpleStatement || { version_added: null };
47 | }
48 |
49 | function interpretSupport(versionAdded) {
50 | // https://github.com/mdn/browser-compat-data/blob/master/schemas/compat-data-schema.md#version_added
51 | return {
52 | isUnknown: versionAdded == null,
53 | isNone: versionAdded === false,
54 | isVersionUnknown: versionAdded === true,
55 | };
56 | }
57 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/compatibility.test.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable camelcase */
2 | import assert from 'node:assert';
3 | import { it } from 'node:test';
4 | import { unsupportedFeatures } from './compatibility.js';
5 | import features from './features/index.js';
6 |
7 | it('supports feature in version introduced', () => {
8 | const feature = {
9 | compatFeatures: [
10 | {
11 | __compat: {
12 | support: {
13 | chrome: { version_added: '73' },
14 | },
15 | },
16 | },
17 | ],
18 | };
19 |
20 | const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
21 | assert.deepStrictEqual(unsupported, []);
22 | });
23 |
24 | it('supports feature in version later than introduced, treating versions as numbers', () => {
25 | const feature = {
26 | compatFeatures: [
27 | {
28 | __compat: {
29 | support: {
30 | safari: { version_added: '9' },
31 | },
32 | },
33 | },
34 | ],
35 | };
36 |
37 | const unsupported = unsupportedFeatures(
38 | [feature],
39 | [{ name: 'safari', version: '14.0' }]
40 | );
41 | assert.deepStrictEqual(unsupported, []);
42 | });
43 |
44 | it('doesnt support feature in version before introduced', () => {
45 | const feature = {
46 | compatFeatures: [
47 | {
48 | __compat: {
49 | support: {
50 | chrome: { version_added: '73' },
51 | },
52 | },
53 | },
54 | ],
55 | };
56 |
57 | const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '72' }]);
58 | assert.strictEqual(unsupported[0], feature);
59 | });
60 |
61 | it('supports feature supported by family in unknown version', () => {
62 | const feature = {
63 | compatFeatures: [
64 | {
65 | __compat: {
66 | support: {
67 | chrome: { version_added: true },
68 | },
69 | },
70 | },
71 | ],
72 | };
73 |
74 | const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
75 | assert.deepStrictEqual(unsupported, []);
76 | });
77 |
78 | it('doesnt support feature not supported in any version of family', () => {
79 | const feature = {
80 | compatFeatures: [
81 | {
82 | __compat: {
83 | support: {
84 | chrome: { version_added: false },
85 | },
86 | },
87 | },
88 | ],
89 | };
90 |
91 | const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
92 | assert.strictEqual(unsupported[0], feature);
93 | });
94 |
95 | it('supports feature with unknown support by family', () => {
96 | const feature = {
97 | compatFeatures: [
98 | {
99 | __compat: {
100 | support: {
101 | chrome: { version_added: null },
102 | },
103 | },
104 | },
105 | ],
106 | };
107 |
108 | const unsupported = unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]);
109 | assert.deepStrictEqual(unsupported, []);
110 | });
111 |
112 | it('supports feature with omitted support entry for mobile target', () => {
113 | const feature = {
114 | compatFeatures: [
115 | {
116 | __compat: {
117 | support: {
118 | chrome: { version_added: '73' },
119 | },
120 | },
121 | },
122 | ],
123 | };
124 |
125 | const unsupported = unsupportedFeatures(
126 | [feature],
127 | [{ name: 'chrome_android', version: '73' }]
128 | );
129 | assert.deepStrictEqual(unsupported, []);
130 | });
131 |
132 | it('doesnt support feature supported by one target but not another', () => {
133 | const feature = {
134 | compatFeatures: [
135 | {
136 | __compat: {
137 | support: {
138 | chrome: { version_added: '60' },
139 | firefox: { version_added: '55' },
140 | },
141 | },
142 | },
143 | ],
144 | };
145 |
146 | const unsupported = unsupportedFeatures(
147 | [feature],
148 | [
149 | { name: 'chrome', version: '73' },
150 | { name: 'firefox', version: '50' },
151 | ]
152 | );
153 | assert.strictEqual(unsupported[0], feature);
154 | });
155 |
156 | it('uses primary support record where multiple ones exist', () => {
157 | const feature = {
158 | compatFeatures: [
159 | {
160 | __compat: {
161 | support: {
162 | nodejs: [
163 | { version_added: '7.0.0' },
164 | {
165 | version_added: '6.5.0',
166 | flags: [
167 | {
168 | type: 'runtime_flag',
169 | name: '--harmony',
170 | },
171 | ],
172 | },
173 | ],
174 | },
175 | },
176 | },
177 | ],
178 | };
179 |
180 | const primaryUnsupported = unsupportedFeatures(
181 | [feature],
182 | [{ name: 'nodejs', version: '7.0.0' }]
183 | );
184 | assert.deepStrictEqual(primaryUnsupported, []);
185 |
186 | const secondaryUnsupported = unsupportedFeatures(
187 | [feature],
188 | [{ name: 'nodejs', version: '6.7.0' }]
189 | );
190 | assert.deepStrictEqual(secondaryUnsupported[0], feature);
191 | });
192 |
193 | it('explains what the problem is when compat feature not found in MDN data', () => {
194 | const feature = {
195 | ruleConfig: {
196 | definition: {
197 | meta: {
198 | docs: { description: 'some rule' },
199 | },
200 | },
201 | },
202 | compatFeatures: [
203 | // Unsupported compatFeature first, to test that validation does not short-circuit
204 | {
205 | __compat: {
206 | support: {
207 | chrome: { version_added: '72' },
208 | },
209 | },
210 | },
211 | // Typically when wrong path to compatData node used
212 | undefined,
213 | ],
214 | };
215 |
216 | assert.throws(
217 | () => unsupportedFeatures([feature], [{ name: 'chrome', version: '73' }]),
218 | { message: "Sparse compatFeatures for rule 'some rule': object,undefined" }
219 | );
220 | });
221 |
222 | it('can rely on all the versions in the compatibility data used being semver or partial semver', () => {
223 | // We rely on this to avoid having to deal with ranged versions, for simplicity.
224 | // https://github.com/mdn/browser-compat-data/blob/main/schemas/compat-data-schema.md#ranged-versions
225 |
226 | for (const esFeature of features) {
227 | for (const compatFeature of esFeature.compatFeatures) {
228 | // eslint-disable-next-line no-underscore-dangle
229 | for (const supportStatement of Object.values(compatFeature.__compat.support)) {
230 | const simpleSupportStatement = Array.isArray(supportStatement)
231 | ? supportStatement[0]
232 | : supportStatement;
233 |
234 | if (simpleSupportStatement.version_added !== false) {
235 | assert.match(
236 | simpleSupportStatement.version_added,
237 | /\d+(?\.\d+(?\.\d+)?)?/u
238 | );
239 | }
240 | }
241 | }
242 | }
243 | });
244 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/delegation.js:
--------------------------------------------------------------------------------
1 | export function createDelegatee(config, rootContext) {
2 | const { definition, options } = config;
3 |
4 | if (!definition) {
5 | // May need to update the es-x dependency, or check that the lookup name is not
6 | // prefixed with es-x/
7 | throw new Error('Rule instance not given');
8 | }
9 |
10 | // All except report() are added later. Define necessary ones for used rules.
11 | // https://eslint.org/docs/latest/extend/custom-rules#the-context-object
12 | const contextLaterAdded = {
13 | getScope: () => rootContext.getScope(),
14 | getSourceCode: () => rootContext.getSourceCode(),
15 |
16 | get settings() {
17 | return rootContext.settings;
18 | },
19 |
20 | get parserServices() {
21 | return rootContext.parserServices;
22 | },
23 | };
24 |
25 | // Would use ES Proxy, but context's properties aren't overridable
26 | const context = {
27 | ...rootContext,
28 | ...contextLaterAdded,
29 | options,
30 | report,
31 | };
32 |
33 | function report(params) {
34 | // Discard fixer; we can't declare the rule as fixable because not all delegatees are.
35 | // Look up messageId on delegate meta; report() would look it up on root rule meta.
36 | const { fix, message, messageId, ...otherParams } = params;
37 |
38 | rootContext.report({
39 | ...otherParams,
40 | message: messageId ? definition.meta.messages[messageId] : message,
41 | });
42 | }
43 |
44 | return definition.create(context);
45 | }
46 |
47 | export function delegatingVisitor(delegatees) {
48 | const delegator = {};
49 |
50 | delegatees.forEach((visitor) => {
51 | for (const [key] of Object.entries(visitor)) {
52 | delegator[key] = (...args) => delegate(key, args);
53 | }
54 | });
55 |
56 | function delegate(key, args) {
57 | delegatees.forEach((visitor) => {
58 | if (visitor[key]) {
59 | visitor[key](...args);
60 | }
61 | });
62 | }
63 |
64 | return delegator;
65 | }
66 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/delegation.test.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import { createDelegatee, delegatingVisitor } from './delegation.js';
3 |
4 | const ruleTester = new eslint.RuleTester();
5 |
6 | const noVarRule = new eslint.Linter().getRules().get('no-var');
7 |
8 | const rule = {
9 | create(context) {
10 | return delegatingVisitor([
11 | createDelegatee({ definition: noVarRule }, context),
12 | createDelegatee({ definition: noVarRule }, context),
13 | ]);
14 | },
15 | };
16 |
17 | ruleTester.run('allows delegatees to independently use the same AST selectors', rule, {
18 | valid: [],
19 | invalid: [
20 | {
21 | code: 'var foo;',
22 | errors: [
23 | { message: 'Unexpected var, use let or const instead.' },
24 | { message: 'Unexpected var, use let or const instead.' },
25 | ],
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es-versions.md:
--------------------------------------------------------------------------------
1 | # ECMAScript features by version
2 |
3 | Static detectability of recently-added features
4 |
5 | - ❌ = not statically detectable
6 | - 😐 = statically detectable, but chance of false positives
7 | - 👎 = statically detectable, but not worth the false positives
8 |
9 | ### ES2023
10 |
11 | | Name | ESLint / eslint-plugin-es | Chrome since |
12 | | --- | --- | --- |
13 | | `{Array, TypedArray}.prototype.{findLast, findLastIndex}` | 😐 es-x/no-array-prototype-findlast-findlastindex | 97 |
14 | | `{Array, TypedArray}.prototype.toReversed` | 😐 es-x/no-array-prototype-toreversed | 110 |
15 | | `{Array, TypedArray}.prototype.toSorted` | 😐 es-x/no-array-prototype-tosorted | 110 |
16 | | `Array.prototype.toSpliced` | 😐 es-x/no-array-prototype-tospliced | 110 |
17 | | `{Array, TypedArray}.prototype.with` | 😐 es-x/no-array-prototype-with | 110 |
18 | | Hashbang Grammar | es-x/no-hashbang | 74 |
19 | | Symbols as WeakMap keys | ❌ | 108 |
20 | | RegExp Unicode property escapes (2023) | es-x/no-regexp-unicode-property-escapes-2023 | see issue #63 |
21 |
22 | ### ES2022
23 |
24 | | Name | ESLint / eslint-plugin-es | Chrome since |
25 | | -------------------------------------------- | -------------------------------------------- | ------------- |
26 | | Arbitrary module namespace names | es-x/no-arbitrary-module-namespace-names | see issue #62 |
27 | | `{Array, String, TypedArray}.prototype.at()` | 😐 es-x/no-array-string-prototype-at | 92 |
28 | | Class fields | es-x/no-class-fields | 72, 74 |
29 | | Class static initialization block | es-x/no-class-static-block | 94 |
30 | | Error `cause` | es-x/no-error-cause | 93 |
31 | | `Object.hasOwn` | es-x/no-object-hasown | 93 |
32 | | Private slot checks (`#x in obj`) | es-x/no-private-in | 91 |
33 | | RegExp match indices (`/d` flag) | es-x/no-regexp-d-flag | 90 |
34 | | RegExp Unicode property escapes (2022) | es-x/no-regexp-unicode-property-escapes-2022 | see issue #63 |
35 | | Top-level `await` | es-x/no-top-level-await | 89 |
36 |
37 | ### ES2021
38 |
39 | | Name | ESLint / eslint-plugin-es | Chrome since |
40 | | -------------------------------------- | -------------------------------------------- | ------------- |
41 | | Logical Assignment \|\|=, \&\&=, ??= | es/no-logical-assignment-operators | 85 |
42 | | Numeric separators | es/no-numeric-separators | 75 |
43 | | `Promise.any` | es/no-promise-any | 85 |
44 | | RegExp Unicode property escapes (2021) | es-x/no-regexp-unicode-property-escapes-2021 | see issue #63 |
45 | | `String.prototype.replaceAll` | 😐 no-restricted-properties | 85 |
46 | | `WeakRef` and `FinalizationRegistry` | es/no-weakrefs | 84 |
47 |
48 | ### ES2020
49 |
50 | | Name | ESLint / eslint-plugin-es | Chrome since |
51 | | -------------------------------------- | -------------------------------------------- | ------------- |
52 | | `Atomics.{notify, wait}` | no-restricted-properties | 68 |
53 | | `BigInt` | es/no-bigint | 67 |
54 | | Dynamic `import()` | es/no-dynamic-import | 63 |
55 | | `globalThis` | es/no-global-this | 71 |
56 | | `import.meta` | es/no-import-meta | 64 |
57 | | Module namespace exports | es/no-export-ns-from | 72 |
58 | | Nullish coalescing (`??`) | es/no-nullish-coalescing-operators | 80 |
59 | | Optional chaining (`?.`) | es/no-optional-chaining | 80 |
60 | | `Promise.allSettled` | es/no-promise-all-settled | 76 |
61 | | RegExp Unicode property escapes (2020) | es-x/no-regexp-unicode-property-escapes-2020 | see issue #63 |
62 | | `String.prototype.matchAll` | 😐 no-restricted-syntax | 73 |
63 |
64 | ### ES2019
65 |
66 | | Name | ESLint / eslint-plugin-es | Chrome since |
67 | | -------------------------------------- | -------------------------------------------- | ------------- |
68 | | `Array.prototype.{flat, flatMap}` | 😐 no-restricted-syntax | 69 |
69 | | JSON superset | es/no-json-superset | 66 |
70 | | `Object.fromEntries` | es/no-object-fromentries | 73 |
71 | | Optional `catch` binding | es/no-optional-catch-binding | 66 |
72 | | RegExp Unicode property escapes (2019) | es-x/no-regexp-unicode-property-escapes-2019 | see issue #63 |
73 | | Revised `Function.prototype.toString` | ❌ |
74 | | Stable `Array.prototype.sort` | ❌ |
75 | | `String.prototype.trimX` methods | 😐 no-restricted-syntax | 66 |
76 | | `Symbol.prototype.description` | 👎 no-restricted-syntax | 70 |
77 | | Well-formed `JSON.stringify` | ❌ |
78 |
79 | ### ES2018
80 |
81 | | Name | ESLint / eslint-plugin-es | Chrome since |
82 | | -------------------------------------- | ------------------------------------- | ------------ |
83 | | Async iteration (loop & generators) | es/no-async-iteration | 63 |
84 | | Object rest and spread operators | es/no-rest-spread-properties | 60 |
85 | | `Promise.prototype.finally` | 😐 no-restricted-syntax | 63 |
86 | | RegExp look-behind assertions | es/no-regexp-lookbehind-assertions | 62 |
87 | | RegExp named capture groups | es/no-regexp-named-capture-groups | 64 |
88 | | RegExp `/s` (dotAll) flag | es/no-regexp-s-flag | 62 |
89 | | RegExp Unicode property escapes (2018) | es/no-regexp-unicode-property-escapes | 64 |
90 |
91 | ### ES2017
92 |
93 | | Name | ESLint / eslint-plugin-es | Chrome since |
94 | | ------------------------------------- | -------------------------------------- | ------------ |
95 | | Async functions | es/no-async-functions | 55 |
96 | | Atomics | es/no-atomics | 68 |
97 | | `Object.entries` | es/no-object-entries | 54 |
98 | | `Object.getOwnPropertyDescriptors` | es/no-object-getownpropertydescriptors | 54 |
99 | | `Object.values` | es/no-object-values | 54 |
100 | | SharedArrayBuffer | es/no-shared-array-buffer | 68 |
101 | | `String.prototype.{padStart, padEnd}` | 😐 no-restricted-syntax | 57 |
102 | | Trailing commas in parameter lists | es/no-trailing-function-commas | 58 |
103 |
104 | ### ES2016
105 |
106 | | Name | ESLint / eslint-plugin-es | Chrome since |
107 | | -------------------------- | --------------------------- | ------------ |
108 | | `Array.prototype.includes` | 😐 no-restricted-syntax | 47 |
109 | | Exponentiation operator | es/no-exponential-operators | 52 |
110 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2016.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import esPlugin from 'eslint-plugin-es-x';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: {
12 | definition: coreRules.get('no-restricted-syntax'),
13 | options: noRestrictedSyntaxPrototypeMethod('Array.prototype.includes', 'ES2016'),
14 | },
15 | compatFeatures: [compatData.javascript.builtins.Array.includes],
16 | polyfill: 'Array.prototype.includes',
17 | },
18 | {
19 | ruleConfig: { definition: esPlugin.rules['no-exponential-operators'] },
20 | compatFeatures: [compatData.javascript.operators.exponentiation],
21 | },
22 | ];
23 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2016.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 46';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2016,
10 | },
11 | });
12 |
13 | ruleTester.run('compat', rule, {
14 | valid: [
15 | {
16 | code: 'foo.includes();',
17 | options: [{ polyfills: ['Array.prototype.includes'] }],
18 | },
19 | ],
20 | invalid: [
21 | {
22 | code: 'foo.includes();',
23 | errors: [{ message: "ES2016 method 'Array.prototype.includes' is forbidden" }],
24 | },
25 | {
26 | code: 'Array.prototype.includes;',
27 | errors: [{ message: "ES2016 method 'Array.prototype.includes' is forbidden" }],
28 | },
29 | {
30 | code: 'foo ** bar',
31 | errors: [{ message: 'ES2016 exponential operators are forbidden.' }],
32 | },
33 | ],
34 | });
35 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2017.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import esPlugin from 'eslint-plugin-es-x';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: { definition: esPlugin.rules['no-async-functions'] },
12 | compatFeatures: [
13 | compatData.javascript.operators.async_function,
14 | compatData.javascript.statements.async_function,
15 | ],
16 | },
17 | {
18 | // Rule requires the ES2017 global, Atomics
19 | ruleConfig: { definition: esPlugin.rules['no-atomics'] },
20 | compatFeatures: [compatData.javascript.builtins.Atomics],
21 | },
22 | {
23 | ruleConfig: { definition: esPlugin.rules['no-object-getownpropertydescriptors'] },
24 | compatFeatures: [compatData.javascript.builtins.Object.getOwnPropertyDescriptors],
25 | polyfill: 'Object.getOwnPropertyDescriptors',
26 | },
27 | {
28 | ruleConfig: { definition: esPlugin.rules['no-object-entries'] },
29 | compatFeatures: [compatData.javascript.builtins.Object.entries],
30 | polyfill: 'Object.entries',
31 | },
32 | {
33 | ruleConfig: { definition: esPlugin.rules['no-object-values'] },
34 | compatFeatures: [compatData.javascript.builtins.Object.values],
35 | polyfill: 'Object.values',
36 | },
37 | {
38 | // Rule requires the ES2017 global, SharedArrayBuffer
39 | ruleConfig: { definition: esPlugin.rules['no-shared-array-buffer'] },
40 | compatFeatures: [compatData.javascript.builtins.SharedArrayBuffer],
41 | },
42 | {
43 | ruleConfig: {
44 | definition: coreRules.get('no-restricted-syntax'),
45 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.padStart', 'ES2017'),
46 | },
47 | compatFeatures: [compatData.javascript.builtins.String.padStart],
48 | polyfill: 'String.prototype.padStart',
49 | },
50 | {
51 | ruleConfig: {
52 | definition: coreRules.get('no-restricted-syntax'),
53 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.padEnd', 'ES2017'),
54 | },
55 | compatFeatures: [compatData.javascript.builtins.String.padEnd],
56 | polyfill: 'String.prototype.padEnd',
57 | },
58 | {
59 | ruleConfig: { definition: esPlugin.rules['no-trailing-function-commas'] },
60 | compatFeatures: [
61 | compatData.javascript.functions.arrow_functions.trailing_comma,
62 | compatData.javascript.operators.function.trailing_comma,
63 | compatData.javascript.operators.generator_function.trailing_comma,
64 | compatData.javascript.statements.generator_function.trailing_comma_in_parameters,
65 | compatData.javascript.statements.function.trailing_comma_in_parameters,
66 | ],
67 | },
68 | ];
69 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2017.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 53';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2017,
10 | },
11 | globals: {
12 | // ES2017 global, required by es/no-atomics
13 | Atomics: 'readonly',
14 |
15 | // ES2017 global, required by es/no-shared-array-buffer
16 | SharedArrayBuffer: 'readonly',
17 | },
18 | });
19 |
20 | ruleTester.run('compat', rule, {
21 | valid: [
22 | {
23 | code: 'Object.getOwnPropertyDescriptors();',
24 | options: [{ polyfills: ['Object.getOwnPropertyDescriptors'] }],
25 | },
26 | {
27 | code: 'Object.entries();',
28 | options: [{ polyfills: ['Object.entries'] }],
29 | },
30 | {
31 | code: 'Object.values();',
32 | options: [{ polyfills: ['Object.values'] }],
33 | },
34 | {
35 | code: 'str.padStart();',
36 | options: [{ polyfills: ['String.prototype.padStart'] }],
37 | },
38 | {
39 | code: 'str.padEnd();',
40 | options: [{ polyfills: ['String.prototype.padEnd'] }],
41 | },
42 | ],
43 | invalid: [
44 | {
45 | code: 'async function foo() {}',
46 | errors: [{ message: 'ES2017 async function declarations are forbidden.' }],
47 | },
48 | {
49 | code: 'Atomics.add(buffer, 0, 2);',
50 | errors: [{ message: "ES2017 'Atomics' class is forbidden." }],
51 | },
52 | {
53 | code: 'Object.getOwnPropertyDescriptors();',
54 | errors: [
55 | { message: "ES2017 'Object.getOwnPropertyDescriptors' method is forbidden." },
56 | ],
57 | },
58 | {
59 | code: 'Object.entries();',
60 | errors: [{ message: "ES2017 'Object.entries' method is forbidden." }],
61 | },
62 | {
63 | code: 'Object.values();',
64 | errors: [{ message: "ES2017 'Object.values' method is forbidden." }],
65 | },
66 | {
67 | code: 'new SharedArrayBuffer();',
68 | errors: [{ message: "ES2017 'SharedArrayBuffer' class is forbidden." }],
69 | },
70 | {
71 | code: 'str.padStart();',
72 | errors: [{ message: "ES2017 method 'String.prototype.padStart' is forbidden" }],
73 | },
74 | {
75 | code: 'String.prototype.padStart;',
76 | errors: [{ message: "ES2017 method 'String.prototype.padStart' is forbidden" }],
77 | },
78 | {
79 | code: 'str.padEnd();',
80 | errors: [{ message: "ES2017 method 'String.prototype.padEnd' is forbidden" }],
81 | },
82 | {
83 | code: 'String.prototype.padEnd;',
84 | errors: [{ message: "ES2017 method 'String.prototype.padEnd' is forbidden" }],
85 | },
86 | {
87 | code: 'foo(bar,);',
88 | errors: [
89 | { message: 'ES2017 trailing commas in parameter/argument lists are forbidden.' },
90 | ],
91 | },
92 | ],
93 | });
94 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2018.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import esPlugin from 'eslint-plugin-es-x';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: { definition: esPlugin.rules['no-async-iteration'] },
12 | compatFeatures: [
13 | compatData.javascript.statements.for_await_of,
14 | compatData.javascript.functions.method_definitions.async_generator_methods,
15 | ],
16 | },
17 | {
18 | ruleConfig: { definition: esPlugin.rules['no-rest-spread-properties'] },
19 | compatFeatures: [
20 | compatData.javascript.operators.destructuring.rest_in_objects,
21 | compatData.javascript.operators.spread.spread_in_object_literals,
22 | ],
23 | },
24 | {
25 | ruleConfig: {
26 | definition: coreRules.get('no-restricted-syntax'),
27 | options: noRestrictedSyntaxPrototypeMethod('Promise.prototype.finally', 'ES2018'),
28 | },
29 | compatFeatures: [compatData.javascript.builtins.Promise.finally],
30 | polyfill: 'Promise.prototype.finally',
31 | },
32 | {
33 | ruleConfig: { definition: esPlugin.rules['no-regexp-lookbehind-assertions'] },
34 | compatFeatures: [compatData.javascript.regular_expressions.lookbehind_assertion],
35 | },
36 | {
37 | ruleConfig: { definition: esPlugin.rules['no-regexp-named-capture-groups'] },
38 | compatFeatures: [compatData.javascript.regular_expressions.named_capturing_group],
39 | },
40 | {
41 | ruleConfig: { definition: esPlugin.rules['no-regexp-s-flag'] },
42 | compatFeatures: [compatData.javascript.builtins.RegExp.dotAll],
43 | },
44 | {
45 | ruleConfig: {
46 | /**
47 | * New values were added in the following ES2019.
48 | * The rule no-regexp-unicode-property-escapes-2019 accepts these, but is omitted
49 | * because the compatibility data doesn't distinguish the two.
50 | */
51 | definition: esPlugin.rules['no-regexp-unicode-property-escapes'],
52 | },
53 | compatFeatures: [
54 | compatData.javascript.regular_expressions.unicode_character_class_escape,
55 | ],
56 | },
57 | ];
58 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2018.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 59';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2018,
10 | },
11 | });
12 |
13 | ruleTester.run('compat', rule, {
14 | valid: [
15 | {
16 | code: 'foo.finally();',
17 | options: [{ polyfills: ['Promise.prototype.finally'] }],
18 | },
19 | ],
20 | invalid: [
21 | {
22 | code: 'async function* asyncGenerator() {}',
23 | errors: [{ message: 'ES2018 async iteration is forbidden.' }],
24 | },
25 | {
26 | code: 'async () => { for await (const bar of bar) { } }',
27 | errors: [{ message: 'ES2018 async iteration is forbidden.' }],
28 | },
29 | {
30 | code: 'const foo = { ...bar };',
31 | errors: [{ message: 'ES2018 rest/spread properties are forbidden.' }],
32 | },
33 | {
34 | code: 'const { a, ...rest } = foo;',
35 | errors: [{ message: 'ES2018 rest/spread properties are forbidden.' }],
36 | },
37 | {
38 | code: 'foo.finally();',
39 | errors: [{ message: "ES2018 method 'Promise.prototype.finally' is forbidden" }],
40 | },
41 | {
42 | code: 'Promise.prototype.finally;',
43 | errors: [{ message: "ES2018 method 'Promise.prototype.finally' is forbidden" }],
44 | },
45 | {
46 | code: "/(?<=a)b/.test('look-behind assertion');",
47 | errors: [{ message: 'ES2018 RegExp lookbehind assertions are forbidden.' }],
48 | },
49 | {
50 | code: "/(?b)c/.test('named capture group');",
51 | errors: [{ message: 'ES2018 RegExp named capture groups are forbidden.' }],
52 | },
53 | {
54 | code: "/./s.test('dotAll flag');",
55 | errors: [{ message: "ES2018 RegExp 's' flag is forbidden." }],
56 | },
57 | {
58 | code: "/\\p{Script=Hiragana}+/u.test('Unicode property escape');",
59 | errors: [
60 | { message: 'ES2018 RegExp Unicode property escape sequences are forbidden.' },
61 | ],
62 | },
63 | ],
64 | });
65 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2019.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import esPlugin from 'eslint-plugin-es-x';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: {
12 | definition: coreRules.get('no-restricted-syntax'),
13 | options: noRestrictedSyntaxPrototypeMethod('Array.prototype.flat', 'ES2019'),
14 | },
15 | compatFeatures: [compatData.javascript.builtins.Array.flat],
16 | polyfill: 'Array.prototype.flat',
17 | },
18 | {
19 | ruleConfig: {
20 | definition: coreRules.get('no-restricted-syntax'),
21 | options: noRestrictedSyntaxPrototypeMethod('Array.prototype.flatMap', 'ES2019'),
22 | },
23 | compatFeatures: [compatData.javascript.builtins.Array.flatMap],
24 | polyfill: 'Array.prototype.flatMap',
25 | },
26 | {
27 | ruleConfig: { definition: esPlugin.rules['no-json-superset'] },
28 | compatFeatures: [compatData.javascript.builtins.JSON.json_superset],
29 | },
30 | {
31 | ruleConfig: { definition: esPlugin.rules['no-object-fromentries'] },
32 | compatFeatures: [compatData.javascript.builtins.Object.fromEntries],
33 | polyfill: 'Object.fromEntries',
34 | },
35 | {
36 | ruleConfig: { definition: esPlugin.rules['no-optional-catch-binding'] },
37 | compatFeatures: [compatData.javascript.statements.try_catch.optional_catch_binding],
38 | },
39 | {
40 | ruleConfig: {
41 | definition: coreRules.get('no-restricted-syntax'),
42 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.trimStart', 'ES2019'),
43 | },
44 | compatFeatures: [compatData.javascript.builtins.String.trimStart],
45 | polyfill: 'String.prototype.trimStart',
46 | },
47 | {
48 | ruleConfig: {
49 | definition: coreRules.get('no-restricted-syntax'),
50 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.trimLeft', 'ES2019'),
51 | },
52 | compatFeatures: [compatData.javascript.builtins.String.trimStart], // not a mistake; trimLeft is an alias for trimStart
53 | polyfill: 'String.prototype.trimLeft',
54 | },
55 | {
56 | ruleConfig: {
57 | definition: coreRules.get('no-restricted-syntax'),
58 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.trimEnd', 'ES2019'),
59 | },
60 | compatFeatures: [compatData.javascript.builtins.String.trimEnd],
61 | polyfill: 'String.prototype.trimEnd',
62 | },
63 | {
64 | ruleConfig: {
65 | definition: coreRules.get('no-restricted-syntax'),
66 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.trimRight', 'ES2019'),
67 | },
68 | compatFeatures: [compatData.javascript.builtins.String.trimEnd], // not a mistake; trimRight is an alias for trimEnd
69 | polyfill: 'String.prototype.trimRight',
70 | },
71 | ];
72 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2019.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 65';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2019,
10 | },
11 | });
12 |
13 | ruleTester.run('compat', rule, {
14 | valid: [
15 | {
16 | code: 'const flat = residentialAddress.flat;',
17 | },
18 | {
19 | code: 'residentialAddress.flat = flat;',
20 | },
21 | {
22 | code: 'foo.flat();',
23 | options: [{ polyfills: ['Array.prototype.flat'] }],
24 | },
25 | {
26 | code: 'foo.flatMap();',
27 | options: [{ polyfills: ['Array.prototype.flatMap'] }],
28 | },
29 | {
30 | code: 'Object.fromEntries();',
31 | options: [{ polyfills: ['Object.fromEntries'] }],
32 | },
33 | {
34 | code: 'foo.trimLeft();',
35 | options: [{ polyfills: ['String.prototype.trimLeft'] }],
36 | },
37 | {
38 | code: 'foo.trimRight();',
39 | options: [{ polyfills: ['String.prototype.trimRight'] }],
40 | },
41 | {
42 | code: 'foo.trimStart();',
43 | options: [{ polyfills: ['String.prototype.trimStart'] }],
44 | },
45 | {
46 | code: 'foo.trimEnd();',
47 | options: [{ polyfills: ['String.prototype.trimEnd'] }],
48 | },
49 | ],
50 | invalid: [
51 | {
52 | code: 'foo.flat();',
53 | errors: [{ message: "ES2019 method 'Array.prototype.flat' is forbidden" }],
54 | },
55 | {
56 | code: 'Array.prototype.flatMap;',
57 | errors: [{ message: "ES2019 method 'Array.prototype.flatMap' is forbidden" }],
58 | },
59 | {
60 | // eslint-disable-next-line no-irregular-whitespace
61 | code: `const u2028 = '
';`, // line separator character \u2028 is in this string
62 | errors: [{ message: "ES2019 '\\u2028' in string literals is forbidden." }],
63 | },
64 | {
65 | code: 'Object.fromEntries();',
66 | errors: [{ message: "ES2019 'Object.fromEntries' method is forbidden." }],
67 | },
68 | {
69 | code: 'try {} catch {}',
70 | errors: [{ message: "ES2019 optional 'catch' binding is forbidden." }],
71 | },
72 | {
73 | code: 'foo.trimLeft();',
74 | errors: [{ message: "ES2019 method 'String.prototype.trimLeft' is forbidden" }],
75 | },
76 | {
77 | code: 'String.prototype.trimRight;',
78 | errors: [{ message: "ES2019 method 'String.prototype.trimRight' is forbidden" }],
79 | },
80 | {
81 | code: 'String.prototype.trimStart;',
82 | errors: [{ message: "ES2019 method 'String.prototype.trimStart' is forbidden" }],
83 | },
84 | {
85 | code: 'foo.trimEnd();',
86 | errors: [{ message: "ES2019 method 'String.prototype.trimEnd' is forbidden" }],
87 | },
88 | ],
89 | });
90 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2020.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | import esPlugin from 'eslint-plugin-es-x';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: {
12 | definition: coreRules.get('no-restricted-properties'),
13 | options: [{ object: 'Atomics', property: 'notify', message: '(ES2020)' }],
14 | },
15 | compatFeatures: [compatData.javascript.builtins.Atomics.notify],
16 | },
17 | {
18 | ruleConfig: {
19 | definition: coreRules.get('no-restricted-properties'),
20 | options: [{ object: 'Atomics', property: 'wait', message: '(ES2020)' }],
21 | },
22 | compatFeatures: [compatData.javascript.builtins.Atomics.wait],
23 | },
24 | {
25 | ruleConfig: { definition: esPlugin.rules['no-bigint'] },
26 | compatFeatures: [compatData.javascript.builtins.BigInt],
27 | },
28 | {
29 | ruleConfig: { definition: esPlugin.rules['no-dynamic-import'] },
30 | compatFeatures: [compatData.javascript.operators.import],
31 | },
32 | {
33 | ruleConfig: { definition: esPlugin.rules['no-global-this'] },
34 | compatFeatures: [compatData.javascript.builtins.globalThis],
35 | polyfill: 'globalThis',
36 | },
37 | {
38 | ruleConfig: { definition: esPlugin.rules['no-import-meta'] },
39 | compatFeatures: [compatData.javascript.operators.import_meta],
40 | },
41 | {
42 | ruleConfig: { definition: esPlugin.rules['no-export-ns-from'] },
43 | compatFeatures: [compatData.javascript.statements.export.namespace],
44 | },
45 | {
46 | ruleConfig: { definition: esPlugin.rules['no-nullish-coalescing-operators'] },
47 | compatFeatures: [compatData.javascript.operators.nullish_coalescing],
48 | },
49 | {
50 | ruleConfig: { definition: esPlugin.rules['no-optional-chaining'] },
51 | compatFeatures: [compatData.javascript.operators.optional_chaining],
52 | },
53 | {
54 | // Rule requires the ES6 global, Promise
55 | ruleConfig: { definition: esPlugin.rules['no-promise-all-settled'] },
56 | compatFeatures: [compatData.javascript.builtins.Promise.allSettled],
57 | polyfill: 'Promise.prototype.allSettled',
58 | },
59 | {
60 | // May false positive for Cache/Clients.matchAll()
61 | ruleConfig: {
62 | definition: coreRules.get('no-restricted-syntax'),
63 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.matchAll', 'ES2020'),
64 | },
65 | compatFeatures: [compatData.javascript.builtins.String.matchAll],
66 | polyfill: 'String.prototype.matchAll',
67 | },
68 | ];
69 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2020.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 62';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2020,
10 | sourceType: 'module', // import.meta and namespace exports can only be used in an ES module
11 | },
12 | globals: {
13 | // ES2020 global, required by es/no-bigint
14 | BigInt: 'readonly',
15 |
16 | // ES2020 global, required by es/no-global-this
17 | globalThis: 'readonly',
18 |
19 | // ES6 global, required by es/no-promise-all-settled
20 | Promise: 'readonly',
21 | },
22 | });
23 |
24 | ruleTester.run('compat', rule, {
25 | valid: [
26 | {
27 | code: 'globalThis.foo;',
28 | options: [{ polyfills: ['globalThis'] }],
29 | },
30 | {
31 | code: 'Promise.allSettled();',
32 | options: [{ polyfills: ['Promise.prototype.allSettled'] }],
33 | },
34 | {
35 | code: 'foo.matchAll();',
36 | options: [{ polyfills: ['String.prototype.matchAll'] }],
37 | },
38 | ],
39 | invalid: [
40 | {
41 | code: 'Atomics.notify();',
42 | errors: [{ message: "'Atomics.notify' is restricted from being used. (ES2020)" }],
43 | },
44 | {
45 | code: 'Atomics.wait();',
46 | errors: [{ message: "'Atomics.wait' is restricted from being used. (ES2020)" }],
47 | },
48 | {
49 | code: 'const foo = 100n;',
50 | errors: [{ message: 'ES2020 BigInt is forbidden.' }],
51 | },
52 | {
53 | code: 'BigInt(100);',
54 | errors: [{ message: 'ES2020 BigInt is forbidden.' }],
55 | },
56 | {
57 | code: "async function foo() { await import(''); }",
58 | errors: [{ message: "ES2020 'import()' syntax is forbidden." }],
59 | },
60 | {
61 | code: 'globalThis.foo;',
62 | errors: [{ message: "ES2020 'globalThis' variable is forbidden." }],
63 | },
64 | {
65 | code: 'import.meta;',
66 | errors: [{ message: "ES2020 'import.meta' meta property is forbidden." }],
67 | },
68 | {
69 | code: 'export * as nmspace from "./other";',
70 | errors: [{ message: "ES2020 'export * as ns' are forbidden." }],
71 | },
72 | {
73 | code: 'foo ?? fallback',
74 | errors: [{ message: 'ES2020 nullish coalescing operators are forbidden.' }],
75 | },
76 | {
77 | code: 'fooMaybe?.something',
78 | errors: [{ message: 'ES2020 optional chaining is forbidden.' }],
79 | },
80 | {
81 | code: 'Promise.allSettled();',
82 | errors: [{ message: "ES2020 'Promise.allSettled' function is forbidden." }],
83 | },
84 | {
85 | code: 'foo.matchAll();',
86 | errors: [{ message: "ES2020 method 'String.prototype.matchAll' is forbidden" }],
87 | },
88 | {
89 | code: 'String.prototype.matchAll;',
90 | errors: [{ message: "ES2020 method 'String.prototype.matchAll' is forbidden" }],
91 | },
92 | ],
93 | });
94 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2021.js:
--------------------------------------------------------------------------------
1 | import eslint from 'eslint';
2 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
3 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
4 | import esPlugin from 'eslint-plugin-es-x';
5 | import { noRestrictedSyntaxPrototypeMethod } from './ruleOptionsUtil.js';
6 |
7 | const coreRules = new eslint.Linter().getRules();
8 |
9 | export default [
10 | {
11 | ruleConfig: {
12 | definition: coreRules.get('no-restricted-syntax'),
13 | options: noRestrictedSyntaxPrototypeMethod('String.prototype.replaceAll', 'ES2021'),
14 | },
15 | compatFeatures: [compatData.javascript.builtins.String.replaceAll],
16 | polyfill: 'String.prototype.replaceAll',
17 | },
18 | {
19 | ruleConfig: { definition: esPlugin.rules['no-logical-assignment-operators'] },
20 | compatFeatures: [
21 | compatData.javascript.operators.logical_or_assignment,
22 | compatData.javascript.operators.logical_and_assignment,
23 | compatData.javascript.operators.nullish_coalescing_assignment,
24 | ],
25 | },
26 | {
27 | ruleConfig: { definition: esPlugin.rules['no-numeric-separators'] },
28 | compatFeatures: [compatData.javascript.grammar.numeric_separators],
29 | },
30 | {
31 | ruleConfig: { definition: esPlugin.rules['no-promise-any'] },
32 | compatFeatures: [compatData.javascript.builtins.Promise.any],
33 | polyfill: 'Promise.prototype.any',
34 | },
35 | {
36 | ruleConfig: { definition: esPlugin.rules['no-weakrefs'] },
37 | compatFeatures: [
38 | compatData.javascript.builtins.WeakRef,
39 | compatData.javascript.builtins.FinalizationRegistry,
40 | ],
41 | },
42 | ];
43 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2021.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 74';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2021,
10 | },
11 | globals: {
12 | // ES2021 global, required by es/no-weakrefs
13 | WeakRef: 'readonly',
14 | FinalizationRegistry: 'readonly',
15 | // ES6 global, required by es/no-promise-all-settled
16 | Promise: 'readonly',
17 | },
18 | });
19 |
20 | ruleTester.run('compat', rule, {
21 | valid: [
22 | {
23 | code: '"A dog".replaceAll("dog", "monkey");',
24 | options: [{ polyfills: ['String.prototype.replaceAll'] }],
25 | },
26 | {
27 | code: 'const a = Promise.any([]);',
28 | options: [{ polyfills: ['Promise.prototype.any'] }],
29 | },
30 | ],
31 | invalid: [
32 | {
33 | code: '"A dog".replaceAll("dog", "monkey");',
34 | errors: [{ message: "ES2021 method 'String.prototype.replaceAll' is forbidden" }],
35 | },
36 | {
37 | code: 'a ||= 1;',
38 | errors: [{ message: 'ES2021 logical assignment operators are forbidden.' }],
39 | },
40 | {
41 | code: 'a &&= 1;',
42 | errors: [{ message: 'ES2021 logical assignment operators are forbidden.' }],
43 | },
44 | {
45 | code: 'a ??= 1;',
46 | errors: [{ message: 'ES2021 logical assignment operators are forbidden.' }],
47 | },
48 | {
49 | code: 'const a = 1_000_00;',
50 | errors: [{ message: 'ES2021 numeric separators are forbidden.' }],
51 | },
52 | {
53 | code: 'const a = Promise.any([]);',
54 | errors: [{ message: "ES2021 'Promise.any' is forbidden." }],
55 | },
56 | {
57 | code: 'const a = new WeakRef();',
58 | errors: [{ message: "ES2021 'WeakRef' class is forbidden." }],
59 | },
60 | {
61 | code: 'const a = new FinalizationRegistry(() => {});',
62 | errors: [{ message: "ES2021 'FinalizationRegistry' class is forbidden." }],
63 | },
64 | ],
65 | });
66 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2022.js:
--------------------------------------------------------------------------------
1 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
2 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
3 | import esPlugin from 'eslint-plugin-es-x';
4 |
5 | export default [
6 | {
7 | ruleConfig: {
8 | definition: esPlugin.rules['no-array-string-prototype-at'],
9 | options: [{ aggressive: true }],
10 | },
11 | compatFeatures: [
12 | compatData.javascript.builtins.Array.at,
13 | compatData.javascript.builtins.TypedArray.at,
14 | compatData.javascript.builtins.String.at,
15 | ],
16 | polyfill: '{Array,String,TypedArray}.prototype.at',
17 | },
18 | {
19 | ruleConfig: { definition: esPlugin.rules['no-class-fields'] },
20 | compatFeatures: [
21 | compatData.javascript.classes.public_class_fields,
22 | compatData.javascript.classes.private_class_fields,
23 | compatData.javascript.classes.static_class_fields,
24 | compatData.javascript.classes.private_class_methods,
25 | ],
26 | },
27 | {
28 | ruleConfig: { definition: esPlugin.rules['no-class-static-block'] },
29 | compatFeatures: [compatData.javascript.classes.static_initialization_blocks],
30 | },
31 | {
32 | ruleConfig: { definition: esPlugin.rules['no-error-cause'] },
33 | compatFeatures: [compatData.javascript.builtins.Error.Error.options_cause_parameter],
34 | polyfill: 'Error.cause',
35 | },
36 | {
37 | ruleConfig: { definition: esPlugin.rules['no-object-hasown'] },
38 | compatFeatures: [compatData.javascript.builtins.Object.hasOwn],
39 | polyfill: 'Object.hasOwn',
40 | },
41 | {
42 | ruleConfig: { definition: esPlugin.rules['no-private-in'] },
43 | compatFeatures: [compatData.javascript.classes.private_class_fields_in],
44 | },
45 | {
46 | ruleConfig: { definition: esPlugin.rules['no-regexp-d-flag'] },
47 | compatFeatures: [compatData.javascript.builtins.RegExp.hasIndices],
48 | },
49 | {
50 | ruleConfig: { definition: esPlugin.rules['no-top-level-await'] },
51 | compatFeatures: [compatData.javascript.operators.await.top_level],
52 | },
53 | ];
54 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2022.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 71';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2022,
10 | sourceType: 'module', // top level await can only be used in an ES module
11 | },
12 | });
13 |
14 | ruleTester.run('compat', rule, {
15 | valid: [
16 | {
17 | code: '[].at(1);',
18 | options: [{ polyfills: ['{Array,String,TypedArray}.prototype.at'] }],
19 | },
20 | {
21 | code: '"Foo".at(1);',
22 | options: [{ polyfills: ['{Array,String,TypedArray}.prototype.at'] }],
23 | },
24 | {
25 | code: "new Error('message', { cause: originalError })",
26 | options: [{ polyfills: ['Error.cause'] }],
27 | },
28 | {
29 | code: "Object.hasOwn(obj, 'prop');",
30 | options: [{ polyfills: ['Object.hasOwn'] }],
31 | },
32 | ],
33 | invalid: [
34 | {
35 | // Obvious array, doesn't need aggressive mode
36 | code: '[].at(1);',
37 | errors: [{ message: "ES2022 'Array.prototype.at' method is forbidden." }],
38 | },
39 | {
40 | // Obvious string, doesn't need aggressive mode
41 | code: '"Foo".at(1);',
42 | errors: [{ message: "ES2022 'String.prototype.at' method is forbidden." }],
43 | },
44 | {
45 | // Not obvious, needs aggressive mode
46 | code: 'foo.at(1);',
47 | errors: [{ message: "ES2022 'Array.prototype.at' method is forbidden." }],
48 | },
49 | {
50 | code: 'class A { #a = 0 }',
51 | errors: [{ message: 'ES2022 private field #a is forbidden.' }],
52 | },
53 | {
54 | code: 'class A { static { } }',
55 | errors: [{ message: 'ES2022 class static block is forbidden.' }],
56 | },
57 | {
58 | code: "new Error('message', { cause: originalError })",
59 | errors: [{ message: 'ES2022 Error Cause is forbidden.' }],
60 | },
61 | {
62 | code: "Object.hasOwn(obj, 'prop');",
63 | errors: [{ message: "ES2022 'Object.hasOwn' method is forbidden." }],
64 | },
65 | {
66 | code: '/./d;',
67 | errors: [{ message: "ES2022 RegExp 'd' flag is forbidden." }],
68 | },
69 | {
70 | code: 'await true;',
71 | errors: [{ message: "ES2022 top-level 'await' is forbidden." }],
72 | },
73 | {
74 | code: 'class A { #field; foo() { #field in this; } }',
75 | // Browser that supports private fields but not `in` on them - see es-versions.md
76 | options: [{ overrideBrowserslist: 'Chrome >= 90' }],
77 | errors: [{ message: 'ES2022 private in (`#field in object`) is forbidden.' }],
78 | },
79 | ],
80 | });
81 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2023.js:
--------------------------------------------------------------------------------
1 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
2 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
3 | import esPlugin from 'eslint-plugin-es-x';
4 |
5 | export default [
6 | {
7 | ruleConfig: {
8 | definition: esPlugin.rules['no-array-prototype-findlast-findlastindex'],
9 | options: [{ aggressive: true }],
10 | },
11 | compatFeatures: [
12 | compatData.javascript.builtins.Array.findLast,
13 | compatData.javascript.builtins.Array.findLastIndex,
14 | compatData.javascript.builtins.TypedArray.findLast,
15 | compatData.javascript.builtins.TypedArray.findLastIndex,
16 | ],
17 | polyfill: '{Array,TypedArray}.prototype.findLast',
18 | },
19 | {
20 | ruleConfig: {
21 | definition: esPlugin.rules['no-array-prototype-toreversed'],
22 | options: [{ aggressive: true }],
23 | },
24 | compatFeatures: [
25 | compatData.javascript.builtins.Array.toReversed,
26 | compatData.javascript.builtins.TypedArray.toReversed,
27 | ],
28 | polyfill: '{Array,TypedArray}.prototype.toReversed',
29 | },
30 | {
31 | ruleConfig: {
32 | definition: esPlugin.rules['no-array-prototype-tosorted'],
33 | options: [{ aggressive: true }],
34 | },
35 | compatFeatures: [
36 | compatData.javascript.builtins.Array.toSorted,
37 | compatData.javascript.builtins.TypedArray.toSorted,
38 | ],
39 | polyfill: '{Array,TypedArray}.prototype.toSorted',
40 | },
41 | {
42 | ruleConfig: {
43 | definition: esPlugin.rules['no-array-prototype-tospliced'],
44 | options: [{ aggressive: true }],
45 | },
46 | compatFeatures: [compatData.javascript.builtins.Array.toSpliced],
47 | polyfill: 'Array.prototype.toSpliced',
48 | },
49 | {
50 | ruleConfig: {
51 | definition: esPlugin.rules['no-array-prototype-with'],
52 | options: [{ aggressive: true }],
53 | },
54 | compatFeatures: [
55 | compatData.javascript.builtins.Array.with,
56 | compatData.javascript.builtins.TypedArray.with,
57 | ],
58 | polyfill: '{Array,TypedArray}.prototype.with',
59 | },
60 | {
61 | ruleConfig: {
62 | definition: esPlugin.rules['no-hashbang'],
63 | },
64 | compatFeatures: [compatData.javascript.grammar.hashbang_comments],
65 | },
66 | ];
67 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/es2023.test.js:
--------------------------------------------------------------------------------
1 | import { RuleTester } from 'eslint';
2 | import rule from '../rule.js';
3 |
4 | // Browser that doesn't support any features of this version - see es-versions.md
5 | process.env.BROWSERSLIST = 'Chrome >= 73';
6 |
7 | const ruleTester = new RuleTester({
8 | parserOptions: {
9 | ecmaVersion: 2023,
10 | },
11 | });
12 |
13 | ruleTester.run('compat', rule, {
14 | valid: [
15 | {
16 | code: '[].findLast("a");',
17 | options: [{ polyfills: ['{Array,TypedArray}.prototype.findLast'] }],
18 | },
19 | {
20 | code: '[].toReversed();',
21 | options: [{ polyfills: ['{Array,TypedArray}.prototype.toReversed'] }],
22 | },
23 | {
24 | code: '[].toSorted();',
25 | options: [{ polyfills: ['{Array,TypedArray}.prototype.toSorted'] }],
26 | },
27 | {
28 | code: '[].toSpliced(1);',
29 | options: [{ polyfills: ['Array.prototype.toSpliced'] }],
30 | },
31 | {
32 | code: '[].with(1, "a");',
33 | options: [{ polyfills: ['{Array,TypedArray}.prototype.with'] }],
34 | },
35 | ],
36 | invalid: [
37 | {
38 | // Obvious array, doesn't need aggressive mode
39 | code: '[].findLast("a");',
40 | errors: [{ message: "ES2023 'Array.prototype.findLast' method is forbidden." }],
41 | },
42 | {
43 | // Not obvious, needs aggressive mode
44 | code: 'foo.findLast("a");',
45 | errors: [{ message: "ES2023 'Array.prototype.findLast' method is forbidden." }],
46 | },
47 | {
48 | // Obvious array, doesn't need aggressive mode
49 | code: '[].toReversed();',
50 | errors: [{ message: "ES2023 'Array.prototype.toReversed' method is forbidden." }],
51 | },
52 | {
53 | // Not obvious, needs aggressive mode
54 | code: 'foo.toReversed();',
55 | errors: [{ message: "ES2023 'Array.prototype.toReversed' method is forbidden." }],
56 | },
57 | {
58 | // Obvious array, doesn't need aggressive mode
59 | code: '[].toSorted();',
60 | errors: [{ message: "ES2023 'Array.prototype.toSorted' method is forbidden." }],
61 | },
62 | {
63 | // Not obvious, needs aggressive mode
64 | code: 'foo.toSorted();',
65 | errors: [{ message: "ES2023 'Array.prototype.toSorted' method is forbidden." }],
66 | },
67 | {
68 | // Obvious array, doesn't need aggressive mode
69 | code: '[].toSpliced(1);',
70 | errors: [{ message: "ES2023 'Array.prototype.toSpliced' method is forbidden." }],
71 | },
72 | {
73 | // Not obvious, needs aggressive mode
74 | code: 'foo.toSpliced(1);',
75 | errors: [{ message: "ES2023 'Array.prototype.toSpliced' method is forbidden." }],
76 | },
77 | {
78 | // Obvious array, doesn't need aggressive mode
79 | code: '[].with(1, "a");',
80 | errors: [{ message: "ES2023 'Array.prototype.with' method is forbidden." }],
81 | },
82 | {
83 | // Not obvious, needs aggressive mode
84 | code: 'foo.with(1, "a");',
85 | errors: [{ message: "ES2023 'Array.prototype.with' method is forbidden." }],
86 | },
87 | {
88 | code: '#!/usr/bin/env node',
89 | errors: [{ message: 'ES2023 Hashbang comments are forbidden.' }],
90 | },
91 | ],
92 | });
93 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/index.js:
--------------------------------------------------------------------------------
1 | import es2016 from './es2016.js';
2 | import es2017 from './es2017.js';
3 | import es2018 from './es2018.js';
4 | import es2019 from './es2019.js';
5 | import es2020 from './es2020.js';
6 | import es2021 from './es2021.js';
7 | import es2022 from './es2022.js';
8 | import es2023 from './es2023.js';
9 |
10 | export default [
11 | ...es2016,
12 | ...es2017,
13 | ...es2018,
14 | ...es2019,
15 | ...es2020,
16 | ...es2021,
17 | ...es2022,
18 | ...es2023,
19 | ];
20 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/features/ruleOptionsUtil.js:
--------------------------------------------------------------------------------
1 | export function noRestrictedSyntaxPrototypeMethod(method, esVersionName) {
2 | const [builtin, , name] = method.split('.');
3 | const message = `${esVersionName} method '${method}' is forbidden`;
4 |
5 | return [
6 | {
7 | selector: `CallExpression[callee.property.name='${name}']`,
8 | message,
9 | },
10 | {
11 | selector: `MemberExpression[object.object.name='${builtin}'][object.property.name='prototype'][property.name='${name}']`,
12 | message,
13 | },
14 | ];
15 | }
16 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/index.js:
--------------------------------------------------------------------------------
1 | import rule from './rule.js';
2 |
3 | export default {
4 | configs: {
5 | recommended: {
6 | plugins: ['ecmascript-compat'],
7 | rules: {
8 | 'ecmascript-compat/compat': 'error',
9 | },
10 | },
11 | },
12 | rules: {
13 | compat: rule,
14 | },
15 | };
16 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/rule.js:
--------------------------------------------------------------------------------
1 | import * as compatibility from './compatibility.js';
2 | import { createDelegatee, delegatingVisitor } from './delegation.js';
3 | import features from './features/index.js';
4 | import targetRuntimes from './targetRuntimes.js';
5 |
6 | export default {
7 | meta: {
8 | type: 'problem',
9 | schema: [
10 | {
11 | type: 'object',
12 | properties: {
13 | polyfills: {
14 | type: 'array',
15 | items: {
16 | type: 'string',
17 | enum: [
18 | // This list is hard-coded so it can serve as documentation
19 | 'globalThis',
20 | '{Array,String,TypedArray}.prototype.at',
21 | '{Array,TypedArray}.prototype.findLast',
22 | '{Array,TypedArray}.prototype.toReversed',
23 | '{Array,TypedArray}.prototype.toSorted',
24 | '{Array,TypedArray}.prototype.with',
25 | 'Array.prototype.flat',
26 | 'Array.prototype.flatMap',
27 | 'Array.prototype.includes',
28 | 'Array.prototype.toSpliced',
29 | 'Error.cause',
30 | 'Object.entries',
31 | 'Object.fromEntries',
32 | 'Object.getOwnPropertyDescriptors',
33 | 'Object.hasOwn',
34 | 'Object.values',
35 | 'Promise.prototype.allSettled',
36 | 'Promise.prototype.any',
37 | 'Promise.prototype.finally',
38 | 'String.prototype.matchAll',
39 | 'String.prototype.padEnd',
40 | 'String.prototype.padStart',
41 | 'String.prototype.replaceAll',
42 | 'String.prototype.trimEnd',
43 | 'String.prototype.trimLeft',
44 | 'String.prototype.trimRight',
45 | 'String.prototype.trimStart',
46 | ],
47 | },
48 | },
49 | overrideBrowserslist: {
50 | oneOf: [{ type: 'string' }, { type: 'array', items: { type: 'string' } }],
51 | },
52 | browserslistOptions: {
53 | type: 'object',
54 | additionalProperties: true,
55 | },
56 | },
57 | additionalProperties: false,
58 | },
59 | ],
60 | },
61 | create(context) {
62 | const overrideBrowserslist = context.options?.[0]?.overrideBrowserslist;
63 | const browserslistOptions = context.options?.[0]?.browserslistOptions;
64 | const targets = targetRuntimes(overrideBrowserslist, browserslistOptions);
65 | const unsupportedFeatures = compatibility.unsupportedFeatures(features, targets);
66 |
67 | const polyfills = context.options?.[0]?.polyfills ?? [];
68 |
69 | const visitors = unsupportedFeatures
70 | .filter((feature) => !polyfills.includes(feature.polyfill))
71 | .map((feature) => createDelegatee(feature.ruleConfig, context));
72 |
73 | return delegatingVisitor(visitors);
74 | },
75 | };
76 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/rule.test.js:
--------------------------------------------------------------------------------
1 | import assert from 'node:assert';
2 | import { test } from 'node:test';
3 | import features from './features/index.js';
4 | import rule from './rule.js';
5 |
6 | test('polyfills accepted in the schema exactly match those supported', () => {
7 | const schemaPolyfills = rule.meta.schema[0].properties.polyfills.items.enum;
8 | const supportedPolyfills = features.flatMap((feature) =>
9 | feature.polyfill ? [feature.polyfill] : []
10 | );
11 |
12 | assert.deepStrictEqual(schemaPolyfills.sort(), supportedPolyfills.sort());
13 | });
14 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/targetRuntimes.js:
--------------------------------------------------------------------------------
1 | import browserslist from 'browserslist';
2 | import _ from 'lodash';
3 | // Import assertions aren't yet stage 4 so aren't supported by ESLint
4 | import compatData from '@mdn/browser-compat-data/forLegacyNode';
5 | import compareVersions from './compareVersions.js';
6 |
7 | export default function targetRuntimes(overrideBrowserslist, browserslistOptions) {
8 | // ['chrome 50', ...]
9 | const allNamedVersions = browserslist(overrideBrowserslist, browserslistOptions);
10 |
11 | // [ { name, version }, ... ]
12 | const all = allNamedVersions.map((namedVersion) => {
13 | const [name, version] = namedVersion.split(' ');
14 | return {
15 | name,
16 | version: simplifyVersion(version),
17 | };
18 | });
19 |
20 | // { name: oldestVersion }
21 | const oldestOfEach = _.chain(all)
22 | .groupBy('name')
23 | .mapValues(
24 | (familyMember) =>
25 | familyMember.sort((a, b) => compareVersions(a.version, b.version))[0].version
26 | )
27 | .value();
28 |
29 | const mapped = _.mapKeys(oldestOfEach, (version, name) => mapFamilyName(name));
30 | const final = _.pickBy(mapped, (version, name) => isKnownFamily(name));
31 |
32 | // [ { name, version } ]
33 | return Object.entries(final).map(([name, version]) => ({ name, version }));
34 | }
35 |
36 | function isKnownFamily(name) {
37 | return compatData.browsers[name] != null;
38 | }
39 |
40 | // browserslist -> @mdn/browser-compat-data (where necessary and available)
41 | /* eslint-disable camelcase */
42 | const familyNameMapping = {
43 | and_chr: 'chrome_android',
44 | and_ff: 'firefox_android',
45 | android: 'webview_android',
46 | ios_saf: 'safari_ios',
47 | node: 'nodejs',
48 | op_mob: 'opera_android',
49 | samsung: 'samsunginternet_android',
50 | };
51 | /* eslint-enable camelcase */
52 |
53 | function mapFamilyName(browserslistName) {
54 | return familyNameMapping[browserslistName] || browserslistName;
55 | }
56 |
57 | function simplifyVersion(version) {
58 | return version.includes('-') ? version.split('-')[0] : version;
59 | }
60 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/lib/targetRuntimes.test.js:
--------------------------------------------------------------------------------
1 | import assert from 'node:assert';
2 | import { beforeEach, it } from 'node:test';
3 | import browserslist from 'browserslist';
4 | import targetRuntimes from './targetRuntimes.js';
5 |
6 | beforeEach(() => {
7 | delete process.env.BROWSERSLIST;
8 | browserslist.clearCaches();
9 | });
10 |
11 | it('targets the oldest version of each family', () => {
12 | process.env.BROWSERSLIST = 'Chrome >= 50';
13 |
14 | assert.deepStrictEqual(targetRuntimes(), [{ name: 'chrome', version: '50' }]);
15 | });
16 |
17 | it('targets the oldest version of each family, treating versions as numbers', () => {
18 | process.env.BROWSERSLIST = 'chrome 9-10';
19 |
20 | assert.deepStrictEqual(targetRuntimes(), [{ name: 'chrome', version: '9' }]);
21 | });
22 |
23 | it('maps browserslist names to mdn names where necessary', () => {
24 | process.env.BROWSERSLIST = 'Android >= 0';
25 |
26 | assert.deepStrictEqual(targetRuntimes(), [{ name: 'webview_android', version: '2.1' }]);
27 | });
28 |
29 | it('discards families unknown to mdn', () => {
30 | process.env.BROWSERSLIST = 'kaios >= 0';
31 |
32 | assert.deepStrictEqual(targetRuntimes(), []);
33 | });
34 |
35 | it('handles multiple families', () => {
36 | process.env.BROWSERSLIST = 'Firefox >= 55,IE >= 10';
37 |
38 | assert.deepStrictEqual(targetRuntimes(), [
39 | { name: 'firefox', version: '55' },
40 | { name: 'ie', version: '10' },
41 | ]);
42 | });
43 |
44 | it('accepts a override', () => {
45 | assert.deepStrictEqual(targetRuntimes('Firefox >= 55,IE >= 10'), [
46 | { name: 'firefox', version: '55' },
47 | { name: 'ie', version: '10' },
48 | ]);
49 | });
50 |
51 | it('preserves versions as strings to allow semver', () => {
52 | process.env.BROWSERSLIST = 'Node >= 0';
53 |
54 | assert.deepStrictEqual(targetRuntimes(), [{ name: 'nodejs', version: '0.2.0' }]);
55 | });
56 |
57 | it('simplifies version ranges to the start of the range', () => {
58 | assert.deepStrictEqual(browserslist('iOS 15'), ['ios_saf 15.0-15.1']);
59 |
60 | process.env.BROWSERSLIST = 'iOS 15';
61 |
62 | assert.deepStrictEqual(targetRuntimes(), [{ name: 'safari_ios', version: '15.0' }]);
63 | });
64 |
--------------------------------------------------------------------------------
/packages/eslint-plugin-ecmascript-compat/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "eslint-plugin-ecmascript-compat",
3 | "version": "3.2.1",
4 | "description": "ESLint plugin for checking JavaScript code compatibility with target browsers and Node.js versions",
5 | "keywords": [
6 | "browser",
7 | "compatibility",
8 | "compat",
9 | "support",
10 | "javascript",
11 | "ecmascript",
12 | "es",
13 | "lint",
14 | "eslint",
15 | "eslintplugin",
16 | "browserslist",
17 | "browser-compat-data",
18 | "caniuse",
19 | "kangax",
20 | "eslint-plugin-compat",
21 | "eslint-plugin-es",
22 | "eslint-plugin-es-x"
23 | ],
24 | "homepage": "https://github.com/robatwilliams/es-compat#readme",
25 | "bugs": {
26 | "url": "https://github.com/robatwilliams/es-compat/issues"
27 | },
28 | "repository": {
29 | "type": "git",
30 | "url": "https://github.com/robatwilliams/es-compat.git"
31 | },
32 | "license": "MIT",
33 | "author": "Robat Williams",
34 | "type": "module",
35 | "main": "lib/index.js",
36 | "scripts": {
37 | "test": "node --test"
38 | },
39 | "dependencies": {
40 | "@mdn/browser-compat-data": "5.5.6",
41 | "browserslist": "^4.22.2",
42 | "eslint-plugin-es-x": "^7.5.0",
43 | "lodash": "^4.17.21"
44 | },
45 | "devDependencies": {
46 | "eslint": "^8.56.0"
47 | },
48 | "peerDependencies": {
49 | "eslint": ">=8"
50 | },
51 | "engines": {
52 | "node": ">=16.0.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------