From 60ff6d2713dbdb1fa2b76f6d25a6125ec0d003eb Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Fri, 24 Jul 2020 08:40:00 +0900 Subject: [PATCH 01/34] Install `@types/table` type definition (#4872) This is a part of #4399. This change installs the type definition `@types/table` of the `table` package. The package is used in `lib/formatters/stringFormatter.js`: https://github.com/stylelint/stylelint/blob/cecacb9d4fe3b5bae5f264efa6e60c414a0f4946/lib/formatters/stringFormatter.js#L8 See also: - https://www.npmjs.com/package/table - https://www.npmjs.com/package/@types/table --- package-lock.json | 6 ++++++ package.json | 1 + types/global.d.ts | 1 - 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index cc6d50e2fe..732495702d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -996,6 +996,12 @@ "integrity": "sha512-PlLI3u2hocS4nbzd9WUzQn/EyFl+NifbssU9QV40XzWOpwf5R7cDod2dmTUKYN7awE9jMrhy9FCO904ZYwaBDw==", "dev": true }, + "@types/table": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/table/-/table-5.0.0.tgz", + "integrity": "sha512-fQLtGLZXor264zUPWI95WNDsZ3QV43/c0lJpR/h1hhLJumXRmHNsrvBfEzW2YMhb0EWCsn4U6h82IgwsajAuTA==", + "dev": true + }, "@types/unist": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz", diff --git a/package.json b/package.json index 3f5498a278..296ad39f12 100644 --- a/package.json +++ b/package.json @@ -173,6 +173,7 @@ "@types/postcss-safe-parser": "^4.0.0", "@types/style-search": "^0.1.1", "@types/svg-tags": "^1.0.0", + "@types/table": "^5.0.0", "@types/write-file-atomic": "^3.0.1", "benchmark": "^2.1.4", "common-tags": "^1.8.0", diff --git a/types/global.d.ts b/types/global.d.ts index b32f120a83..a2a6a6a39c 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -6,4 +6,3 @@ declare module 'postcss-less'; declare module 'postcss-sass'; declare module 'postcss-scss'; declare module 'sugarss'; -declare module 'table'; From 9f93d1f25ab6c8f8142817269243848fb1bec22a Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Fri, 24 Jul 2020 08:41:53 +0900 Subject: [PATCH 02/34] Add type definition for `postcss-syntax` (#4871) This change adds a type definition for the `postcss-syntax` package. To find the definition easily, this extracts a new file from the `types/postcss/index.d.ts` file. Note that there is no `@types/postcss-syntax` package. (see ) Here is a main source of the package: https://github.com/gucong3000/postcss-syntax/blob/v0.36.2/index.js Also, `postcss-syntax` is used only in `lib/getPostcssResult.js`: https://github.com/stylelint/stylelint/blob/cecacb9d4fe3b5bae5f264efa6e60c414a0f4946/lib/getPostcssResult.js#L64-L75 This is a part of #4399. --- types/postcss-syntax/index.d.ts | 7 +++++++ types/postcss/index.d.ts | 6 ------ 2 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 types/postcss-syntax/index.d.ts diff --git a/types/postcss-syntax/index.d.ts b/types/postcss-syntax/index.d.ts new file mode 100644 index 0000000000..75a6c32315 --- /dev/null +++ b/types/postcss-syntax/index.d.ts @@ -0,0 +1,7 @@ +declare module 'postcss-syntax' { + import { Syntax } from 'postcss'; + + function syntax(config: { [k: string]: Syntax }): Syntax; + + export = syntax; +} diff --git a/types/postcss/index.d.ts b/types/postcss/index.d.ts index 5173bd4af7..17912361e6 100644 --- a/types/postcss/index.d.ts +++ b/types/postcss/index.d.ts @@ -27,12 +27,6 @@ declare module 'postcss/lib/lazy-result' { export = LazyResultImpl; } -declare module 'postcss-syntax' { - var result: any; // TODO TYPES - - export = result; -} - declare module 'postcss/lib/result' { import { Result } from 'postcss'; From 30bacfc2b6559b8428d44c01e612e343021e6be7 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Thu, 30 Jul 2020 09:03:27 +0900 Subject: [PATCH 03/34] Use official `postcss-scss` types (#4879) The `postcss-scss` package has own types already. https://github.com/postcss/postcss-scss/blob/2.1.1/lib/scss-syntax.d.ts --- types/global.d.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/types/global.d.ts b/types/global.d.ts index a2a6a6a39c..57e1654f4c 100644 --- a/types/global.d.ts +++ b/types/global.d.ts @@ -4,5 +4,4 @@ declare module 'import-lazy'; declare module 'postcss-html'; declare module 'postcss-less'; declare module 'postcss-sass'; -declare module 'postcss-scss'; declare module 'sugarss'; From 48fb7cf4b49ff948bd1e6848165fde77ea7e8543 Mon Sep 17 00:00:00 2001 From: Mike Allanson Date: Sat, 1 Aug 2020 18:53:13 +0100 Subject: [PATCH 04/34] Fix inconsistent trailing newlines in CLI error output (#4876) --- lib/cli.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/cli.js b/lib/cli.js index cf8179e083..f1805e6c83 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -534,7 +534,7 @@ module.exports = (argv) => { * @returns {void} */ function handleError(err) { - process.stderr.write(err.stack); + process.stderr.write(err.stack + EOL); const exitCode = typeof err.code === 'number' ? err.code : 1; process.exitCode = exitCode; From 2338275fbc4a5209d7eb5fc02d6439138a0bf78e Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Sat, 1 Aug 2020 18:55:29 +0100 Subject: [PATCH 05/34] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f31248903d..d9d52d923b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ All notable changes to this project are documented in this file. - Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). - Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). +- Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). - Fixed: false negatives for `where`, `is`, `nth-child` and `nth-last-child` in `selector-max-*` rules (except selector-max-type) ([#4842](https://github.com/stylelint/stylelint/pull/4842)). ## 13.6.1 From f02a58836190f73a234bd4031b99424ca40e71e5 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sat, 1 Aug 2020 19:13:15 +0100 Subject: [PATCH 06/34] Bump jest from 26.0.1 to 26.1.0 (#4883) Bumps [jest](https://github.com/facebook/jest) from 26.0.1 to 26.1.0. - [Release notes](https://github.com/facebook/jest/releases) - [Changelog](https://github.com/facebook/jest/blob/master/CHANGELOG.md) - [Commits](https://github.com/facebook/jest/compare/v26.0.1...v26.1.0) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 1824 +++++++++++++++++++++++++++++++++++++++++---- package.json | 2 +- 2 files changed, 1691 insertions(+), 135 deletions(-) diff --git a/package-lock.json b/package-lock.json index 732495702d..0792c3c655 100644 --- a/package-lock.json +++ b/package-lock.json @@ -419,33 +419,33 @@ } }, "@jest/core": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.0.1.tgz", - "integrity": "sha512-Xq3eqYnxsG9SjDC+WLeIgf7/8KU6rddBxH+SCt18gEpOhAGYC/Mq+YbtlNcIdwjnnT+wDseXSbU0e5X84Y4jTQ==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.1.0.tgz", + "integrity": "sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/reporters": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.1.0", + "@jest/reporters": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.0.1", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", + "jest-changed-files": "^26.1.0", + "jest-config": "^26.1.0", + "jest-haste-map": "^26.1.0", + "jest-message-util": "^26.1.0", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-resolve-dependencies": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "jest-watcher": "^26.0.1", + "jest-resolve": "^26.1.0", + "jest-resolve-dependencies": "^26.1.0", + "jest-runner": "^26.1.0", + "jest-runtime": "^26.1.0", + "jest-snapshot": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "jest-watcher": "^26.1.0", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "rimraf": "^3.0.0", @@ -453,6 +453,557 @@ "strip-ansi": "^6.0.0" }, "dependencies": { + "@jest/console": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", + "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "jest-message-util": "^26.1.0", + "jest-util": "^26.1.0", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.1.0.tgz", + "integrity": "sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0" + } + }, + "@jest/fake-timers": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.1.0.tgz", + "integrity": "sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@sinonjs/fake-timers": "^6.0.1", + "jest-message-util": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0" + } + }, + "@jest/globals": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.1.0.tgz", + "integrity": "sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/types": "^26.1.0", + "expect": "^26.1.0" + } + }, + "@jest/source-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.1.0.tgz", + "integrity": "sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", + "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz", + "integrity": "sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q==", + "dev": true, + "requires": { + "@jest/test-result": "^26.1.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.1.0", + "jest-runner": "^26.1.0", + "jest-runtime": "^26.1.0" + } + }, + "@jest/transform": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", + "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.1.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.1.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", + "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "babel-jest": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.1.0.tgz", + "integrity": "sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg==", + "dev": true, + "requires": { + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz", + "integrity": "sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz", + "integrity": "sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^26.1.0", + "babel-preset-current-node-syntax": "^0.1.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "expect": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", + "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.0.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-regex-util": "^26.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-config": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.1.0.tgz", + "integrity": "sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.1.0", + "@jest/types": "^26.1.0", + "babel-jest": "^26.1.0", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.1.0", + "jest-environment-node": "^26.1.0", + "jest-get-type": "^26.0.0", + "jest-jasmine2": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "micromatch": "^4.0.2", + "pretty-format": "^26.1.0" + } + }, + "jest-diff": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", + "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.0.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-each": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.1.0.tgz", + "integrity": "sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.0.0", + "jest-util": "^26.1.0", + "pretty-format": "^26.1.0" + } + }, + "jest-environment-jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz", + "integrity": "sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0", + "jsdom": "^16.2.2" + } + }, + "jest-environment-node": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.1.0.tgz", + "integrity": "sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0" + } + }, + "jest-haste-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", + "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@types/graceful-fs": "^4.1.2", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-serializer": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" + } + }, + "jest-jasmine2": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz", + "integrity": "sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.1.0", + "@jest/source-map": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.1.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.1.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-runtime": "^26.1.0", + "jest-snapshot": "^26.1.0", + "jest-util": "^26.1.0", + "pretty-format": "^26.1.0", + "throat": "^5.0.0" + } + }, + "jest-leak-detector": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz", + "integrity": "sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw==", + "dev": true, + "requires": { + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-matcher-utils": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", + "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-message-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", + "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-mock": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.1.0.tgz", + "integrity": "sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0" + } + }, + "jest-resolve": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", + "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.1", + "jest-util": "^26.1.0", + "read-pkg-up": "^7.0.1", + "resolve": "^1.17.0", + "slash": "^3.0.0" + } + }, + "jest-runner": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.1.0.tgz", + "integrity": "sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/environment": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.1.0", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-jasmine2": "^26.1.0", + "jest-leak-detector": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-resolve": "^26.1.0", + "jest-runtime": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + } + }, + "jest-runtime": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.1.0.tgz", + "integrity": "sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/globals": "^26.1.0", + "@jest/source-map": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.1.0", + "jest-haste-map": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.1.0", + "jest-snapshot": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.3.1" + } + }, + "jest-serializer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", + "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", + "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.1.0", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-resolve": "^26.1.0", + "natural-compare": "^1.4.0", + "pretty-format": "^26.1.0", + "semver": "^7.3.2" + } + }, + "jest-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", + "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-validate": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.1.0.tgz", + "integrity": "sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.0.0", + "leven": "^3.1.0", + "pretty-format": "^26.1.0" + } + }, + "jest-watcher": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.1.0.tgz", + "integrity": "sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ==", + "dev": true, + "requires": { + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "jest-util": "^26.1.0", + "string-length": "^4.0.1" + } + }, + "jest-worker": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", + "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "pretty-format": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", + "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -461,6 +1012,36 @@ "requires": { "glob": "^7.1.3" } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -500,30 +1081,30 @@ } }, "@jest/reporters": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.0.1.tgz", - "integrity": "sha512-NWWy9KwRtE1iyG/m7huiFVF9YsYv/e+mbflKRV84WDoJfBqUrNRyDbL/vFxQcYLl8IRqI4P3MgPn386x76Gf2g==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.1.0.tgz", + "integrity": "sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.2", "graceful-fs": "^4.2.4", "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", + "istanbul-lib-instrument": "^4.0.3", "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-resolve": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", "node-notifier": "^7.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", @@ -532,11 +1113,180 @@ "v8-to-istanbul": "^4.1.3" }, "dependencies": { + "@jest/console": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", + "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "jest-message-util": "^26.1.0", + "jest-util": "^26.1.0", + "slash": "^3.0.0" + } + }, + "@jest/test-result": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", + "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/transform": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", + "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.1.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.1.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", + "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-haste-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", + "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@types/graceful-fs": "^4.1.2", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-serializer": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" + } + }, + "jest-message-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", + "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-resolve": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", + "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.1", + "jest-util": "^26.1.0", + "read-pkg-up": "^7.0.1", + "resolve": "^1.17.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", + "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4" + } + }, + "jest-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", + "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-worker": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", + "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } } } }, @@ -4478,28 +5228,649 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.1.0.tgz", + "integrity": "sha512-LIti8jppw5BcQvmNJe4w2g1N/3V68HUfAv9zDVm7v+VAtQulGhH0LnmmiVkbNE4M4I43Bj2fXPiBGKt26k9tHw==", + "dev": true, + "requires": { + "@jest/core": "^26.1.0", + "import-local": "^3.0.2", + "jest-cli": "^26.1.0" + }, + "dependencies": { + "@jest/console": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", + "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "jest-message-util": "^26.1.0", + "jest-util": "^26.1.0", + "slash": "^3.0.0" + } + }, + "@jest/environment": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.1.0.tgz", + "integrity": "sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA==", + "dev": true, + "requires": { + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0" + } + }, + "@jest/fake-timers": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.1.0.tgz", + "integrity": "sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@sinonjs/fake-timers": "^6.0.1", + "jest-message-util": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0" + } + }, + "@jest/globals": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.1.0.tgz", + "integrity": "sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/types": "^26.1.0", + "expect": "^26.1.0" + } + }, + "@jest/source-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.1.0.tgz", + "integrity": "sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA==", + "dev": true, + "requires": { + "callsites": "^3.0.0", + "graceful-fs": "^4.2.4", + "source-map": "^0.6.0" + } + }, + "@jest/test-result": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", + "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + } + }, + "@jest/test-sequencer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz", + "integrity": "sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q==", + "dev": true, + "requires": { + "@jest/test-result": "^26.1.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.1.0", + "jest-runner": "^26.1.0", + "jest-runtime": "^26.1.0" + } + }, + "@jest/transform": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", + "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/types": "^26.1.0", + "babel-plugin-istanbul": "^6.0.0", + "chalk": "^4.0.0", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.2.4", + "jest-haste-map": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-util": "^26.1.0", + "micromatch": "^4.0.2", + "pirates": "^4.0.1", + "slash": "^3.0.0", + "source-map": "^0.6.1", + "write-file-atomic": "^3.0.0" + } + }, + "@jest/types": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", + "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "babel-jest": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.1.0.tgz", + "integrity": "sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg==", + "dev": true, + "requires": { + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/babel__core": "^7.1.7", + "babel-plugin-istanbul": "^6.0.0", + "babel-preset-jest": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "slash": "^3.0.0" + } + }, + "babel-plugin-jest-hoist": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz", + "integrity": "sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw==", + "dev": true, + "requires": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", + "@types/babel__traverse": "^7.0.6" + } + }, + "babel-preset-jest": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz", + "integrity": "sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w==", + "dev": true, + "requires": { + "babel-plugin-jest-hoist": "^26.1.0", + "babel-preset-current-node-syntax": "^0.1.2" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "expect": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", + "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.0.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-regex-util": "^26.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-cli": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.1.0.tgz", + "integrity": "sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw==", + "dev": true, + "requires": { + "@jest/core": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "is-ci": "^2.0.0", + "jest-config": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "prompts": "^2.0.1", + "yargs": "^15.3.1" + } + }, + "jest-config": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.1.0.tgz", + "integrity": "sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw==", + "dev": true, + "requires": { + "@babel/core": "^7.1.0", + "@jest/test-sequencer": "^26.1.0", + "@jest/types": "^26.1.0", + "babel-jest": "^26.1.0", + "chalk": "^4.0.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.1", + "graceful-fs": "^4.2.4", + "jest-environment-jsdom": "^26.1.0", + "jest-environment-node": "^26.1.0", + "jest-get-type": "^26.0.0", + "jest-jasmine2": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "micromatch": "^4.0.2", + "pretty-format": "^26.1.0" + } + }, + "jest-diff": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", + "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.0.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-each": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.1.0.tgz", + "integrity": "sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.0.0", + "jest-util": "^26.1.0", + "pretty-format": "^26.1.0" + } + }, + "jest-environment-jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz", + "integrity": "sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0", + "jsdom": "^16.2.2" + } + }, + "jest-environment-node": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.1.0.tgz", + "integrity": "sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg==", + "dev": true, + "requires": { + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/types": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-util": "^26.1.0" + } + }, + "jest-haste-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", + "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@types/graceful-fs": "^4.1.2", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-serializer": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" + } + }, + "jest-jasmine2": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz", + "integrity": "sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ==", + "dev": true, + "requires": { + "@babel/traverse": "^7.1.0", + "@jest/environment": "^26.1.0", + "@jest/source-map": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "co": "^4.6.0", + "expect": "^26.1.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^26.1.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-runtime": "^26.1.0", + "jest-snapshot": "^26.1.0", + "jest-util": "^26.1.0", + "pretty-format": "^26.1.0", + "throat": "^5.0.0" + } + }, + "jest-leak-detector": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz", + "integrity": "sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw==", + "dev": true, + "requires": { + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-matcher-utils": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", + "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-message-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", + "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-mock": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.1.0.tgz", + "integrity": "sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0" + } + }, + "jest-resolve": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", + "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.1", + "jest-util": "^26.1.0", + "read-pkg-up": "^7.0.1", + "resolve": "^1.17.0", + "slash": "^3.0.0" + } + }, + "jest-runner": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.1.0.tgz", + "integrity": "sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/environment": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "jest-config": "^26.1.0", + "jest-docblock": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-jasmine2": "^26.1.0", + "jest-leak-detector": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-resolve": "^26.1.0", + "jest-runtime": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "source-map-support": "^0.5.6", + "throat": "^5.0.0" + } + }, + "jest-runtime": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.1.0.tgz", + "integrity": "sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA==", + "dev": true, + "requires": { + "@jest/console": "^26.1.0", + "@jest/environment": "^26.1.0", + "@jest/fake-timers": "^26.1.0", + "@jest/globals": "^26.1.0", + "@jest/source-map": "^26.1.0", + "@jest/test-result": "^26.1.0", + "@jest/transform": "^26.1.0", + "@jest/types": "^26.1.0", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.4", + "jest-config": "^26.1.0", + "jest-haste-map": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-mock": "^26.1.0", + "jest-regex-util": "^26.0.0", + "jest-resolve": "^26.1.0", + "jest-snapshot": "^26.1.0", + "jest-util": "^26.1.0", + "jest-validate": "^26.1.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0", + "yargs": "^15.3.1" + } + }, + "jest-serializer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", + "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", + "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.1.0", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-resolve": "^26.1.0", + "natural-compare": "^1.4.0", + "pretty-format": "^26.1.0", + "semver": "^7.3.2" + } + }, + "jest-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", + "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-validate": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.1.0.tgz", + "integrity": "sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "camelcase": "^6.0.0", + "chalk": "^4.0.0", + "jest-get-type": "^26.0.0", + "leven": "^3.1.0", + "pretty-format": "^26.1.0" + } + }, + "jest-worker": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", + "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "pretty-format": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", + "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, "supports-color": { @@ -4510,87 +5881,45 @@ "requires": { "has-flag": "^4.0.0" } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.0.1.tgz", - "integrity": "sha512-29Q54kn5Bm7ZGKIuH2JRmnKl85YRigp0o0asTc6Sb6l2ch1DCXIeZTLLFy9ultJvhkTqbswF5DEx4+RlkmCxWg==", - "dev": true, - "requires": { - "@jest/core": "^26.0.1", - "import-local": "^3.0.2", - "jest-cli": "^26.0.1" - }, - "dependencies": { - "jest-cli": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.0.1.tgz", - "integrity": "sha512-pFLfSOBcbG9iOZWaMK4Een+tTxi/Wcm34geqZEqrst9cZDkTQ1LZ2CnBrTlHWuYAiTMFr0EQeK52ScyFU8wK+w==", + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "requires": { - "@jest/core": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "is-ci": "^2.0.0", - "jest-config": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", - "prompts": "^2.0.1", - "yargs": "^15.3.1" + "isexe": "^2.0.0" } } } }, "jest-changed-files": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.0.1.tgz", - "integrity": "sha512-q8LP9Sint17HaE2LjxQXL+oYWW/WeeXMPE2+Op9X3mY8IEGFVc14xRxFjUuXUbcPAlDLhtWdIEt59GdQbn76Hw==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.1.0.tgz", + "integrity": "sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.1.0", "execa": "^4.0.0", "throat": "^5.0.0" }, "dependencies": { + "@jest/types": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", + "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -4895,14 +6224,241 @@ } }, "jest-resolve-dependencies": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.0.1.tgz", - "integrity": "sha512-9d5/RS/ft0vB/qy7jct/qAhzJsr6fRQJyGAFigK3XD4hf9kIbEH5gks4t4Z7kyMRhowU6HWm/o8ILqhaHdSqLw==", + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz", + "integrity": "sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.1.0", "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.0.1" + "jest-snapshot": "^26.1.0" + }, + "dependencies": { + "@jest/types": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", + "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^1.1.1", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + } + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "expect": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", + "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-styles": "^4.0.0", + "jest-get-type": "^26.0.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-regex-util": "^26.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "jest-diff": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", + "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "diff-sequences": "^26.0.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-haste-map": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", + "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "@types/graceful-fs": "^4.1.2", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "fsevents": "^2.1.2", + "graceful-fs": "^4.2.4", + "jest-serializer": "^26.1.0", + "jest-util": "^26.1.0", + "jest-worker": "^26.1.0", + "micromatch": "^4.0.2", + "sane": "^4.0.3", + "walker": "^1.0.7", + "which": "^2.0.2" + } + }, + "jest-matcher-utils": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", + "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "pretty-format": "^26.1.0" + } + }, + "jest-message-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", + "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/stack-utils": "^1.0.1", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.2", + "slash": "^3.0.0", + "stack-utils": "^2.0.2" + } + }, + "jest-resolve": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", + "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.1", + "jest-util": "^26.1.0", + "read-pkg-up": "^7.0.1", + "resolve": "^1.17.0", + "slash": "^3.0.0" + } + }, + "jest-serializer": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", + "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.4" + } + }, + "jest-snapshot": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", + "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0", + "@jest/types": "^26.1.0", + "@types/prettier": "^2.0.0", + "chalk": "^4.0.0", + "expect": "^26.1.0", + "graceful-fs": "^4.2.4", + "jest-diff": "^26.1.0", + "jest-get-type": "^26.0.0", + "jest-haste-map": "^26.1.0", + "jest-matcher-utils": "^26.1.0", + "jest-message-util": "^26.1.0", + "jest-resolve": "^26.1.0", + "natural-compare": "^1.4.0", + "pretty-format": "^26.1.0", + "semver": "^7.3.2" + } + }, + "jest-util": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", + "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "is-ci": "^2.0.0", + "micromatch": "^4.0.2" + } + }, + "jest-worker": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", + "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", + "dev": true, + "requires": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + } + }, + "pretty-format": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", + "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", + "dev": true, + "requires": { + "@jest/types": "^26.1.0", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^16.12.0" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } } }, "jest-runner": { @@ -6213,17 +7769,17 @@ "dev": true }, "node-notifier": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.1.tgz", - "integrity": "sha512-VkzhierE7DBmQEElhTGJIoiZa1oqRijOtgOlsXg32KrJRXsPy0NXFBqWGW/wTswnJlDCs5viRYaqWguqzsKcmg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.2.tgz", + "integrity": "sha512-ux+n4hPVETuTL8+daJXTOC6uKLgMsl1RYfFv7DKRzyvzBapqco0rZZ9g72ZN8VS6V+gvNYHYa/ofcCY8fkJWsA==", "dev": true, "optional": true, "requires": { "growly": "^1.3.0", - "is-wsl": "^2.1.1", - "semver": "^7.2.1", + "is-wsl": "^2.2.0", + "semver": "^7.3.2", "shellwords": "^0.1.1", - "uuid": "^7.0.3", + "uuid": "^8.2.0", "which": "^2.0.2" }, "dependencies": { @@ -9988,9 +11544,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==", "dev": true, "optional": true }, diff --git a/package.json b/package.json index 296ad39f12..22b50a23dd 100644 --- a/package.json +++ b/package.json @@ -182,7 +182,7 @@ "eslint-config-stylelint": "^12.0.0", "got": "^11.3.0", "husky": "^4.2.5", - "jest": "^26.0.1", + "jest": "^26.1.0", "jest-circus": "^26.0.1", "jest-preset-stylelint": "^3.0.0", "jest-watch-typeahead": "^0.6.0", From 2c348199235e2b2faeb61e09ada1ff0ad5955a67 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Sun, 9 Aug 2020 07:20:05 -0700 Subject: [PATCH 07/34] Add types for plugin objects (#4889) --- lib/createPlugin.js | 6 ++++-- lib/rules/index.js | 4 +++- lib/utils/checkAgainstRule.js | 2 +- types/stylelint/index.d.ts | 17 ++++++++++++++--- 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/lib/createPlugin.js b/lib/createPlugin.js index b1233ce6d7..5e9ff6b25f 100644 --- a/lib/createPlugin.js +++ b/lib/createPlugin.js @@ -1,9 +1,11 @@ 'use strict'; +/** @typedef {import('stylelint').StylelintRule} StylelintRule */ + /** * @param {string} ruleName - * @param {Function} rule - * @returns {{ruleName: string, rule: Function}} + * @param {StylelintRule} rule + * @returns {{ruleName: string, rule: StylelintRule}} */ module.exports = function (ruleName, rule) { return { diff --git a/lib/rules/index.js b/lib/rules/index.js index 4846a04021..390bb34432 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -4,7 +4,9 @@ const importLazy = require('import-lazy'); -/** @type {{[k: string]: Function}} */ +/** @typedef {import('stylelint').StylelintRule} StylelintRule */ + +/** @type {{[k: string]: StylelintRule}} */ const rules = { 'alpha-value-notation': importLazy(() => require('./alpha-value-notation'))(), 'at-rule-allowed-list': importLazy(() => require('./at-rule-allowed-list'))(), diff --git a/lib/utils/checkAgainstRule.js b/lib/utils/checkAgainstRule.js index 57775063c1..88a24d3c4a 100644 --- a/lib/utils/checkAgainstRule.js +++ b/lib/utils/checkAgainstRule.js @@ -10,7 +10,7 @@ const rules = require('../rules'); * @param {{ ruleName: string, ruleSettings: import('stylelint').StylelintConfigRuleSettings, - root: Object, + root: import('postcss').Root, }} options * @param {Function} callback * @returns {void} diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index f3f8aecfa0..197291b439 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -1,5 +1,5 @@ declare module 'stylelint' { - import { Result, ResultMessage, Syntax, WarningOptions, Warning } from 'postcss'; + import { Result, ResultMessage, Root, Syntax, WarningOptions, Warning } from 'postcss'; export type StylelintConfigExtends = string | Array; export type StylelintConfigPlugins = string | Array; @@ -106,6 +106,14 @@ declare module 'stylelint' { fix?: boolean; }; + export type StylelintPluginContext = { fix?: boolean; newline?: string }; + + export type StylelintRule = ( + primaryOption: any, + secondaryOptions: object, + context: StylelintPluginContext, + ) => (root: Root, result: PostcssResult) => Promise | void; + export type GetPostcssOptions = { code?: string; codeFilename?: string; @@ -239,9 +247,12 @@ declare module 'stylelint' { export type StylelintPublicAPI = { lint: Function; - rules: { [k: string]: any }; + rules: { [k: string]: StylelintRule }; formatters: { [k: string]: Formatter }; - createPlugin: Function; + createPlugin: ( + ruleName: string, + rule: StylelintRule, + ) => { ruleName: string; rule: StylelintRule }; createLinter: Function; utils: { report: Function; From 23c0e81c3f4f6a75a79c5bed2e66a7ae5d7a1a00 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Sun, 9 Aug 2020 15:20:27 +0100 Subject: [PATCH 08/34] Bump @stylelint/postcss-css-in-js from 0.37.1 to 0.37.2 (#4888) Bumps [@stylelint/postcss-css-in-js](https://github.com/stylelint/postcss-css-in-js) from 0.37.1 to 0.37.2. - [Release notes](https://github.com/stylelint/postcss-css-in-js/releases) - [Changelog](https://github.com/stylelint/postcss-css-in-js/blob/master/CHANGELOG.md) - [Commits](https://github.com/stylelint/postcss-css-in-js/compare/0.37.1...0.37.2) Signed-off-by: dependabot-preview[bot] Co-authored-by: dependabot-preview[bot] <27856297+dependabot-preview[bot]@users.noreply.github.com> --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0792c3c655..e3cd564a1e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1442,9 +1442,9 @@ } }, "@stylelint/postcss-css-in-js": { - "version": "0.37.1", - "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.1.tgz", - "integrity": "sha512-UMf2Rni3JGKi3ZwYRGMYJ5ipOA5ENJSKMtYA/pE1ZLURwdh7B5+z2r73RmWvub+N0UuH1Lo+TGfCgYwPvqpXNw==", + "version": "0.37.2", + "resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz", + "integrity": "sha512-nEhsFoJurt8oUmieT8qy4nk81WRHmJynmVwn/Vts08PL9fhgIsMhk1GId5yAN643OzqEEb5S/6At2TZW7pqPDA==", "requires": { "@babel/core": ">=7.9.0" } diff --git a/package.json b/package.json index 22b50a23dd..707f2ebb41 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ ] }, "dependencies": { - "@stylelint/postcss-css-in-js": "^0.37.1", + "@stylelint/postcss-css-in-js": "^0.37.2", "@stylelint/postcss-markdown": "^0.36.1", "autoprefixer": "^9.8.2", "balanced-match": "^1.0.0", From 53f5c1848863c7c49b2d689b72dad5ee17e3abbb Mon Sep 17 00:00:00 2001 From: Yevgeny Petukhov Date: Sun, 9 Aug 2020 19:41:00 +0300 Subject: [PATCH 09/34] Add autofix to *-no-vendor rules (#4859) --- docs/user-guide/rules/list.md | 10 +++++----- lib/rules/at-rule-no-vendor-prefix/README.md | 2 ++ .../at-rule-no-vendor-prefix/__tests__/index.js | 6 ++++++ lib/rules/at-rule-no-vendor-prefix/index.js | 8 +++++++- .../README.md | 2 ++ .../__tests__/index.js | 13 ++++++++++++- .../media-feature-name-no-vendor-prefix/index.js | 10 ++++++++-- lib/rules/property-no-vendor-prefix/README.md | 2 ++ .../property-no-vendor-prefix/__tests__/index.js | 16 ++++++++++++++++ lib/rules/property-no-vendor-prefix/index.js | 8 +++++++- lib/rules/selector-no-vendor-prefix/README.md | 2 ++ .../selector-no-vendor-prefix/__tests__/index.js | 10 ++++++++++ lib/rules/selector-no-vendor-prefix/index.js | 8 +++++++- lib/rules/value-no-vendor-prefix/README.md | 2 ++ .../value-no-vendor-prefix/__tests__/index.js | 16 ++++++++++++++++ lib/rules/value-no-vendor-prefix/index.js | 8 +++++++- lib/utils/isAutoprefixable.js | 9 +++++++++ 17 files changed, 120 insertions(+), 12 deletions(-) diff --git a/docs/user-guide/rules/list.md b/docs/user-guide/rules/list.md index 2fb3483afa..6cd7c29dd7 100644 --- a/docs/user-guide/rules/list.md +++ b/docs/user-guide/rules/list.md @@ -130,7 +130,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Value -- [`value-no-vendor-prefix`](../../../lib/rules/value-no-vendor-prefix/README.md): Disallow vendor prefixes for values. +- [`value-no-vendor-prefix`](../../../lib/rules/value-no-vendor-prefix/README.md): Disallow vendor prefixes for values (Autofixable). ### Custom property @@ -140,7 +140,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`property-allowed-list`](../../../lib/rules/property-allowed-list/README.md): Specify a list of allowed properties. - [`property-disallowed-list`](../../../lib/rules/property-disallowed-list/README.md): Specify a list of disallowed properties. -- [`property-no-vendor-prefix`](../../../lib/rules/property-no-vendor-prefix/README.md): Disallow vendor prefixes for properties. +- [`property-no-vendor-prefix`](../../../lib/rules/property-no-vendor-prefix/README.md): Disallow vendor prefixes for properties (Autofixable). ### Declaration @@ -175,7 +175,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`selector-max-universal`](../../../lib/rules/selector-max-universal/README.md): Limit the number of universal selectors in a selector. - [`selector-nested-pattern`](../../../lib/rules/selector-nested-pattern/README.md): Specify a pattern for the selectors of rules nested within rules. - [`selector-no-qualifying-type`](../../../lib/rules/selector-no-qualifying-type/README.md): Disallow qualifying a selector by type. -- [`selector-no-vendor-prefix`](../../../lib/rules/selector-no-vendor-prefix/README.md): Disallow vendor prefixes for selectors. +- [`selector-no-vendor-prefix`](../../../lib/rules/selector-no-vendor-prefix/README.md): Disallow vendor prefixes for selectors (Autofixable). - [`selector-pseudo-class-allowed-list`](../../../lib/rules/selector-pseudo-class-allowed-list/README.md): Specify a list of allowed pseudo-class selectors. - [`selector-pseudo-class-disallowed-list`](../../../lib/rules/selector-pseudo-class-disallowed-list/README.md): Specify a list of disallowed pseudo-class selectors. - [`selector-pseudo-element-allowed-list`](../../../lib/rules/selector-pseudo-element-allowed-list/README.md): Specify a list of allowed pseudo-element selectors. @@ -186,7 +186,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`media-feature-name-allowed-list`](../../../lib/rules/media-feature-name-allowed-list/README.md): Specify a list of allowed media feature names. - [`media-feature-name-disallowed-list`](../../../lib/rules/media-feature-name-disallowed-list/README.md): Specify a list of disallowed media feature names. -- [`media-feature-name-no-vendor-prefix`](../../../lib/rules/media-feature-name-no-vendor-prefix/README.md): Disallow vendor prefixes for media feature names. +- [`media-feature-name-no-vendor-prefix`](../../../lib/rules/media-feature-name-no-vendor-prefix/README.md): Disallow vendor prefixes for media feature names (Autofixable). - [`media-feature-name-value-allowed-list`](../../../lib/rules/media-feature-name-value-allowed-list/README.md): Specify a list of allowed media feature name and value pairs. ### Custom media @@ -197,7 +197,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`at-rule-allowed-list`](../../../lib/rules/at-rule-allowed-list/README.md): Specify a list of allowed at-rules. - [`at-rule-disallowed-list`](../../../lib/rules/at-rule-disallowed-list/README.md): Specify a list of disallowed at-rules. -- [`at-rule-no-vendor-prefix`](../../../lib/rules/at-rule-no-vendor-prefix/README.md): Disallow vendor prefixes for at-rules. +- [`at-rule-no-vendor-prefix`](../../../lib/rules/at-rule-no-vendor-prefix/README.md): Disallow vendor prefixes for at-rules (Autofixable). - [`at-rule-property-required-list`](../../../lib/rules/at-rule-property-required-list/README.md): Specify a list of required properties for an at-rule. ### Comment diff --git a/lib/rules/at-rule-no-vendor-prefix/README.md b/lib/rules/at-rule-no-vendor-prefix/README.md index a84d210638..b39d3de552 100644 --- a/lib/rules/at-rule-no-vendor-prefix/README.md +++ b/lib/rules/at-rule-no-vendor-prefix/README.md @@ -9,6 +9,8 @@ Disallow vendor prefixes for at-rules. * This prefix */ ``` +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/at-rule-no-vendor-prefix/__tests__/index.js b/lib/rules/at-rule-no-vendor-prefix/__tests__/index.js index 37622f06af..006f727fda 100644 --- a/lib/rules/at-rule-no-vendor-prefix/__tests__/index.js +++ b/lib/rules/at-rule-no-vendor-prefix/__tests__/index.js @@ -5,6 +5,7 @@ const { messages, ruleName } = require('..'); testRule({ ruleName, config: [true], + fix: true, accept: [ { @@ -18,22 +19,27 @@ testRule({ reject: [ { code: '@-webkit-keyframes { 0% { top: 0; } }', + fixed: '@keyframes { 0% { top: 0; } }', message: messages.rejected('-webkit-keyframes'), }, { code: '@-wEbKiT-kEyFrAmEs { 0% { top: 0; } }', + fixed: '@kEyFrAmEs { 0% { top: 0; } }', message: messages.rejected('-wEbKiT-kEyFrAmEs'), }, { code: '@-WEBKIT-KEYFRAMES { 0% { top: 0; } }', + fixed: '@KEYFRAMES { 0% { top: 0; } }', message: messages.rejected('-WEBKIT-KEYFRAMES'), }, { code: '@-moz-keyframes { 0% { top: 0; } }', + fixed: '@keyframes { 0% { top: 0; } }', message: messages.rejected('-moz-keyframes'), }, { code: '@-ms-viewport { orientation: landscape; }', + fixed: '@viewport { orientation: landscape; }', message: messages.rejected('-ms-viewport'), }, ], diff --git a/lib/rules/at-rule-no-vendor-prefix/index.js b/lib/rules/at-rule-no-vendor-prefix/index.js index 810b94c356..c3036f1974 100644 --- a/lib/rules/at-rule-no-vendor-prefix/index.js +++ b/lib/rules/at-rule-no-vendor-prefix/index.js @@ -14,7 +14,7 @@ const messages = ruleMessages(ruleName, { rejected: (p) => `Unexpected vendor-prefixed at-rule "@${p}"`, }); -function rule(actual) { +function rule(actual, options, context) { return function (root, result) { const validOptions = validateOptions(result, ruleName, { actual }); @@ -37,6 +37,12 @@ function rule(actual) { return; } + if (context.fix) { + atRule.name = isAutoprefixable.unprefix(atRule.name); + + return; + } + report({ message: messages.rejected(name), node: atRule, diff --git a/lib/rules/media-feature-name-no-vendor-prefix/README.md b/lib/rules/media-feature-name-no-vendor-prefix/README.md index 53ec93df7b..91c113cf5f 100644 --- a/lib/rules/media-feature-name-no-vendor-prefix/README.md +++ b/lib/rules/media-feature-name-no-vendor-prefix/README.md @@ -11,6 +11,8 @@ Disallow vendor prefixes for media feature names. Right now this rule simply checks for prefixed _resolutions_. +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/media-feature-name-no-vendor-prefix/__tests__/index.js b/lib/rules/media-feature-name-no-vendor-prefix/__tests__/index.js index aaad9dff7f..89a70ff5c9 100644 --- a/lib/rules/media-feature-name-no-vendor-prefix/__tests__/index.js +++ b/lib/rules/media-feature-name-no-vendor-prefix/__tests__/index.js @@ -5,6 +5,7 @@ const { messages, ruleName } = require('..'); testRule({ ruleName, config: [true], + fix: true, accept: [ { @@ -13,47 +14,57 @@ testRule({ { code: '@media (device-pixel-ratio: 2) {}', }, + { + code: '@media (min-device-pixel-ratio: 2) {}', + }, ], reject: [ { code: '@media (-webkit-min-device-pixel-ratio: 1) {}', + fixed: '@media (min-device-pixel-ratio: 1) {}', message: messages.rejected, line: 1, column: 9, }, { code: '@media (-wEbKiT-mIn-DeViCe-PiXeL-rAtIo: 1) {}', + fixed: '@media (mIn-DeViCe-PiXeL-rAtIo: 1) {}', message: messages.rejected, line: 1, column: 9, }, { code: '@media (-WEBKIT-MIN-DEVICE-PIXEL-RATIO: 1) {}', + fixed: '@media (MIN-DEVICE-PIXEL-RATIO: 1) {}', message: messages.rejected, line: 1, column: 9, }, { code: '@media\n\t(min--moz-device-pixel-ratio: 1) {}', + fixed: '@media\n\t(min-device-pixel-ratio: 1) {}', message: messages.rejected, line: 2, - column: 3, + column: 6, }, { code: '@media (-o-max-device-pixel-ratio: 1/1) {}', + fixed: '@media (max-device-pixel-ratio: 1/1) {}', message: messages.rejected, line: 1, column: 11, }, { code: '@media (-o-max-device-pixel-ratio > 1) {}', + fixed: '@media (max-device-pixel-ratio > 1) {}', message: messages.rejected, line: 1, column: 9, }, { code: '@media (1 < -o-max-device-pixel-ratio < 2) {}', + fixed: '@media (1 < max-device-pixel-ratio < 2) {}', message: messages.rejected, line: 1, column: 13, diff --git a/lib/rules/media-feature-name-no-vendor-prefix/index.js b/lib/rules/media-feature-name-no-vendor-prefix/index.js index 5c777335d4..bfdbd2b6d4 100644 --- a/lib/rules/media-feature-name-no-vendor-prefix/index.js +++ b/lib/rules/media-feature-name-no-vendor-prefix/index.js @@ -13,7 +13,7 @@ const messages = ruleMessages(ruleName, { rejected: 'Unexpected vendor-prefix', }); -function rule(actual) { +function rule(actual, options, context) { return (root, result) => { const validOptions = validateOptions(result, ruleName, { actual }); @@ -28,12 +28,18 @@ function rule(actual) { return; } - const matches = atRule.toString().match(/[a-z-]+device-pixel-ratio/gi); + const matches = atRule.toString().match(/-[a-z-]+device-pixel-ratio/gi); if (!matches) { return; } + if (context.fix) { + atRule.params = isAutoprefixable.unprefix(atRule.params); + + return; + } + matches.forEach((match) => { report({ message: messages.rejected, diff --git a/lib/rules/property-no-vendor-prefix/README.md b/lib/rules/property-no-vendor-prefix/README.md index 89f237302b..7833e0f16f 100644 --- a/lib/rules/property-no-vendor-prefix/README.md +++ b/lib/rules/property-no-vendor-prefix/README.md @@ -11,6 +11,8 @@ a { -webkit-transform: scale(1); } This rule does not blanketly condemn vendor prefixes. Instead, it uses [Autoprefixer's](https://github.com/postcss/autoprefixer) up-to-date data (from [caniuse.com](http://caniuse.com/)) to know whether a vendor prefix should cause a violation or not. _If you've included a vendor prefixed property that has a standard alternative, one that Autoprefixer could take care of for you, this rule will complain about it_. If, however, you use a non-standard vendor-prefixed property, one that Autoprefixer would ignore and could not provide (such as `-webkit-touch-callout`), this rule will ignore it. +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/property-no-vendor-prefix/__tests__/index.js b/lib/rules/property-no-vendor-prefix/__tests__/index.js index d81b624e8a..424c03e553 100644 --- a/lib/rules/property-no-vendor-prefix/__tests__/index.js +++ b/lib/rules/property-no-vendor-prefix/__tests__/index.js @@ -5,6 +5,7 @@ const { messages, ruleName } = require('..'); testRule({ ruleName, config: [true], + fix: true, accept: [ { @@ -40,48 +41,56 @@ testRule({ reject: [ { code: 'a { -webkit-transform: scale(1); }', + fixed: 'a { transform: scale(1); }', message: messages.rejected('-webkit-transform'), line: 1, column: 5, }, { code: 'a { -wEbKiT-tRaNsFoRm: scale(1); }', + fixed: 'a { tRaNsFoRm: scale(1); }', message: messages.rejected('-wEbKiT-tRaNsFoRm'), line: 1, column: 5, }, { code: 'a { -WEBKIT-TRANSFORM: scale(1); }', + fixed: 'a { TRANSFORM: scale(1); }', message: messages.rejected('-WEBKIT-TRANSFORM'), line: 1, column: 5, }, { code: 'a { -webkit-transform: scale(1); transform: scale(1); }', + fixed: 'a { transform: scale(1); transform: scale(1); }', message: messages.rejected('-webkit-transform'), line: 1, column: 5, }, { code: 'a { transform: scale(1); -webkit-transform: scale(1); }', + fixed: 'a { transform: scale(1); transform: scale(1); }', message: messages.rejected('-webkit-transform'), line: 1, column: 26, }, { code: 'a { -moz-transition: all 3s; }', + fixed: 'a { transition: all 3s; }', message: messages.rejected('-moz-transition'), line: 1, column: 5, }, { code: 'a { -moz-columns: 2; }', + fixed: 'a { columns: 2; }', message: messages.rejected('-moz-columns'), line: 1, column: 5, }, { code: 'a { -o-columns: 2; }', + fixed: 'a { columns: 2; }', description: 'mistaken prefix', message: messages.rejected('-o-columns'), line: 1, @@ -89,6 +98,7 @@ testRule({ }, { code: 'a { -ms-interpolation-mode: nearest-neighbor; }', + fixed: 'a { interpolation-mode: nearest-neighbor; }', description: '"hack" prefix', message: messages.rejected('-ms-interpolation-mode'), line: 1, @@ -100,6 +110,7 @@ testRule({ testRule({ ruleName, config: [true, { ignoreProperties: ['transform', 'columns', '/^animation-/i'] }], + fix: true, accept: [ { @@ -121,18 +132,21 @@ testRule({ reject: [ { code: 'a { -webkit-border-radius: 10px; }', + fixed: 'a { border-radius: 10px; }', message: messages.rejected('-webkit-border-radius'), line: 1, column: 5, }, { code: 'a { -moz-background-size: cover; }', + fixed: 'a { background-size: cover; }', message: messages.rejected('-moz-background-size'), line: 1, column: 5, }, { code: 'a { -WEBKIT-tranSFoRM: translateY(-50%); }', + fixed: 'a { tranSFoRM: translateY(-50%); }', message: messages.rejected('-WEBKIT-tranSFoRM'), line: 1, column: 5, @@ -143,6 +157,7 @@ testRule({ testRule({ ruleName, config: [true, { ignoreProperties: [/^animation-/i] }], + fix: true, accept: [ { @@ -152,6 +167,7 @@ testRule({ reject: [ { code: 'a { -webkit-border-radius: 10px; }', + fixed: 'a { border-radius: 10px; }', message: messages.rejected('-webkit-border-radius'), line: 1, column: 5, diff --git a/lib/rules/property-no-vendor-prefix/index.js b/lib/rules/property-no-vendor-prefix/index.js index 0771731993..d5fbcc0969 100644 --- a/lib/rules/property-no-vendor-prefix/index.js +++ b/lib/rules/property-no-vendor-prefix/index.js @@ -16,7 +16,7 @@ const messages = ruleMessages(ruleName, { rejected: (property) => `Unexpected vendor-prefix "${property}"`, }); -function rule(actual, options) { +function rule(actual, options, context) { return (root, result) => { const validOptions = validateOptions( result, @@ -55,6 +55,12 @@ function rule(actual, options) { return; } + if (context.fix) { + decl.prop = isAutoprefixable.unprefix(decl.prop); + + return; + } + report({ message: messages.rejected(prop), node: decl, diff --git a/lib/rules/selector-no-vendor-prefix/README.md b/lib/rules/selector-no-vendor-prefix/README.md index adf3b0b6ce..8555ec6d10 100644 --- a/lib/rules/selector-no-vendor-prefix/README.md +++ b/lib/rules/selector-no-vendor-prefix/README.md @@ -11,6 +11,8 @@ input::-moz-placeholder {} This rule does not blanketly condemn vendor prefixes. Instead, it uses [Autoprefixer's](https://github.com/postcss/autoprefixer) up-to-date data (from [caniuse.com](http://caniuse.com/)) to know whether a vendor prefix should cause a violation or not. _If you've included a vendor prefixed selector that has a standard alternative, one that Autoprefixer could take care of for you, this rule will complain about it_. If, however, you use a non-standard vendor-prefixed selector, one that Autoprefixer would ignore and could not provide, this rule will ignore it. +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/selector-no-vendor-prefix/__tests__/index.js b/lib/rules/selector-no-vendor-prefix/__tests__/index.js index 3fa68a4d2b..f22ea1897c 100644 --- a/lib/rules/selector-no-vendor-prefix/__tests__/index.js +++ b/lib/rules/selector-no-vendor-prefix/__tests__/index.js @@ -5,6 +5,7 @@ const { messages, ruleName } = require('..'); testRule({ ruleName, config: [true], + fix: true, accept: [ { @@ -46,42 +47,49 @@ testRule({ reject: [ { code: ':-webkit-full-screen a {}', + fixed: ':full-screen a {}', message: messages.rejected(':-webkit-full-screen'), line: 1, column: 1, }, { code: ':-wEbKiT-fUlL-sCrEeN a {}', + fixed: ':fUlL-sCrEeN a {}', message: messages.rejected(':-wEbKiT-fUlL-sCrEeN'), line: 1, column: 1, }, { code: ':-WEBKIT-FULL-SCREEN a {}', + fixed: ':FULL-SCREEN a {}', message: messages.rejected(':-WEBKIT-FULL-SCREEN'), line: 1, column: 1, }, { code: 'body, :-ms-fullscreen a {}', + fixed: 'body, :fullscreen a {}', message: messages.rejected(':-ms-fullscreen'), line: 1, column: 7, }, { code: 'input::-moz-placeholder, input::placeholder { color: pink; }', + fixed: 'input::placeholder, input::placeholder { color: pink; }', message: messages.rejected('::-moz-placeholder'), line: 1, column: 6, }, { code: 'input::-moz-placeholder { color: pink; }', + fixed: 'input::placeholder { color: pink; }', message: messages.rejected('::-moz-placeholder'), line: 1, column: 6, }, { code: 'input::-webkit-input-placeholder { color: pink; }', + fixed: 'input::input-placeholder { color: pink; }', message: messages.rejected('::-webkit-input-placeholder'), }, ], @@ -90,6 +98,7 @@ testRule({ testRule({ ruleName, config: [true, { ignoreSelectors: ['::-webkit-input-placeholder', '/-moz-.*/'] }], + fix: true, accept: [ { @@ -103,6 +112,7 @@ testRule({ reject: [ { code: 'input::-ms-input-placeholder { color: pink; }', + fixed: 'input::input-placeholder { color: pink; }', message: messages.rejected('::-ms-input-placeholder'), }, ], diff --git a/lib/rules/selector-no-vendor-prefix/index.js b/lib/rules/selector-no-vendor-prefix/index.js index 4e37e01865..9f768f586e 100644 --- a/lib/rules/selector-no-vendor-prefix/index.js +++ b/lib/rules/selector-no-vendor-prefix/index.js @@ -17,7 +17,7 @@ const messages = ruleMessages(ruleName, { rejected: (selector) => `Unexpected vendor-prefix "${selector}"`, }); -function rule(actual, options) { +function rule(actual, options, context) { return (root, result) => { const validOptions = validateOptions( result, @@ -50,6 +50,12 @@ function rule(actual, options) { return; } + if (context.fix) { + rule.selector = isAutoprefixable.unprefix(rule.selector); + + return; + } + report({ result, ruleName, diff --git a/lib/rules/value-no-vendor-prefix/README.md b/lib/rules/value-no-vendor-prefix/README.md index 08a8c10f1e..9a08e40582 100644 --- a/lib/rules/value-no-vendor-prefix/README.md +++ b/lib/rules/value-no-vendor-prefix/README.md @@ -11,6 +11,8 @@ a { display: -webkit-flex; } This rule will only complain for prefixed _standard_ values, and not for prefixed _proprietary_ or _unknown_ ones. +The [`fix` option](../../../docs/user-guide/usage/options.md#fix) can automatically fix all of the problems reported by this rule. + ## Options ### `true` diff --git a/lib/rules/value-no-vendor-prefix/__tests__/index.js b/lib/rules/value-no-vendor-prefix/__tests__/index.js index 8c9ef0e663..39934295e1 100644 --- a/lib/rules/value-no-vendor-prefix/__tests__/index.js +++ b/lib/rules/value-no-vendor-prefix/__tests__/index.js @@ -5,6 +5,7 @@ const { messages, ruleName } = require('..'); testRule({ ruleName, config: [true], + fix: true, accept: [ { @@ -33,54 +34,63 @@ testRule({ reject: [ { code: '.foo { display: -webkit-flex; }', + fixed: '.foo { display: flex; }', message: messages.rejected('-webkit-flex'), line: 1, column: 17, }, { code: '.foo { display: -wEbKiT-fLeX; }', + fixed: '.foo { display: fLeX; }', message: messages.rejected('-wEbKiT-fLeX'), line: 1, column: 17, }, { code: '.foo { display: -WEBKIT-FLEX; }', + fixed: '.foo { display: FLEX; }', message: messages.rejected('-WEBKIT-FLEX'), line: 1, column: 17, }, { code: '.foo { dIsPlAy: -webkit-flex; }', + fixed: '.foo { dIsPlAy: flex; }', message: messages.rejected('-webkit-flex'), line: 1, column: 17, }, { code: '.foo { DISPLAY: -webkit-flex; }', + fixed: '.foo { DISPLAY: flex; }', message: messages.rejected('-webkit-flex'), line: 1, column: 17, }, { code: '.foo { color: pink; display: -webkit-flex; }', + fixed: '.foo { color: pink; display: flex; }', message: messages.rejected('-webkit-flex'), line: 1, column: 30, }, { code: '.foo { display: -webkit-box; }', + fixed: '.foo { display: box; }', message: messages.rejected('-webkit-box'), line: 1, column: 17, }, { code: '.foo { background: -webkit-linear-gradient(bottom, #000, #fff); }', + fixed: '.foo { background: linear-gradient(bottom, #000, #fff); }', message: messages.rejected('-webkit-linear-gradient'), line: 1, column: 20, }, { code: '.foo { max-width: -moz-max-content; }', + fixed: '.foo { max-width: max-content; }', message: messages.rejected('-moz-max-content'), line: 1, column: 19, @@ -92,6 +102,7 @@ testRule({ ruleName, config: [true], syntax: 'scss', + fix: true, accept: [ { @@ -113,6 +124,7 @@ testRule({ ruleName, config: [true], syntax: 'less', + fix: true, accept: [ { @@ -127,6 +139,7 @@ testRule({ testRule({ ruleName, config: [true, { ignoreValues: ['grab', 'max-content', '/^linear-/'] }], + fix: true, accept: [ { @@ -142,18 +155,21 @@ testRule({ reject: [ { code: '.foo { display: -webkit-flex; }', + fixed: '.foo { display: flex; }', message: messages.rejected('-webkit-flex'), line: 1, column: 17, }, { code: '.foo { display: -wEbKiT-fLeX; }', + fixed: '.foo { display: fLeX; }', message: messages.rejected('-wEbKiT-fLeX'), line: 1, column: 17, }, { code: '.foo { display: -WEBKIT-FLEX; }', + fixed: '.foo { display: FLEX; }', message: messages.rejected('-WEBKIT-FLEX'), line: 1, column: 17, diff --git a/lib/rules/value-no-vendor-prefix/index.js b/lib/rules/value-no-vendor-prefix/index.js index f82718d921..ba4b3609c3 100644 --- a/lib/rules/value-no-vendor-prefix/index.js +++ b/lib/rules/value-no-vendor-prefix/index.js @@ -21,7 +21,7 @@ const messages = ruleMessages(ruleName, { const valuePrefixes = ['-webkit-', '-moz-', '-ms-', '-o-']; -function rule(actual, options) { +function rule(actual, options, context) { return (root, result) => { const validOptions = validateOptions( result, @@ -67,6 +67,12 @@ function rule(actual, options) { return; } + if (context.fix) { + decl.value = isAutoprefixable.unprefix(decl.value); + + return; + } + report({ message: messages.rejected(fullIdentifier), node: decl, diff --git a/lib/utils/isAutoprefixable.js b/lib/utils/isAutoprefixable.js index 521aee12bb..051e23ea32 100644 --- a/lib/utils/isAutoprefixable.js +++ b/lib/utils/isAutoprefixable.js @@ -74,4 +74,13 @@ module.exports = { }) ); }, + + /** + * + * @param {string} value + * @returns {string} + */ + unprefix(value) { + return value.replace(/-\w+-/, ''); + }, }; From 1e52251a5effa519ccdd6775d4f730386c60c3bf Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Sun, 9 Aug 2020 17:45:38 +0100 Subject: [PATCH 10/34] Update CHANGELOG.md --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9d52d923b..7afc46e144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,11 @@ All notable changes to this project are documented in this file. - Added: syntax object acceptance to `customSyntax` option ([#4839](https://github.com/stylelint/stylelint/pull/4839)). - Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). - Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). -- Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). +- Added: `*-no-vendor-prefix` autofix ([#4859](https://github.com/stylelint/stylelint/pull/4859)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). +- Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). - Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). -- Fixed: false negatives for `where`, `is`, `nth-child` and `nth-last-child` in `selector-max-*` rules (except selector-max-type) ([#4842](https://github.com/stylelint/stylelint/pull/4842)). +- Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). ## 13.6.1 From 9e1edfac44af9cace9168eb38918674c44bb6782 Mon Sep 17 00:00:00 2001 From: Van Nguyen Date: Tue, 11 Aug 2020 00:21:42 +1000 Subject: [PATCH 11/34] Fix TypeError for custom properties fallback in length-zero-no-unit (#4860) --- lib/rules/length-zero-no-unit/__tests__/index.js | 11 +++++++++++ lib/rules/length-zero-no-unit/index.js | 4 ++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/rules/length-zero-no-unit/__tests__/index.js b/lib/rules/length-zero-no-unit/__tests__/index.js index e0ffd733ad..6efb8e176e 100644 --- a/lib/rules/length-zero-no-unit/__tests__/index.js +++ b/lib/rules/length-zero-no-unit/__tests__/index.js @@ -237,6 +237,10 @@ testRule({ code: 'a { font: normal normal 400 16px /0px cursive; }', description: 'ignore line-height in font declaration', }, + { + code: 'a { font: var(--foo, normal normal 400 16px/0px cursive); }', + description: 'ignore line-height in font declaration within var function', + }, { code: 'a { font: normal normal 400 1.2em cursive; }', description: 'do not fail if no line-height in font declaration', @@ -530,6 +534,13 @@ testRule({ line: 1, column: 30, }, + { + code: 'a { margin: var(--foo, 0px); }', + fixed: 'a { margin: var(--foo, 0); }', + message: messages.rejected, + line: 1, + column: 25, + }, ], }); diff --git a/lib/rules/length-zero-no-unit/index.js b/lib/rules/length-zero-no-unit/index.js index 40acda60a3..6145771b27 100644 --- a/lib/rules/length-zero-no-unit/index.js +++ b/lib/rules/length-zero-no-unit/index.js @@ -40,9 +40,9 @@ function rule(actual, secondary, context) { const ignorableIndexes = new Array(stringValue.length).fill(false); const parsedValue = valueParser(stringValue); - parsedValue.walk((node, nodeIndex) => { + parsedValue.walk((node, nodeIndex, nodes) => { if (decl.prop.toLowerCase() === 'font' && node.type === 'div' && node.value === '/') { - const lineHeightNode = parsedValue.nodes[nodeIndex + 1]; + const lineHeightNode = nodes[nodeIndex + 1]; const lineHeightNodeValue = valueParser.stringify(lineHeightNode); for (let i = 0; i < lineHeightNodeValue.length; i++) { From a5b8277ab5706560584ba417ce63e835b91298e5 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Mon, 10 Aug 2020 15:24:43 +0100 Subject: [PATCH 12/34] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7afc46e144..fd2dc48b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project are documented in this file. - Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). - Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). - Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). +- Fixed: `length-zero-no-unit` TypeError for custom properties fallback ([#4860](https://github.com/stylelint/stylelint/pull/4860)). ## 13.6.1 From 03f494d59e3f2500d17e3b72e11b258d650fd426 Mon Sep 17 00:00:00 2001 From: ka-weihe Date: Mon, 10 Aug 2020 16:25:05 +0200 Subject: [PATCH 13/34] faster levenshtein (#4874) --- lib/reportUnknownRuleNames.js | 4 ++-- lib/utils/checkInvalidCLIOptions.js | 4 ++-- package-lock.json | 13 +++++++++++++ package.json | 2 +- 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/reportUnknownRuleNames.js b/lib/reportUnknownRuleNames.js index e06f0f6722..6656bf5092 100644 --- a/lib/reportUnknownRuleNames.js +++ b/lib/reportUnknownRuleNames.js @@ -1,6 +1,6 @@ 'use strict'; -const leven = require('leven'); +const levenshtein = require('fastest-levenshtein'); const rules = require('./rules'); const MAX_LEVENSHTEIN_DISTANCE = 6; @@ -18,7 +18,7 @@ function extractSuggestions(ruleName) { } Object.keys(rules).forEach((existRuleName) => { - const distance = leven(existRuleName, ruleName); + const distance = levenshtein.distance(existRuleName, ruleName); if (distance <= MAX_LEVENSHTEIN_DISTANCE) { suggestions[distance - 1].push(existRuleName); diff --git a/lib/utils/checkInvalidCLIOptions.js b/lib/utils/checkInvalidCLIOptions.js index 9334ecb9e5..9bb937669b 100644 --- a/lib/utils/checkInvalidCLIOptions.js +++ b/lib/utils/checkInvalidCLIOptions.js @@ -3,7 +3,7 @@ const _ = require('lodash'); const chalk = require('chalk'); const EOL = require('os').EOL; -const leven = require('leven'); +const levenshtein = require('fastest-levenshtein'); /** * @param {{ [key: string]: { alias?: string } }} allowedOptions @@ -35,7 +35,7 @@ const suggest = (all, invalid) => { const maxThreshold = 10; for (let threshold = 1; threshold <= maxThreshold; threshold++) { - const suggestion = all.find((option) => leven(option, invalid) <= threshold); + const suggestion = all.find((option) => levenshtein.distance(option, invalid) <= threshold); if (suggestion) { return suggestion; diff --git a/package-lock.json b/package-lock.json index e3cd564a1e..6bcd99a021 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1662,6 +1662,14 @@ "@types/node": "*" } }, + "@types/leven": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@types/leven/-/leven-2.1.2.tgz", + "integrity": "sha512-/DZnNl+6YyiHG+t1EbNMBlMbrU8r1f7RWRi0kAYZYxko0hzA13IMagg9qtTL4a3SwFx4eYubZMcvYAijuKbS5A==", + "requires": { + "leven": "*" + } + }, "@types/lodash": { "version": "4.14.157", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.157.tgz", @@ -3950,6 +3958,11 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, + "fastest-levenshtein": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.9.tgz", + "integrity": "sha512-8DIQrqkmGTMfjcwiebj28Y1l6eCoLCU+TppdZa5zp5ZyNO12oUhtEEeCZjojZZarD8+peRg3CxL4Zm5BrKr9Fw==" + }, "fastq": { "version": "1.8.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.8.0.tgz", diff --git a/package.json b/package.json index 707f2ebb41..e4a591eb9d 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "cosmiconfig": "^6.0.0", "debug": "^4.1.1", "execall": "^2.0.0", + "fastest-levenshtein": "^1.0.9", "file-entry-cache": "^5.0.1", "get-stdin": "^8.0.0", "global-modules": "^2.0.0", @@ -128,7 +129,6 @@ "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "known-css-properties": "^0.19.0", - "leven": "^3.1.0", "lodash": "^4.17.19", "log-symbols": "^4.0.0", "mathml-tag-names": "^2.1.3", From 40e60cef3cd1083d3f70b19101b4e40baf97c8b0 Mon Sep 17 00:00:00 2001 From: Jennifer Thakar Date: Mon, 17 Aug 2020 14:27:09 -0700 Subject: [PATCH 14/34] Support multi-line disable descriptions (#4895) --- CHANGELOG.md | 2 ++ lib/__tests__/disableRanges.test.js | 52 +++++++++++++++++++++++++++++ lib/assignDisabledRanges.js | 51 +++++++++++++++++++++++++--- types/postcss/index.d.ts | 17 ++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fd2dc48b09..6ab07cb90f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ All notable changes to this project are documented in this file. - Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). - Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). - Fixed: `length-zero-no-unit` TypeError for custom properties fallback ([#4860](https://github.com/stylelint/stylelint/pull/4860)). +- Fixed: false negatives for `where`, `is`, `nth-child` and `nth-last-child` in `selector-max-*` rules (except selector-max-type) ([#4842](https://github.com/stylelint/stylelint/pull/4842)). +- Fixed: support for multi-line disable descriptions ([#4895](https://github.com/stylelint/stylelint/pull/4895)). ## 13.6.1 diff --git a/lib/__tests__/disableRanges.test.js b/lib/__tests__/disableRanges.test.js index fc93c29ebb..d31bea78e8 100644 --- a/lib/__tests__/disableRanges.test.js +++ b/lib/__tests__/disableRanges.test.js @@ -747,6 +747,32 @@ it('SCSS // line-disabling comment (with description)', () => { }); }); +it('SCSS // disable next-line comment (with multi-line description)', () => { + const scssSource = `a { + // stylelint-disable-next-line declaration-no-important + // -- + // Long-winded description + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 5, + end: 5, + strictStart: true, + strictEnd: true, + }, + ], + }); + }); +}); + it('Less // line-disabling comment (with description)', () => { const lessSource = `a { color: pink !important; // stylelint-disable-line declaration-no-important -- Description @@ -770,6 +796,32 @@ it('Less // line-disabling comment (with description)', () => { }); }); +it('Less // disable next-line comment (with multi-line description)', () => { + const lessSource = `a { + // stylelint-disable-next-line declaration-no-important + // -- + // Long-winded description + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(lessSource, { syntax: less, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 5, + end: 5, + strictStart: true, + strictEnd: true, + }, + ], + }); + }); +}); + function testDisableRanges(source, cb) { return postcss().use(assignDisabledRanges).process(source, { from: undefined }).then(cb); } diff --git a/lib/assignDisabledRanges.js b/lib/assignDisabledRanges.js index 31406d74b4..0f1b4352ba 100644 --- a/lib/assignDisabledRanges.js +++ b/lib/assignDisabledRanges.js @@ -9,7 +9,7 @@ const disableLineCommand = `${COMMAND_PREFIX}disable-line`; const disableNextLineCommand = `${COMMAND_PREFIX}disable-next-line`; const ALL_RULES = 'all'; -/** @typedef {import('postcss').Comment} PostcssComment */ +/** @typedef {import('postcss/lib/comment')} PostcssComment */ /** @typedef {import('postcss').Root} PostcssRoot */ /** @typedef {import('stylelint').PostcssResult} PostcssResult */ /** @typedef {import('stylelint').DisabledRangeObject} DisabledRangeObject */ @@ -53,10 +53,53 @@ module.exports = function (root, result) { }; result.stylelint.disabledRanges = disabledRanges; - root.walkComments(checkComment); + + // Work around postcss/postcss-scss#109 by merging adjacent `//` comments + // into a single node before passing to `checkComment`. + + /** @type {PostcssComment?} */ + let inlineEnd; + + root.walkComments((/** @type {PostcssComment} */ comment) => { + if (inlineEnd) { + // Ignore comments already processed by grouping with a previous one. + if (inlineEnd === comment) inlineEnd = null; + } else if (isInlineComment(comment)) { + const fullComment = comment.clone(); + let next = comment.next(); + + while (next && next.type === 'comment') { + /** @type {PostcssComment} */ + const current = next; + + if (!isInlineComment(current)) break; + + fullComment.text += `\n${current.text}`; + + if (fullComment.source && current.source) { + fullComment.source.end = current.source.end; + } + + inlineEnd = current; + next = current.next(); + } + checkComment(fullComment); + } else { + checkComment(comment); + } + }); return result; + /** + * @param {PostcssComment} comment + */ + function isInlineComment(comment) { + // We check both here because the Sass parser uses `raws.inline` to indicate + // inline comments, while the Less parser uses `inline`. + return comment.inline || comment.raws.inline; + } + /** * @param {PostcssComment} comment */ @@ -74,8 +117,8 @@ module.exports = function (root, result) { * @param {PostcssComment} comment */ function processDisableNextLineCommand(comment) { - if (comment.source && comment.source.start) { - const line = comment.source.start.line; + if (comment.source && comment.source.end) { + const line = comment.source.end.line; getCommandRules(disableNextLineCommand, comment.text).forEach((ruleName) => { disableLine(line + 1, ruleName, comment); diff --git a/types/postcss/index.d.ts b/types/postcss/index.d.ts index 17912361e6..93e6a97875 100644 --- a/types/postcss/index.d.ts +++ b/types/postcss/index.d.ts @@ -1,3 +1,20 @@ +declare module 'postcss/lib/comment' { + import { Comment, NodeRaws } from 'postcss'; + + interface NodeRawsExt extends NodeRaws { + // Used by the SCSS parser to indicate `//` comments. + inline?: boolean; + } + + interface CommentExt extends Comment { + // Used by the Less parser to indicate `//` comments. + inline?: boolean; + raws: NodeRawsExt; + } + + export = CommentExt; +} + declare module 'postcss/lib/lazy-result' { import { LazyResult, From 858dcd584224042654d80ce8fa8ad71f41f20808 Mon Sep 17 00:00:00 2001 From: Natalie Weizenbaum Date: Wed, 19 Aug 2020 00:04:34 -0700 Subject: [PATCH 15/34] Add a reportDisables secondary option (#4897) * Rename UnusedRange to DisableReportRange and .unusedRule to .rule This allows us to re-use this structure for representing errors relating to disabled that aren't specifically related to the disable being unused. * Add a reportDisables secondary option This allows config authors to specify that certain rules may not be disabled by authors. Closes #4875 * Produce different messages for different disable-level failures * Code review --- docs/developer-guide/formatters.md | 4 +- docs/user-guide/configure.md | 20 ++++ lib/__tests__/cli.test.js | 18 ++- ...config-block-no-empty-report-disables.json | 5 + .../empty-block-with-relevant-disable.css | 2 + lib/__tests__/invalidScopeDisables.test.js | 11 +- lib/__tests__/needlessDisables.test.js | 22 ++-- lib/__tests__/reportDisables.test.js | 105 ++++++++++++++++++ .../standalone-invalidScopeDisables.test.js | 2 + .../standalone-needlessDisables.test.js | 2 + .../stylelintignore.test.js | 3 + lib/cli.js | 17 ++- ...isableOptionsReportStringFormatter.test.js | 51 +++++---- .../disableOptionsReportStringFormatter.js | 5 +- lib/invalidScopeDisables.js | 4 +- lib/needlessDisables.js | 5 +- lib/prepareReturnValue.js | 2 + lib/reportDisables.js | 71 ++++++++++++ lib/utils/validateOptions.js | 2 +- .../001/__snapshots__/fs.test.js.snap | 1 + .../001/__snapshots__/no-fs.test.js.snap | 1 + .../002/__snapshots__/fs.test.js.snap | 1 + .../002/__snapshots__/no-fs.test.js.snap | 1 + .../003/__snapshots__/fs.test.js.snap | 1 + .../003/__snapshots__/no-fs.test.js.snap | 1 + types/stylelint/index.d.ts | 16 +-- 26 files changed, 314 insertions(+), 59 deletions(-) create mode 100644 lib/__tests__/fixtures/config-block-no-empty-report-disables.json create mode 100644 lib/__tests__/fixtures/empty-block-with-relevant-disable.css create mode 100644 lib/__tests__/reportDisables.test.js create mode 100644 lib/reportDisables.js diff --git a/docs/developer-guide/formatters.md b/docs/developer-guide/formatters.md index b51e1055e0..ad1b2f280d 100644 --- a/docs/developer-guide/formatters.md +++ b/docs/developer-guide/formatters.md @@ -57,7 +57,7 @@ And the second argument (`returnValue`) is an object (type `StylelintStandaloneR "ranges": [ { "start": 10, - "unusedRule": "indentation" + "rule": "indentation" } ] } @@ -69,7 +69,7 @@ And the second argument (`returnValue`) is an object (type `StylelintStandaloneR "ranges": [ { "start": 1, - "unusedRule": "color-named" + "rule": "color-named" } ] } diff --git a/docs/user-guide/configure.md b/docs/user-guide/configure.md index 38afea37d6..4811b02908 100644 --- a/docs/user-guide/configure.md +++ b/docs/user-guide/configure.md @@ -135,6 +135,26 @@ For example: Reporters may use these severity levels to display violations or exit the process differently. +### `reportDisables` + +You can set the `reportDisables` secondary option to report any disable comments for this rule, effectively disallowing authors to opt out of it. + +For example: + +```json +{ + "rules": { + "indentation": [ + 2, + { + "except": ["value"], + "reportDisables": true + } + ] + } +} +``` + ## `defaultSeverity` You can set the default severity level for all rules that do not have a severity specified in their secondary options. For example, you can set the default severity to `"warning"`: diff --git a/lib/__tests__/cli.test.js b/lib/__tests__/cli.test.js index f41b88f9e2..ba81d44264 100644 --- a/lib/__tests__/cli.test.js +++ b/lib/__tests__/cli.test.js @@ -234,7 +234,7 @@ describe('CLI', () => { expect(process.stdout.write).toHaveBeenCalledTimes(2); expect(process.stdout.write).toHaveBeenNthCalledWith( 1, - expect.stringContaining('unused rule: color-named'), + expect.stringContaining('needless disable: color-named'), ); expect(process.stdout.write).toHaveBeenNthCalledWith( 2, @@ -242,6 +242,22 @@ describe('CLI', () => { ); }); + it('reports disallowed disables', async () => { + await cli([ + '--config', + replaceBackslashes(path.join(fixturesPath, 'config-block-no-empty-report-disables.json')), + replaceBackslashes(path.join(fixturesPath, 'empty-block-with-relevant-disable.css')), + ]); + + expect(process.exitCode).toBe(2); + + expect(process.stdout.write).toHaveBeenCalledTimes(1); + expect(process.stdout.write).toHaveBeenNthCalledWith( + 1, + expect.stringContaining('forbidden disable: block-no-empty'), + ); + }); + it('--stdin', async () => { await cli(['--stdin', '--config', `${fixturesPath}/config-no-empty-source.json`]); diff --git a/lib/__tests__/fixtures/config-block-no-empty-report-disables.json b/lib/__tests__/fixtures/config-block-no-empty-report-disables.json new file mode 100644 index 0000000000..609545d4e3 --- /dev/null +++ b/lib/__tests__/fixtures/config-block-no-empty-report-disables.json @@ -0,0 +1,5 @@ +{ + "rules": { + "block-no-empty": [true, { "reportDisables": true }] + } +} diff --git a/lib/__tests__/fixtures/empty-block-with-relevant-disable.css b/lib/__tests__/fixtures/empty-block-with-relevant-disable.css new file mode 100644 index 0000000000..b37a3088b4 --- /dev/null +++ b/lib/__tests__/fixtures/empty-block-with-relevant-disable.css @@ -0,0 +1,2 @@ +/* stylelint-disable block-no-empty */ +a {} diff --git a/lib/__tests__/invalidScopeDisables.test.js b/lib/__tests__/invalidScopeDisables.test.js index ffb2b2688e..f3a06bc03a 100644 --- a/lib/__tests__/invalidScopeDisables.test.js +++ b/lib/__tests__/invalidScopeDisables.test.js @@ -40,8 +40,8 @@ it('invalidScopeDisables simple case', () => { expect(report).toHaveLength(1); expect(report[0].ranges).toHaveLength(2); expect(report[0].ranges).toEqual([ - { end: 3, start: 1, unusedRule: 'block-no-empty' }, - { end: 5, start: 5, unusedRule: 'block-no-empty' }, + { end: 3, start: 1, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { end: 5, start: 5, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, ]); }); }); @@ -65,11 +65,11 @@ it('invalidScopeDisables complex case', () => { expect(invalidScopeDisables(linted.results, config)).toEqual([ { source: source('disabled-ranges-1.css'), - ranges: [{ start: 1, end: 3, unusedRule: 'color-named' }], + ranges: [{ start: 1, end: 3, rule: 'color-named', unusedRule: 'color-named' }], }, { source: source('disabled-ranges-2.css'), - ranges: [{ start: 5, end: 5, unusedRule: 'color-named' }], + ranges: [{ start: 5, end: 5, rule: 'color-named', unusedRule: 'color-named' }], }, ]); }); @@ -91,7 +91,7 @@ it('invalidScopeDisables ignored case', () => { expect(invalidScopeDisables(linted.results, config)).toEqual([ { source: source('disabled-ranges-1.css'), - ranges: [{ start: 5, end: 7, unusedRule: 'block-no-empty' }], + ranges: [{ start: 5, end: 7, rule: 'block-no-empty', unusedRule: 'block-no-empty' }], }, ]); }); @@ -119,6 +119,7 @@ it('invalidScopeDisables for config file', () => { { end: undefined, start: 4, + rule: 'foo', unusedRule: 'foo', }, ]); diff --git a/lib/__tests__/needlessDisables.test.js b/lib/__tests__/needlessDisables.test.js index ecf2e3451b..2a0b7380e4 100644 --- a/lib/__tests__/needlessDisables.test.js +++ b/lib/__tests__/needlessDisables.test.js @@ -42,8 +42,8 @@ it('needlessDisables simple case', () => { expect(report).toHaveLength(1); expect(report[0].ranges).toEqual([ - { start: 7, end: 9, unusedRule: 'all' }, - { start: 11, end: 11, unusedRule: 'block-no-empty' }, + { start: 7, end: 9, rule: 'all', unusedRule: 'all' }, + { start: 11, end: 11, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, ]); }); }); @@ -70,17 +70,17 @@ it('needlessDisables complex case', () => { { source: source('disabled-ranges-1.css'), ranges: [ - { start: 1, end: 3, unusedRule: 'color-named' }, - { start: 5, end: 7, unusedRule: 'block-no-empty' }, - { start: 10, end: 10, unusedRule: 'block-no-empty' }, + { start: 1, end: 3, rule: 'color-named', unusedRule: 'color-named' }, + { start: 5, end: 7, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { start: 10, end: 10, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, ], }, { source: source('disabled-ranges-2.css'), ranges: [ - { start: 5, end: 5, unusedRule: 'color-named' }, - { start: 6, end: 6, unusedRule: 'block-no-empty' }, - { start: 8, end: 10, unusedRule: 'block-no-empty' }, + { start: 5, end: 5, rule: 'color-named', unusedRule: 'color-named' }, + { start: 6, end: 6, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { start: 8, end: 10, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, ], }, ]); @@ -104,9 +104,9 @@ it('needlessDisables ignored case', () => { { source: source('disabled-ranges-1.css'), ranges: [ - { start: 1, end: 3, unusedRule: 'color-named' }, - { start: 5, end: 7, unusedRule: 'block-no-empty' }, - { start: 10, end: 10, unusedRule: 'all' }, + { start: 1, end: 3, rule: 'color-named', unusedRule: 'color-named' }, + { start: 5, end: 7, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { start: 10, end: 10, rule: 'all', unusedRule: 'all' }, ], }, ]); diff --git a/lib/__tests__/reportDisables.test.js b/lib/__tests__/reportDisables.test.js new file mode 100644 index 0000000000..c04d529c19 --- /dev/null +++ b/lib/__tests__/reportDisables.test.js @@ -0,0 +1,105 @@ +'use strict'; + +const standalone = require('../standalone'); +const stripIndent = require('common-tags').stripIndent; + +describe('reportDisables', () => { + it('reports a disabled comment', () => { + const config = { + rules: { 'block-no-empty': [true, { reportDisables: true }] }, + }; + + const css = stripIndent` + /* stylelint-disable block-no-empty */ + a {} + /* stylelint-enable block-no-empty */ + a { + b {} /* stylelint-disable-line block-no-empty */ + } + `; + + return standalone({ config, code: css }).then((linted) => { + const report = linted.reportedDisables; + + expect(report).toHaveLength(1); + expect(report[0].ranges).toEqual([ + { start: 1, end: 3, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { start: 5, end: 5, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + ]); + + // Although these disables are reported as issues, they're still in effect + // so the underlying lint issues are not reported. + expect(linted.results[0].warnings).toHaveLength(0); + }); + }); + + it('reports an ignored disabled comment', () => { + const config = { + rules: { 'block-no-empty': [true, { reportDisables: true }] }, + }; + + const css = stripIndent` + /* stylelint-disable block-no-empty */ + a {} + /* stylelint-enable block-no-empty */ + a { + b {} /* stylelint-disable-line block-no-empty */ + } + `; + + return standalone({ + config, + code: css, + ignoreDisables: true, + }).then((linted) => { + const report = linted.reportedDisables; + + expect(report).toHaveLength(1); + expect(report[0].ranges).toEqual([ + { start: 1, end: 3, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + { start: 5, end: 5, rule: 'block-no-empty', unusedRule: 'block-no-empty' }, + ]); + + expect(linted.results[0].warnings).toHaveLength(2); + }); + }); + + it("doesn't report disables by default", () => { + const config = { + rules: { 'block-no-empty': [true] }, + }; + + const css = stripIndent` + /* stylelint-disable block-no-empty */ + a {} + /* stylelint-enable block-no-empty */ + a { + b {} /* stylelint-disable-line block-no-empty */ + } + `; + + return standalone({ config, code: css }).then((linted) => { + const report = linted.reportedDisables; + + expect(report).toHaveLength(0); + }); + }); + + // This should be handled by the global `reportUnscopedDisables` option (#2292). + it("doesn't report unscoped disables", () => { + const config = { + rules: { 'block-no-empty': [true, { reportDisables: true }] }, + }; + + const css = stripIndent` + a {} /* stylelint-disable-line */ + `; + + return standalone({ config, code: css }).then((linted) => { + const report = linted.reportedDisables; + + expect(report).toHaveLength(1); + expect(report[0].ranges).toHaveLength(0); + }); + }); +}); diff --git a/lib/__tests__/standalone-invalidScopeDisables.test.js b/lib/__tests__/standalone-invalidScopeDisables.test.js index c65cab3321..220baff965 100644 --- a/lib/__tests__/standalone-invalidScopeDisables.test.js +++ b/lib/__tests__/standalone-invalidScopeDisables.test.js @@ -25,6 +25,7 @@ it('standalone with input css and `reportInvalidScopeDisables`', () => { expect(invalidScopeDisables[0].ranges).toHaveLength(1); expect(invalidScopeDisables[0].ranges[0]).toEqual({ start: 1, + rule: 'color-named', unusedRule: 'color-named', }); }); @@ -45,6 +46,7 @@ it('standalone with input file(s) and `reportInvalidScopeDisables`', () => { ); expect(invalidScopeDisables[0].ranges[0]).toEqual({ start: 1, + rule: 'color-named', unusedRule: 'color-named', }); }); diff --git a/lib/__tests__/standalone-needlessDisables.test.js b/lib/__tests__/standalone-needlessDisables.test.js index 08fbebcdfb..b3559e463a 100644 --- a/lib/__tests__/standalone-needlessDisables.test.js +++ b/lib/__tests__/standalone-needlessDisables.test.js @@ -27,6 +27,7 @@ it('standalone with input css and `reportNeedlessDisables`', () => { expect(needlessDisables[0].ranges).toHaveLength(1); expect(needlessDisables[0].ranges[0]).toEqual({ start: 1, + rule: 'color-named', unusedRule: 'color-named', }); @@ -130,6 +131,7 @@ it('standalone with input file(s) and `reportNeedlessDisables`', () => { ); expect(needlessDisables[0].ranges[0]).toEqual({ start: 1, + rule: 'color-named', unusedRule: 'color-named', }); }); diff --git a/lib/__tests__/stylelintignore-test/stylelintignore.test.js b/lib/__tests__/stylelintignore-test/stylelintignore.test.js index a2783fa202..04919e5e47 100644 --- a/lib/__tests__/stylelintignore-test/stylelintignore.test.js +++ b/lib/__tests__/stylelintignore-test/stylelintignore.test.js @@ -64,6 +64,7 @@ describe('stylelintignore', () => { expect(data).toEqual({ errored: false, output: '[]', + reportedDisables: [], results: [], }); }); @@ -98,6 +99,7 @@ describe('stylelintignore', () => { expect(data).toEqual({ errored: false, output: '[]', + reportedDisables: [], results: [], }); }); @@ -112,6 +114,7 @@ describe('stylelintignore', () => { expect(data).toEqual({ errored: false, output: '[]', + reportedDisables: [], results: [], }); }); diff --git a/lib/cli.js b/lib/cli.js index f1805e6c83..7c5a40608e 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -481,8 +481,18 @@ module.exports = (argv) => { .then((linted) => { const reports = []; + const report = disableOptionsReportStringFormatter( + linted.reportedDisables || [], + 'forbidden disable', + ); + + if (report) reports.push(report); + if (reportNeedlessDisables) { - const report = disableOptionsReportStringFormatter(linted.needlessDisables || []); + const report = disableOptionsReportStringFormatter( + linted.needlessDisables || [], + 'needless disable', + ); if (report) { reports.push(report); @@ -490,7 +500,10 @@ module.exports = (argv) => { } if (reportInvalidScopeDisables) { - const report = disableOptionsReportStringFormatter(linted.invalidScopeDisables || []); + const report = disableOptionsReportStringFormatter( + linted.invalidScopeDisables || [], + 'disable with invalid scope', + ); if (report) { reports.push(report); diff --git a/lib/formatters/__tests__/disableOptionsReportStringFormatter.test.js b/lib/formatters/__tests__/disableOptionsReportStringFormatter.test.js index b6d5cdc743..28f336e465 100644 --- a/lib/formatters/__tests__/disableOptionsReportStringFormatter.test.js +++ b/lib/formatters/__tests__/disableOptionsReportStringFormatter.test.js @@ -7,36 +7,39 @@ const stripIndent = require('common-tags').stripIndent; describe('disableOptionsReportStringFormatter', () => { it('formatter stringified', () => { const actual = stripAnsi( - disableOptionsReportStringFormatterTest([ - { - source: 'foo', - ranges: [ - { start: 1, end: 3, unusedRule: 'baz' }, - { start: 7, unusedRule: 'all' }, - ], - }, - { - source: 'bar', - ranges: [ - { start: 19, end: 33, unusedRule: 'all' }, - { start: 99, end: 102, unusedRule: 'baz' }, - ], - }, - { - sourc: 'baz', - ranges: [], - }, - ]), + disableOptionsReportStringFormatterTest( + [ + { + source: 'foo', + ranges: [ + { start: 1, end: 3, rule: 'baz' }, + { start: 7, rule: 'all' }, + ], + }, + { + source: 'bar', + ranges: [ + { start: 19, end: 33, rule: 'all' }, + { start: 99, end: 102, rule: 'baz' }, + ], + }, + { + sourc: 'baz', + ranges: [], + }, + ], + 'wrong disable', + ), ); let expected = stripIndent` foo - unused rule: baz, start line: 1, end line: 3 - unused rule: all, start line: 7 + wrong disable: baz, start line: 1, end line: 3 + wrong disable: all, start line: 7 bar - unused rule: all, start line: 19, end line: 33 - unused rule: baz, start line: 99, end line: 102`; + wrong disable: all, start line: 19, end line: 33 + wrong disable: baz, start line: 99, end line: 102`; expected = `\n${expected}\n`; diff --git a/lib/formatters/disableOptionsReportStringFormatter.js b/lib/formatters/disableOptionsReportStringFormatter.js index 341f45ba67..3c1fcebe6d 100644 --- a/lib/formatters/disableOptionsReportStringFormatter.js +++ b/lib/formatters/disableOptionsReportStringFormatter.js @@ -15,9 +15,10 @@ function logFrom(fromValue) { /** * @param {import('stylelint').StylelintDisableOptionsReport} report + * @param {string} message * @returns {string} */ -module.exports = function (report) { +module.exports = function (report, message) { if (!report) return ''; let output = ''; @@ -32,7 +33,7 @@ module.exports = function (report) { output += chalk.underline(logFrom(sourceReport.source || '')) + '\n'; sourceReport.ranges.forEach((range) => { - output += `unused rule: ${range.unusedRule}, start line: ${range.start}`; + output += `${message}: ${range.rule}, start line: ${range.start}`; if (range.end !== undefined) { output += `, end line: ${range.end}`; diff --git a/lib/invalidScopeDisables.js b/lib/invalidScopeDisables.js index 4c572d5d0c..1249284cb0 100644 --- a/lib/invalidScopeDisables.js +++ b/lib/invalidScopeDisables.js @@ -1,7 +1,6 @@ 'use strict'; /** @typedef {import('stylelint').RangeType} RangeType */ -/** @typedef {import('stylelint').UnusedRange} UnusedRange */ /** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */ /** @@ -45,9 +44,10 @@ module.exports = function (results) { } sourceReport.ranges.push({ - unusedRule: rule, + rule, start: range.start, end: range.end, + unusedRule: rule, }); }); }); diff --git a/lib/needlessDisables.js b/lib/needlessDisables.js index 70c2886d74..70eae0f92a 100644 --- a/lib/needlessDisables.js +++ b/lib/needlessDisables.js @@ -3,7 +3,7 @@ const _ = require('lodash'); /** @typedef {import('stylelint').RangeType} RangeType */ -/** @typedef {import('stylelint').UnusedRange} UnusedRange */ +/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */ /** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */ /** @@ -20,7 +20,7 @@ module.exports = function (results) { return; } - /** @type {{ranges: UnusedRange[], source: string}} */ + /** @type {{ranges: DisableReportRange[], source: string}} */ const unused = { source: result.source || '', ranges: [] }; /** @type {{[ruleName: string]: Array}} */ @@ -68,6 +68,7 @@ module.exports = function (results) { // mark this range as unused if (!range.used && !alreadyMarkedUnused) { unused.ranges.push({ + rule, start: range.start, end: range.end, unusedRule: rule, diff --git a/lib/prepareReturnValue.js b/lib/prepareReturnValue.js index 90f887c018..2153c4c1de 100644 --- a/lib/prepareReturnValue.js +++ b/lib/prepareReturnValue.js @@ -2,6 +2,7 @@ const invalidScopeDisables = require('./invalidScopeDisables'); const needlessDisables = require('./needlessDisables'); +const reportDisables = require('./reportDisables'); /** @typedef {import('stylelint').Formatter} Formatter */ /** @typedef {import('stylelint').StylelintResult} StylelintResult */ @@ -27,6 +28,7 @@ function prepareReturnValue(stylelintResults, options, formatter) { errored, results: [], output: '', + reportedDisables: reportDisables(stylelintResults), }; if (reportNeedlessDisables) { diff --git a/lib/reportDisables.js b/lib/reportDisables.js new file mode 100644 index 0000000000..a528fe7640 --- /dev/null +++ b/lib/reportDisables.js @@ -0,0 +1,71 @@ +'use strict'; + +const _ = require('lodash'); + +/** @typedef {import('stylelint').RangeType} RangeType */ +/** @typedef {import('stylelint').DisableReportRange} DisabledRange */ +/** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */ + +/** + * Returns a report describing which `results` (if any) contain disabled ranges + * for rules that disallow disables via `reportDisables: true`. + * + * @param {import('stylelint').StylelintResult[]} results + * @returns {StylelintDisableOptionsReport} + */ +module.exports = function (results) { + /** @type {StylelintDisableOptionsReport} */ + const report = []; + + results.forEach((result) => { + // File with `CssSyntaxError` don't have `_postcssResult`s. + if (!result._postcssResult) { + return; + } + + /** @type {{ranges: DisabledRange[], source: string}} */ + const reported = { source: result.source || '', ranges: [] }; + + /** @type {{[ruleName: string]: Array}} */ + const rangeData = result._postcssResult.stylelint.disabledRanges; + + if (!rangeData) return; + + const config = result._postcssResult.stylelint.config; + + // If no rules actually disallow disables, don't bother looking for ranges + // that correspond to disabled rules. + if (!Object.values(_.get(config, 'rules', {})).some(reportDisablesForRule)) { + return []; + } + + Object.keys(rangeData).forEach((rule) => { + rangeData[rule].forEach((range) => { + if (!reportDisablesForRule(_.get(config, ['rules', rule], []))) return; + + reported.ranges.push({ + rule, + start: range.start, + end: range.end, + unusedRule: rule, + }); + }); + }); + + reported.ranges = _.sortBy(reported.ranges, ['start', 'end']); + + report.push(reported); + }); + + return report; +}; + +/** + * @param {[any, object]|null} options + * @return {boolean} + */ +function reportDisablesForRule(options) { + if (!options) return false; + + return _.get(options[1], 'reportDisables', false); +} diff --git a/lib/utils/validateOptions.js b/lib/utils/validateOptions.js index a315839309..be701baaea 100644 --- a/lib/utils/validateOptions.js +++ b/lib/utils/validateOptions.js @@ -2,7 +2,7 @@ const _ = require('lodash'); -const ignoredOptions = ['severity', 'message']; +const ignoredOptions = ['severity', 'message', 'reportDisables']; /** @typedef {{possible: any, actual: any, optional: boolean}} Options */ diff --git a/system-tests/001/__snapshots__/fs.test.js.snap b/system-tests/001/__snapshots__/fs.test.js.snap index 1838ea5b96..dc44057660 100644 --- a/system-tests/001/__snapshots__/fs.test.js.snap +++ b/system-tests/001/__snapshots__/fs.test.js.snap @@ -12,6 +12,7 @@ Object { "warnings": Array [], }, ], + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/system-tests/001/__snapshots__/no-fs.test.js.snap b/system-tests/001/__snapshots__/no-fs.test.js.snap index 7b5542ea72..a22d9111a8 100644 --- a/system-tests/001/__snapshots__/no-fs.test.js.snap +++ b/system-tests/001/__snapshots__/no-fs.test.js.snap @@ -12,6 +12,7 @@ Object { "warnings": Array [], }, ], + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/system-tests/002/__snapshots__/fs.test.js.snap b/system-tests/002/__snapshots__/fs.test.js.snap index a3477dd5e0..f7b6f0e9e7 100644 --- a/system-tests/002/__snapshots__/fs.test.js.snap +++ b/system-tests/002/__snapshots__/fs.test.js.snap @@ -34,6 +34,7 @@ Object { ], }, ], + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/system-tests/002/__snapshots__/no-fs.test.js.snap b/system-tests/002/__snapshots__/no-fs.test.js.snap index 291196c64d..06cdbf4b68 100644 --- a/system-tests/002/__snapshots__/no-fs.test.js.snap +++ b/system-tests/002/__snapshots__/no-fs.test.js.snap @@ -34,6 +34,7 @@ Object { ], }, ], + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/system-tests/003/__snapshots__/fs.test.js.snap b/system-tests/003/__snapshots__/fs.test.js.snap index 7557ca761c..6e827c1243 100644 --- a/system-tests/003/__snapshots__/fs.test.js.snap +++ b/system-tests/003/__snapshots__/fs.test.js.snap @@ -20,6 +20,7 @@ Object { ], }, ], + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/system-tests/003/__snapshots__/no-fs.test.js.snap b/system-tests/003/__snapshots__/no-fs.test.js.snap index cc78fb7613..33b27ad578 100644 --- a/system-tests/003/__snapshots__/no-fs.test.js.snap +++ b/system-tests/003/__snapshots__/no-fs.test.js.snap @@ -216,6 +216,7 @@ footer a:visited { height: 110px; } ", + "reportedDisables": Array [], "results": Array [ Object { "deprecations": Array [], diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index 197291b439..7ee82c577a 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -216,21 +216,22 @@ declare module 'stylelint' { _postcssResult?: PostcssResult; }; - export type UnusedRange = { - unusedRule: string; + export type DisableReportRange = { + rule: string; start: number; end?: number; + + // This is for backwards-compatibility with formatters that were written + // when this name was used instead of `rule`. It should be avoided for new + // formatters. + unusedRule: string; }; export type RangeType = DisabledRange & { used?: boolean }; export type StylelintDisableReportEntry = { source?: string; - ranges: Array<{ - unusedRule: string; - start: number; - end?: number; - }>; + ranges: Array; }; export type StylelintStandaloneReturnValue = { @@ -241,6 +242,7 @@ declare module 'stylelint' { maxWarnings: number; foundWarnings: number; }; + reportedDisables: StylelintDisableOptionsReport; needlessDisables?: StylelintDisableOptionsReport; invalidScopeDisables?: StylelintDisableOptionsReport; }; From e1240334e69499e23a8501e717c67369ed25f38e Mon Sep 17 00:00:00 2001 From: Dmitrii Kanatnikov Date: Fri, 28 Aug 2020 17:41:06 +0300 Subject: [PATCH 16/34] Add support for *.cjs config files (#4905) --- package-lock.json | 62 ++++++++++++++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/package-lock.json b/package-lock.json index 6bcd99a021..62be53202e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1662,14 +1662,6 @@ "@types/node": "*" } }, - "@types/leven": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@types/leven/-/leven-2.1.2.tgz", - "integrity": "sha512-/DZnNl+6YyiHG+t1EbNMBlMbrU8r1f7RWRi0kAYZYxko0hzA13IMagg9qtTL4a3SwFx4eYubZMcvYAijuKbS5A==", - "requires": { - "leven": "*" - } - }, "@types/lodash": { "version": "4.14.157", "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.157.tgz", @@ -2853,15 +2845,15 @@ "dev": true }, "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.0.tgz", + "integrity": "sha512-pondGvTuVYDk++upghXJabWzL6Kxu6f26ljFw64Swq9v6sQPUL3EUlVDV56diOjpCayKihL6hVe8exIACU4XcA==", "requires": { "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", + "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", - "yaml": "^1.7.2" + "yaml": "^1.10.0" } }, "cross-spawn": { @@ -4524,6 +4516,21 @@ "please-upgrade-node": "^3.2.0", "slash": "^3.0.0", "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + } } }, "iconv-lite": { @@ -6809,7 +6816,8 @@ "leven": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==" + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true }, "levenshtein-edit-distance": { "version": "1.0.0", @@ -6911,6 +6919,19 @@ "stringify-object": "^3.3.0" }, "dependencies": { + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, "execa": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", @@ -7940,6 +7961,19 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, "del": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", diff --git a/package.json b/package.json index e4a591eb9d..8283cc81d2 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "autoprefixer": "^9.8.2", "balanced-match": "^1.0.0", "chalk": "^4.1.0", - "cosmiconfig": "^6.0.0", + "cosmiconfig": "^7.0.0", "debug": "^4.1.1", "execall": "^2.0.0", "fastest-levenshtein": "^1.0.9", From fd1875d550e79a7c93d26f945b22b7c2c053461c Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Fri, 28 Aug 2020 15:45:13 +0100 Subject: [PATCH 17/34] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ab07cb90f..065d8cc8d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,15 +6,16 @@ All notable changes to this project are documented in this file. - Added: syntax object acceptance to `customSyntax` option ([#4839](https://github.com/stylelint/stylelint/pull/4839)). - Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). +- Added: support for `*.cjs` config files ([#4905](https://github.com/stylelint/stylelint/pull/4905)). - Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). - Added: `*-no-vendor-prefix` autofix ([#4859](https://github.com/stylelint/stylelint/pull/4859)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). - Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). - Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). +- Fixed: support for multi-line disable descriptions ([#4895](https://github.com/stylelint/stylelint/pull/4895)). - Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). - Fixed: `length-zero-no-unit` TypeError for custom properties fallback ([#4860](https://github.com/stylelint/stylelint/pull/4860)). - Fixed: false negatives for `where`, `is`, `nth-child` and `nth-last-child` in `selector-max-*` rules (except selector-max-type) ([#4842](https://github.com/stylelint/stylelint/pull/4842)). -- Fixed: support for multi-line disable descriptions ([#4895](https://github.com/stylelint/stylelint/pull/4895)). ## 13.6.1 From e2da12415385422ce8ebd3600eac63fb67f19b41 Mon Sep 17 00:00:00 2001 From: Brandon Conway Date: Fri, 28 Aug 2020 07:49:01 -0700 Subject: [PATCH 18/34] Add coc-stylelint (#4901) --- docs/user-guide/integrations/editor.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/user-guide/integrations/editor.md b/docs/user-guide/integrations/editor.md index 10e3e85029..034470de2a 100644 --- a/docs/user-guide/integrations/editor.md +++ b/docs/user-guide/integrations/editor.md @@ -9,3 +9,4 @@ Editor integrations built and maintained by the community. - [SublimeLinter-contrib-stylelint_d](https://github.com/jo-sm/SublimeLinter-contrib-stylelint_d) - Sublime Text plugin for stylelint that run's on daemon. - [WebStorm](https://blog.jetbrains.com/webstorm/2016/09/webstorm-2016-3-eap-163-4830-stylelint-usages-for-default-exports-and-more/) - version 2016.3 onwards has built-in support for stylelint. - [vscode-stylelint](https://marketplace.visualstudio.com/items?itemName=stylelint.vscode-stylelint) - VS Code extension for stylelint. +- [coc-stylelint](https://github.com/neoclide/coc-stylelint) - coc.nvim language server extension for neovim. From 2c4d77fcb9aed067e92bddb1aa0ba15be1976a1c Mon Sep 17 00:00:00 2001 From: Matt Wang Date: Fri, 28 Aug 2020 07:50:12 -0700 Subject: [PATCH 19/34] Fix false positives for trailing combinator in selector-combinator-space-after (#4878) --- .../__tests__/index.js | 56 ++----------------- lib/rules/selectorCombinatorSpaceChecker.js | 6 ++ .../isStandardSyntaxCombinator.test.js | 20 +++++++ lib/utils/isStandardSyntaxCombinator.js | 24 +++++++- 4 files changed, 53 insertions(+), 53 deletions(-) diff --git a/lib/rules/selector-combinator-space-after/__tests__/index.js b/lib/rules/selector-combinator-space-after/__tests__/index.js index eb05188292..a153b793a4 100644 --- a/lib/rules/selector-combinator-space-after/__tests__/index.js +++ b/lib/rules/selector-combinator-space-after/__tests__/index.js @@ -554,33 +554,9 @@ testRule({ code: 'a { > /*comment*/a, > /*comment*/.b{} }', description: 'scss nesting and comment', }, - ], - - reject: [ { - code: 'a { >/*comment*/a {} }', - fixed: 'a { > /*comment*/a {} }', - description: 'scss nesting and comment', - message: messages.expectedAfter('>'), - line: 1, - column: 5, - }, - { - code: 'a { >/*comment*/a, >/*comment*/.b{} }', - fixed: 'a { > /*comment*/a, > /*comment*/.b{} }', - description: 'scss nesting, comment and comma', - warnings: [ - { - message: messages.expectedAfter('>'), - line: 1, - column: 5, - }, - { - message: messages.expectedAfter('>'), - line: 1, - column: 20, - }, - ], + code: 'a ~, b {}', + description: 'scss trailing combinator', }, ], }); @@ -596,33 +572,9 @@ testRule({ code: 'a { >/*comment*/a, >/*comment*/.b {} }', description: 'scss nesting and comment', }, - ], - - reject: [ { - code: 'a { > /*comment*/a {} }', - fixed: 'a { >/*comment*/a {} }', - description: 'scss nesting and comment', - message: messages.rejectedAfter('>'), - line: 1, - column: 5, - }, - { - code: 'a { > /*comment*/a, > /*comment*/.b {} }', - fixed: 'a { >/*comment*/a, >/*comment*/.b {} }', - description: 'scss nesting, comment and comma', - warnings: [ - { - message: messages.rejectedAfter('>'), - line: 1, - column: 5, - }, - { - message: messages.rejectedAfter('>'), - line: 1, - column: 21, - }, - ], + code: 'a ~, b {}', + description: 'scss trailing combinator', }, ], }); diff --git a/lib/rules/selectorCombinatorSpaceChecker.js b/lib/rules/selectorCombinatorSpaceChecker.js index c6731dc1bc..d8c73a846a 100644 --- a/lib/rules/selectorCombinatorSpaceChecker.js +++ b/lib/rules/selectorCombinatorSpaceChecker.js @@ -2,6 +2,7 @@ 'use strict'; +const isStandardSyntaxCombinator = require('../utils/isStandardSyntaxCombinator'); const isStandardSyntaxRule = require('../utils/isStandardSyntaxRule'); const parseSelector = require('../utils/parseSelector'); const report = require('../utils/report'); @@ -19,6 +20,11 @@ module.exports = function (opts) { const fixedSelector = parseSelector(selector, opts.result, rule, (selectorTree) => { selectorTree.walkCombinators((node) => { + // Ignore non-standard combinators + if (!isStandardSyntaxCombinator(node)) { + return; + } + // Ignore spaced descendant combinator if (/\s/.test(node.value)) { return; diff --git a/lib/utils/__tests__/isStandardSyntaxCombinator.test.js b/lib/utils/__tests__/isStandardSyntaxCombinator.test.js index ed73f96d59..65b71d3454 100644 --- a/lib/utils/__tests__/isStandardSyntaxCombinator.test.js +++ b/lib/utils/__tests__/isStandardSyntaxCombinator.test.js @@ -60,6 +60,26 @@ describe('isStandardSyntaxCombinator', () => { expect(isStandardSyntaxCombinator(func)).toBeFalsy(); }); }); + it('last node is combinator', () => { + rules('a ~, {}', (func) => { + expect(isStandardSyntaxCombinator(func)).toBeFalsy(); + }); + }); + it('first node is combinator', () => { + rules('~ b {}', (func) => { + expect(isStandardSyntaxCombinator(func)).toBeFalsy(); + }); + }); + it('last node (in first container) is combinator', () => { + rules('a ~, b {}', (func) => { + expect(isStandardSyntaxCombinator(func)).toBeFalsy(); + }); + }); + it('first node (in second container) is combinator', () => { + rules('a, ~ b {}', (func) => { + expect(isStandardSyntaxCombinator(func)).toBeFalsy(); + }); + }); }); function rules(css, cb) { diff --git a/lib/utils/isStandardSyntaxCombinator.js b/lib/utils/isStandardSyntaxCombinator.js index 2a929510ca..2eba3d9677 100644 --- a/lib/utils/isStandardSyntaxCombinator.js +++ b/lib/utils/isStandardSyntaxCombinator.js @@ -7,6 +7,28 @@ * @return {boolean} If `true`, the combinator is standard */ module.exports = function (node) { + // if it's not a combinator, then it's not a standard combinator + if (node.type !== 'combinator') { + return false; + } + // Ignore reference combinators like `/deep/` - return node.type === 'combinator' && !node.value.startsWith('/') && !node.value.endsWith('/'); + if (node.value.startsWith('/') || node.value.endsWith('/')) { + return false; + } + + // ignore the combinators that are the first or last node in their container + if (node.parent !== undefined && node.parent !== null) { + let parent = node.parent; + + if (node === parent.first) { + return false; + } + + if (node === parent.last) { + return false; + } + } + + return true; }; From d0a150e8da7d8808205f3a025aed99264f067a83 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Fri, 28 Aug 2020 15:52:15 +0100 Subject: [PATCH 20/34] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 065d8cc8d5..801da1a13a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,7 +15,7 @@ All notable changes to this project are documented in this file. - Fixed: support for multi-line disable descriptions ([#4895](https://github.com/stylelint/stylelint/pull/4895)). - Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). - Fixed: `length-zero-no-unit` TypeError for custom properties fallback ([#4860](https://github.com/stylelint/stylelint/pull/4860)). -- Fixed: false negatives for `where`, `is`, `nth-child` and `nth-last-child` in `selector-max-*` rules (except selector-max-type) ([#4842](https://github.com/stylelint/stylelint/pull/4842)). +- Fixed: `selector-combinator-space-after` false positives for trailing combinator ([#4878](https://github.com/stylelint/stylelint/pull/4878)). ## 13.6.1 From 260e7431aed8562b62343b8e3087596bf346c8d6 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Fri, 28 Aug 2020 23:55:01 +0900 Subject: [PATCH 21/34] Fix callbacks in tests (#4903) --- lib/utils/__tests__/atRuleParamIndex.test.js | 24 +++--- .../__tests__/declarationValueIndex.test.js | 28 +++---- .../__tests__/isCustomPropertySet.test.js | 12 +-- lib/utils/__tests__/isFirstNested.test.js | 73 +++++++++++++------ 4 files changed, 77 insertions(+), 60 deletions(-) diff --git a/lib/utils/__tests__/atRuleParamIndex.test.js b/lib/utils/__tests__/atRuleParamIndex.test.js index fe4daf0989..ab20fead7d 100644 --- a/lib/utils/__tests__/atRuleParamIndex.test.js +++ b/lib/utils/__tests__/atRuleParamIndex.test.js @@ -5,30 +5,26 @@ const postcss = require('postcss'); describe('atRuleParamIndex', () => { it('has a single space before the param', () => { - atRules('@media (color) {}', (atRule) => { - expect(atRuleParamIndex(atRule)).toBe(7); - }); + expect(atRuleParamIndex(atRule('@media (color) {}'))).toBe(7); }); it('has multiple spaces before the param', () => { - atRules('@media (color) {}', (atRule) => { - expect(atRuleParamIndex(atRule)).toBe(8); - }); + expect(atRuleParamIndex(atRule('@media (color) {}'))).toBe(8); }); it('has a newline before the param', () => { - atRules("@import\n'x.css');", (atRule) => { - expect(atRuleParamIndex(atRule)).toBe(8); - }); + expect(atRuleParamIndex(atRule("@import\n'x.css');"))).toBe(8); }); it('has a function param', () => { - atRules('@document url-prefix(http://www.w3.org/Style/)', (atRule) => { - expect(atRuleParamIndex(atRule)).toBe(10); - }); + expect(atRuleParamIndex(atRule('@document url-prefix(http://www.w3.org/Style/)'))).toBe(10); }); }); -function atRules(css, cb) { - postcss.parse(css).walkAtRules(cb); +function atRule(css) { + const list = []; + + postcss.parse(css).walkAtRules((rule) => list.push(rule)); + + return list[0]; } diff --git a/lib/utils/__tests__/declarationValueIndex.test.js b/lib/utils/__tests__/declarationValueIndex.test.js index d5b98ec46a..b6b0ed4dd8 100644 --- a/lib/utils/__tests__/declarationValueIndex.test.js +++ b/lib/utils/__tests__/declarationValueIndex.test.js @@ -5,36 +5,30 @@ const postcss = require('postcss'); describe('declarationValueIndex', () => { it('has a space before the value', () => { - rules('a { a: b}', (decl) => { - expect(declarationValueIndex(decl)).toBe(3); - }); + expect(declarationValueIndex(decl('a { a: b}'))).toBe(3); }); it('has a colon before the value', () => { - rules('a { a :b }', (decl) => { - expect(declarationValueIndex(decl)).toBe(3); - }); + expect(declarationValueIndex(decl('a { a :b }'))).toBe(3); }); it('has no spaces before the value', () => { - rules('a { a:b }', (decl) => { - expect(declarationValueIndex(decl)).toBe(2); - }); + expect(declarationValueIndex(decl('a { a:b }'))).toBe(2); }); it('has multiple characters before the value', () => { - rules('a { a : b }', (decl) => { - expect(declarationValueIndex(decl)).toBe(5); - }); + expect(declarationValueIndex(decl('a { a : b }'))).toBe(5); }); it('has a newline before the value', () => { - rules('a { a:\nb }', (decl) => { - expect(declarationValueIndex(decl)).toBe(3); - }); + expect(declarationValueIndex(decl('a { a:\nb }'))).toBe(3); }); }); -function rules(css, cb) { - postcss.parse(css).walkDecls(cb); +function decl(css) { + const list = []; + + postcss.parse(css).walkDecls((decl) => list.push(decl)); + + return list[0]; } diff --git a/lib/utils/__tests__/isCustomPropertySet.test.js b/lib/utils/__tests__/isCustomPropertySet.test.js index 0dee043e9d..0a3de8fc11 100644 --- a/lib/utils/__tests__/isCustomPropertySet.test.js +++ b/lib/utils/__tests__/isCustomPropertySet.test.js @@ -5,18 +5,14 @@ const postcss = require('postcss'); describe('isCustomPropertySet', () => { it('accepts custom property set', () => { - customPropertySet('--foo: {};', (customPropertySet) => { - expect(isCustomPropertySet(customPropertySet)).toBeTruthy(); - }); + expect(isCustomPropertySet(node('--foo: {};'))).toBeTruthy(); }); it('rejects custom property', () => { - customPropertySet('--foo: red;', (customPropertySet) => { - expect(isCustomPropertySet(customPropertySet)).toBeFalsy(); - }); + expect(isCustomPropertySet(node('--foo: red;'))).toBeFalsy(); }); }); -function customPropertySet(css, cb) { - postcss.parse(css).walk(cb); +function node(css) { + return postcss.parse(css).first; } diff --git a/lib/utils/__tests__/isFirstNested.test.js b/lib/utils/__tests__/isFirstNested.test.js index c3ced6594e..6e699bc0a4 100644 --- a/lib/utils/__tests__/isFirstNested.test.js +++ b/lib/utils/__tests__/isFirstNested.test.js @@ -22,9 +22,13 @@ describe('isFirstNested', () => { } `); - root.walkRules((rule) => { - expect(isFirstNested(rule)).toBe(true); - }); + const rules = []; + + root.walkRules((rule) => rules.push(rule)); + + expect(rules).toHaveLength(2); + expect(isFirstNested(rules[0])).toBe(true); + expect(isFirstNested(rules[1])).toBe(true); }); it('returns true with the first-nested at-rule', () => { @@ -37,9 +41,13 @@ describe('isFirstNested', () => { } `); - root.walkAtRules((atRule) => { - expect(isFirstNested(atRule)).toBe(true); - }); + const atRules = []; + + root.walkAtRules((rule) => atRules.push(rule)); + + expect(atRules).toHaveLength(2); + expect(isFirstNested(atRules[0])).toBe(true); + expect(isFirstNested(atRules[1])).toBe(true); }); it('returns true with the first-nested declaration', () => { @@ -52,9 +60,13 @@ describe('isFirstNested', () => { } `); - root.walkDecls((atRule) => { - expect(isFirstNested(atRule)).toBe(true); - }); + const decls = []; + + root.walkDecls((decl) => decls.push(decl)); + + expect(decls).toHaveLength(2); + expect(isFirstNested(decls[0])).toBe(true); + expect(isFirstNested(decls[1])).toBe(true); }); it('returns true with first-nested non-statement', () => { @@ -67,9 +79,14 @@ describe('isFirstNested', () => { } `); - root.walkComments((comment) => { - expect(isFirstNested(comment)).toBe(true); - }); + const comments = []; + + root.walkComments((comment) => comments.push(comment)); + + expect(comments).toHaveLength(3); + expect(isFirstNested(comments[0])).toBe(true); + expect(isFirstNested(comments[1])).toBe(true); + expect(isFirstNested(comments[2])).toBe(true); }); it('returns false with not-first-nested rule', () => { @@ -84,9 +101,13 @@ describe('isFirstNested', () => { } `); - root.walkRules('b', (rule) => { - expect(isFirstNested(rule)).toBe(false); - }); + const rules = []; + + root.walkRules('b', (rule) => rules.push(rule)); + + expect(rules).toHaveLength(2); + expect(isFirstNested(rules[0])).toBe(false); + expect(isFirstNested(rules[1])).toBe(false); }); it('returns false with not-first-nested at-rule', () => { @@ -101,9 +122,13 @@ describe('isFirstNested', () => { } `); - root.walkAtRules('expect', (atRule) => { - expect(isFirstNested(atRule)).toBe(false); - }); + const atRules = []; + + root.walkAtRules('expect', (atRule) => atRules.push(atRule)); + + expect(atRules).toHaveLength(2); + expect(isFirstNested(atRules[0])).toBe(false); + expect(isFirstNested(atRules[1])).toBe(false); }); it('returns false with not-first-nested declaration', () => { @@ -126,8 +151,14 @@ describe('isFirstNested', () => { } `); - root.walkDecls('color', (atRule) => { - expect(isFirstNested(atRule)).toBe(false); - }); + const decls = []; + + root.walkDecls('color', (decl) => decls.push(decl)); + + expect(decls).toHaveLength(4); + expect(isFirstNested(decls[0])).toBe(false); + expect(isFirstNested(decls[1])).toBe(false); + expect(isFirstNested(decls[2])).toBe(false); + expect(isFirstNested(decls[3])).toBe(false); }); }); From 5446be22bbc1f71f52c0c2c4aa7f3e2cd0cffe32 Mon Sep 17 00:00:00 2001 From: Masafumi Koba <473530+ybiquitous@users.noreply.github.com> Date: Mon, 31 Aug 2020 17:41:19 +0900 Subject: [PATCH 22/34] Fix CHANGELOG.md format via Prettier (#4910) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 801da1a13a..e916fab15f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this project are documented in this file. - Added: syntax object acceptance to `customSyntax` option ([#4839](https://github.com/stylelint/stylelint/pull/4839)). - Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). -- Added: support for `*.cjs` config files ([#4905](https://github.com/stylelint/stylelint/pull/4905)). +- Added: support for `*.cjs` config files ([#4905](https://github.com/stylelint/stylelint/pull/4905)). - Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). - Added: `*-no-vendor-prefix` autofix ([#4859](https://github.com/stylelint/stylelint/pull/4859)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). From 0a17b64b5471ff1e096d16ec6dfce2b02c021982 Mon Sep 17 00:00:00 2001 From: Jennifer Thakar Date: Mon, 31 Aug 2020 03:50:37 -0700 Subject: [PATCH 23/34] Add a reportDescriptionlessDisables flag (#4907) --- lib/__tests__/__snapshots__/cli.test.js.snap | 5 ++ lib/__tests__/cli.test.js | 18 ++++++ lib/__tests__/descriptionlessDisables.test.js | 62 +++++++++++++++++++ lib/__tests__/disableRanges.test.js | 10 +++ lib/assignDisabledRanges.js | 48 +++++++++----- lib/cli.js | 27 ++++++++ lib/descriptionlessDisables.js | 52 ++++++++++++++++ lib/prepareReturnValue.js | 12 +++- lib/standalone.js | 2 + types/stylelint/index.d.ts | 5 ++ 10 files changed, 226 insertions(+), 15 deletions(-) create mode 100644 lib/__tests__/descriptionlessDisables.test.js create mode 100644 lib/descriptionlessDisables.js diff --git a/lib/__tests__/__snapshots__/cli.test.js.snap b/lib/__tests__/__snapshots__/cli.test.js.snap index 8daa701743..2cda5d64de 100644 --- a/lib/__tests__/__snapshots__/cli.test.js.snap +++ b/lib/__tests__/__snapshots__/cli.test.js.snap @@ -122,6 +122,11 @@ exports[`CLI --help 1`] = ` Report stylelint-disable comments that used for rules that don't exist within the configuration object. The process will exit with code 2 if invalid scope disables are found. + --report-descriptionless-disables, --rdd + + Report stylelint-disable comments without a description. + The process will exit with code 2 if descriptionless disables are found. + --max-warnings, --mw Number of warnings above which the process will exit with code 2. diff --git a/lib/__tests__/cli.test.js b/lib/__tests__/cli.test.js index ba81d44264..9599f39d4e 100644 --- a/lib/__tests__/cli.test.js +++ b/lib/__tests__/cli.test.js @@ -26,6 +26,7 @@ describe('buildCLI', () => { ignoreDisables: false, printConfig: false, quiet: false, + reportDescriptionlessDisables: false, reportInvalidScopeDisables: false, reportNeedlessDisables: false, stdin: false, @@ -258,6 +259,23 @@ describe('CLI', () => { ); }); + it('reports descriptionless disables', async () => { + await cli([ + '--report-descriptionless-disables', + '--config', + replaceBackslashes(path.join(fixturesPath, 'config-block-no-empty.json')), + replaceBackslashes(path.join(fixturesPath, 'empty-block-with-relevant-disable.css')), + ]); + + expect(process.exitCode).toBe(2); + + expect(process.stdout.write).toHaveBeenCalledTimes(1); + expect(process.stdout.write).toHaveBeenNthCalledWith( + 1, + expect.stringContaining('descriptionless disable: block-no-empty'), + ); + }); + it('--stdin', async () => { await cli(['--stdin', '--config', `${fixturesPath}/config-no-empty-source.json`]); diff --git a/lib/__tests__/descriptionlessDisables.test.js b/lib/__tests__/descriptionlessDisables.test.js new file mode 100644 index 0000000000..d1983b83f3 --- /dev/null +++ b/lib/__tests__/descriptionlessDisables.test.js @@ -0,0 +1,62 @@ +'use strict'; + +const standalone = require('../standalone'); +const stripIndent = require('common-tags').stripIndent; + +it('descriptionlessDisables', () => { + const config = { + rules: { 'block-no-empty': true }, + }; + + const css = stripIndent` + /* stylelint-disable -- Description */ + a {} + /* stylelint-enable */ + a { + b {} /* stylelint-disable-line block-no-empty -- Description */ + } + /* stylelint-disable-next-line block-no-empty + * -- + * Description */ + a {} + + /* stylelint-disable */ + a {} + /* stylelint-enable */ + a { + b {} /* stylelint-disable-line block-no-empty */ + } + /* stylelint-disable-next-line block-no-empty */ + a {} + `; + + return standalone({ + config, + code: css, + reportDescriptionlessDisables: true, + }).then((linted) => { + const report = linted.descriptionlessDisables; + + expect(report).toHaveLength(1); + expect(report[0].ranges).toEqual([ + { + start: 12, + end: 14, + rule: 'all', + unusedRule: 'all', + }, + { + start: 16, + end: 16, + rule: 'block-no-empty', + unusedRule: 'block-no-empty', + }, + { + start: 19, + end: 19, + rule: 'block-no-empty', + unusedRule: 'block-no-empty', + }, + ]); + }); +}); diff --git a/lib/__tests__/disableRanges.test.js b/lib/__tests__/disableRanges.test.js index d31bea78e8..d30a669b82 100644 --- a/lib/__tests__/disableRanges.test.js +++ b/lib/__tests__/disableRanges.test.js @@ -653,6 +653,7 @@ it('disable (with description) without re-enabling', () => { { start: 1, strictStart: true, + description: 'Description', }, ], }); @@ -672,6 +673,7 @@ it('disable and re-enable (with descriptions)', () => { end: 4, strictStart: true, strictEnd: true, + description: 'Description', }, ], }); @@ -689,6 +691,7 @@ it('disable rule (with description) without re-enabling', () => { strictStart: true, end: undefined, strictEnd: undefined, + description: 'Description', }, ], }); @@ -706,18 +709,21 @@ it('disable rules (with description) with newline in rule list', () => { { start: 1, strictStart: true, + description: 'Description', }, ], 'hoo-hah': [ { start: 1, strictStart: true, + description: 'Description', }, ], slime: [ { start: 1, strictStart: true, + description: 'Description', }, ], }); @@ -741,6 +747,7 @@ it('SCSS // line-disabling comment (with description)', () => { end: 2, strictStart: true, strictEnd: true, + description: 'Description', }, ], }); @@ -767,6 +774,7 @@ it('SCSS // disable next-line comment (with multi-line description)', () => { end: 5, strictStart: true, strictEnd: true, + description: 'Long-winded description', }, ], }); @@ -790,6 +798,7 @@ it('Less // line-disabling comment (with description)', () => { end: 2, strictStart: true, strictEnd: true, + description: 'Description', }, ], }); @@ -816,6 +825,7 @@ it('Less // disable next-line comment (with multi-line description)', () => { end: 5, strictStart: true, strictEnd: true, + description: 'Long-winded description', }, ], }); diff --git a/lib/assignDisabledRanges.js b/lib/assignDisabledRanges.js index 0f1b4352ba..9405207f00 100644 --- a/lib/assignDisabledRanges.js +++ b/lib/assignDisabledRanges.js @@ -18,16 +18,18 @@ const ALL_RULES = 'all'; /** * @param {number} start * @param {boolean} strictStart + * @param {string|undefined} description * @param {number} [end] * @param {boolean} [strictEnd] * @returns {DisabledRange} */ -function createDisableRange(start, strictStart, end, strictEnd) { +function createDisableRange(start, strictStart, description, end, strictEnd) { return { start, end: end || undefined, strictStart, strictEnd: typeof strictEnd === 'boolean' ? strictEnd : undefined, + description, }; } @@ -106,9 +108,10 @@ module.exports = function (root, result) { function processDisableLineCommand(comment) { if (comment.source && comment.source.start) { const line = comment.source.start.line; + const description = getDescription(comment.text); getCommandRules(disableLineCommand, comment.text).forEach((ruleName) => { - disableLine(line, ruleName, comment); + disableLine(line, ruleName, comment, description); }); } } @@ -119,9 +122,10 @@ module.exports = function (root, result) { function processDisableNextLineCommand(comment) { if (comment.source && comment.source.end) { const line = comment.source.end.line; + const description = getDescription(comment.text); getCommandRules(disableNextLineCommand, comment.text).forEach((ruleName) => { - disableLine(line + 1, ruleName, comment); + disableLine(line + 1, ruleName, comment, description); }); } } @@ -130,8 +134,9 @@ module.exports = function (root, result) { * @param {number} line * @param {string} ruleName * @param {PostcssComment} comment + * @param {string|undefined} description */ - function disableLine(line, ruleName, comment) { + function disableLine(line, ruleName, comment, description) { if (ruleIsDisabled(ALL_RULES)) { throw comment.error('All rules have already been disabled', { plugin: 'stylelint', @@ -144,7 +149,7 @@ module.exports = function (root, result) { const strict = disabledRuleName === ALL_RULES; - startDisabledRange(line, disabledRuleName, strict); + startDisabledRange(line, disabledRuleName, strict, description); endDisabledRange(line, disabledRuleName, strict); }); } else { @@ -154,7 +159,7 @@ module.exports = function (root, result) { }); } - startDisabledRange(line, ruleName, true); + startDisabledRange(line, ruleName, true, description); endDisabledRange(line, ruleName, true); } } @@ -163,6 +168,8 @@ module.exports = function (root, result) { * @param {PostcssComment} comment */ function processDisableCommand(comment) { + const description = getDescription(comment.text); + getCommandRules(disableCommand, comment.text).forEach((ruleToDisable) => { const isAllRules = ruleToDisable === ALL_RULES; @@ -182,10 +189,10 @@ module.exports = function (root, result) { if (isAllRules) { Object.keys(disabledRanges).forEach((ruleName) => { - startDisabledRange(line, ruleName, ruleName === ALL_RULES); + startDisabledRange(line, ruleName, ruleName === ALL_RULES, description); }); } else { - startDisabledRange(line, ruleToDisable, true); + startDisabledRange(line, ruleToDisable, true, description); } } }); @@ -225,8 +232,8 @@ module.exports = function (root, result) { if (ruleIsDisabled(ALL_RULES) && disabledRanges[ruleToEnable] === undefined) { // Get a starting point from the where all rules were disabled if (!disabledRanges[ruleToEnable]) { - disabledRanges[ruleToEnable] = disabledRanges.all.map(({ start, end }) => - createDisableRange(start, false, end, false), + disabledRanges[ruleToEnable] = disabledRanges.all.map(({ start, end, description }) => + createDisableRange(start, false, description, end, false), ); } else { const range = _.last(disabledRanges[ALL_RULES]); @@ -297,13 +304,26 @@ module.exports = function (root, result) { return rules; } + /** + * @param {string} fullText + * @returns {string|undefined} + */ + function getDescription(fullText) { + const descriptionStart = fullText.indexOf('--'); + + if (descriptionStart === -1) return; + + return fullText.slice(descriptionStart + 2).trim(); + } + /** * @param {number} line * @param {string} ruleName * @param {boolean} strict + * @param {string|undefined} description */ - function startDisabledRange(line, ruleName, strict) { - const rangeObj = createDisableRange(line, strict); + function startDisabledRange(line, ruleName, strict, description) { + const rangeObj = createDisableRange(line, strict, description); ensureRuleRanges(ruleName); disabledRanges[ruleName].push(rangeObj); @@ -331,8 +351,8 @@ module.exports = function (root, result) { */ function ensureRuleRanges(ruleName) { if (!disabledRanges[ruleName]) { - disabledRanges[ruleName] = disabledRanges.all.map(({ start, end }) => - createDisableRange(start, false, end, false), + disabledRanges[ruleName] = disabledRanges.all.map(({ start, end, description }) => + createDisableRange(start, false, description, end, false), ); } } diff --git a/lib/cli.js b/lib/cli.js index 7c5a40608e..80189a7759 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -39,6 +39,7 @@ const EXIT_CODE_ERROR = 2; * @property {string} [stdinFilename] * @property {boolean} [reportNeedlessDisables] * @property {boolean} [reportInvalidScopeDisables] + * @property {boolean} [reportDescriptionlessDisables] * @property {number} [maxWarnings] * @property {string | boolean} quiet * @property {string} [syntax] @@ -73,6 +74,7 @@ const EXIT_CODE_ERROR = 2; * @property {string} [outputFile] * @property {boolean} [reportNeedlessDisables] * @property {boolean} [reportInvalidScopeDisables] + * @property {boolean} [reportDescriptionlessDisables] * @property {boolean} [disableDefaultIgnores] * @property {number} [maxWarnings] * @property {string} [syntax] @@ -204,6 +206,11 @@ const meowOptions = { Report stylelint-disable comments that used for rules that don't exist within the configuration object. The process will exit with code ${EXIT_CODE_ERROR} if invalid scope disables are found. + --report-descriptionless-disables, --rdd + + Report stylelint-disable comments without a description. + The process will exit with code ${EXIT_CODE_ERROR} if descriptionless disables are found. + --max-warnings, --mw Number of warnings above which the process will exit with code ${EXIT_CODE_ERROR}. @@ -292,6 +299,10 @@ const meowOptions = { alias: 'q', type: 'boolean', }, + reportDescriptionlessDisables: { + alias: 'rdd', + type: 'boolean', + }, reportInvalidScopeDisables: { alias: 'risd', type: 'boolean', @@ -417,6 +428,7 @@ module.exports = (argv) => { const reportNeedlessDisables = cli.flags.reportNeedlessDisables; const reportInvalidScopeDisables = cli.flags.reportInvalidScopeDisables; + const reportDescriptionlessDisables = cli.flags.reportDescriptionlessDisables; if (reportNeedlessDisables) { optionsBase.reportNeedlessDisables = reportNeedlessDisables; @@ -426,6 +438,10 @@ module.exports = (argv) => { optionsBase.reportInvalidScopeDisables = reportInvalidScopeDisables; } + if (reportDescriptionlessDisables) { + optionsBase.reportDescriptionlessDisables = reportDescriptionlessDisables; + } + const maxWarnings = cli.flags.maxWarnings; if (maxWarnings !== undefined) { @@ -510,6 +526,17 @@ module.exports = (argv) => { } } + if (reportDescriptionlessDisables) { + const report = disableOptionsReportStringFormatter( + linted.descriptionlessDisables || [], + 'descriptionless disable', + ); + + if (report) { + reports.push(report); + } + } + if (reports.length > 0) { reports.forEach((report) => process.stdout.write(report)); process.exitCode = EXIT_CODE_ERROR; diff --git a/lib/descriptionlessDisables.js b/lib/descriptionlessDisables.js new file mode 100644 index 0000000000..6bfb634cce --- /dev/null +++ b/lib/descriptionlessDisables.js @@ -0,0 +1,52 @@ +'use strict'; + +/** @typedef {import('stylelint').RangeType} RangeType */ +/** @typedef {import('stylelint').DisableReportRange} DisableReportRange */ +/** @typedef {import('stylelint').StylelintDisableOptionsReport} StylelintDisableOptionsReport */ + +/** + * @param {import('stylelint').StylelintResult[]} results + * @returns {StylelintDisableOptionsReport} + */ +module.exports = function (results) { + /** @type {StylelintDisableOptionsReport} */ + const report = []; + + results.forEach((result) => { + // File with `CssSyntaxError` have not `_postcssResult` + if (!result._postcssResult) { + return; + } + + const rangeData = result._postcssResult.stylelint.disabledRanges; + + /** @type {import('stylelint').StylelintDisableReportEntry} */ + const entry = { source: result.source, ranges: [] }; + + Object.keys(rangeData).forEach((rule) => { + rangeData[rule].forEach((range) => { + if (range.description) return; + + // Avoid duplicates from stylelint-disable comments with multiple rules. + const alreadyReported = entry.ranges.find((existing) => { + return existing.start === range.start && existing.end === range.end; + }); + + if (alreadyReported) return; + + entry.ranges.push({ + rule, + start: range.start, + end: range.end, + unusedRule: rule, + }); + }); + }); + + if (entry.ranges.length > 0) { + report.push(entry); + } + }); + + return report; +}; diff --git a/lib/prepareReturnValue.js b/lib/prepareReturnValue.js index 2153c4c1de..9319433cb2 100644 --- a/lib/prepareReturnValue.js +++ b/lib/prepareReturnValue.js @@ -1,5 +1,6 @@ 'use strict'; +const descriptionlessDisables = require('./descriptionlessDisables'); const invalidScopeDisables = require('./invalidScopeDisables'); const needlessDisables = require('./needlessDisables'); const reportDisables = require('./reportDisables'); @@ -17,7 +18,12 @@ const reportDisables = require('./reportDisables'); * @returns {StylelintStandaloneReturnValue} */ function prepareReturnValue(stylelintResults, options, formatter) { - const { reportNeedlessDisables, reportInvalidScopeDisables, maxWarnings } = options; + const { + reportNeedlessDisables, + reportInvalidScopeDisables, + reportDescriptionlessDisables, + maxWarnings, + } = options; const errored = stylelintResults.some( (result) => result.errored || result.parseErrors.length > 0, @@ -39,6 +45,10 @@ function prepareReturnValue(stylelintResults, options, formatter) { returnValue.invalidScopeDisables = invalidScopeDisables(stylelintResults); } + if (reportDescriptionlessDisables) { + returnValue.descriptionlessDisables = descriptionlessDisables(stylelintResults); + } + if (maxWarnings !== undefined) { const foundWarnings = stylelintResults.reduce((count, file) => { return count + file.warnings.length; diff --git a/lib/standalone.js b/lib/standalone.js index 34190d312b..16d84aa9bb 100644 --- a/lib/standalone.js +++ b/lib/standalone.js @@ -47,6 +47,7 @@ module.exports = function (options) { const ignoreDisables = options.ignoreDisables; const reportNeedlessDisables = options.reportNeedlessDisables; const reportInvalidScopeDisables = options.reportInvalidScopeDisables; + const reportDescriptionlessDisables = options.reportDescriptionlessDisables; const syntax = options.syntax; const allowEmptyInput = options.allowEmptyInput || false; const useCache = options.cache || false; @@ -95,6 +96,7 @@ module.exports = function (options) { ignorePath: ignoreFilePath, reportNeedlessDisables, reportInvalidScopeDisables, + reportDescriptionlessDisables, syntax, customSyntax, fix, diff --git a/types/stylelint/index.d.ts b/types/stylelint/index.d.ts index 7ee82c577a..800abaa67e 100644 --- a/types/stylelint/index.d.ts +++ b/types/stylelint/index.d.ts @@ -36,6 +36,7 @@ declare module 'stylelint' { end?: number; strictEnd?: boolean; rules?: string[]; + description?: string; }; export type DisabledRangeObject = { @@ -53,6 +54,7 @@ declare module 'stylelint' { ignored?: boolean; ignoreDisables?: boolean; reportNeedlessDisables?: boolean; + reportDescriptionlessDisables?: boolean; stylelintError?: boolean; disableWritingFix?: boolean; config?: StylelintConfig; @@ -101,6 +103,7 @@ declare module 'stylelint' { ignorePath?: string; reportInvalidScopeDisables?: boolean; reportNeedlessDisables?: boolean; + reportDescriptionlessDisables?: boolean; syntax?: string; customSyntax?: CustomSyntax; fix?: boolean; @@ -164,6 +167,7 @@ declare module 'stylelint' { ignoreDisables?: boolean; ignorePath?: string; ignorePattern?: string[]; + reportDescriptionlessDisables?: boolean; reportNeedlessDisables?: boolean; reportInvalidScopeDisables?: boolean; maxWarnings?: number; @@ -243,6 +247,7 @@ declare module 'stylelint' { foundWarnings: number; }; reportedDisables: StylelintDisableOptionsReport; + descriptionlessDisables?: StylelintDisableOptionsReport; needlessDisables?: StylelintDisableOptionsReport; invalidScopeDisables?: StylelintDisableOptionsReport; }; From 3cfc6589f6ef3c5fb57c67a4caadbee975f53a76 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Mon, 31 Aug 2020 11:52:15 +0100 Subject: [PATCH 24/34] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e916fab15f..cca0776ed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,9 @@ All notable changes to this project are documented in this file. ## Head - Added: syntax object acceptance to `customSyntax` option ([#4839](https://github.com/stylelint/stylelint/pull/4839)). -- Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). - Added: support for `*.cjs` config files ([#4905](https://github.com/stylelint/stylelint/pull/4905)). +- Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). +- Added: `reportDescriptionlessDisables` flag ([#4907](https://github.com/stylelint/stylelint/pull/4907)). - Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). - Added: `*-no-vendor-prefix` autofix ([#4859](https://github.com/stylelint/stylelint/pull/4859)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). From 181f3d9eea930dccdd52def1cd616ecb5a92197a Mon Sep 17 00:00:00 2001 From: Mike Allanson Date: Mon, 31 Aug 2020 12:08:09 +0100 Subject: [PATCH 25/34] Fix some path / glob problems (#4867) --- .../globs/[digit]/not-digits/styles.css | 1 + .../fixtures/globs/extglob!(s)/styles.css | 1 + .../fixtures/globs/glob+chars/glob-plus.css | 1 + .../globs/glob-contains-plus/styles.css | 1 + .../globs/got!negate/negate/styles.css | 1 + .../globs/got[braces] and (spaces)/styles.css | 1 + .../negated-globs/ignore/ignore-this-file.css | 1 + .../globs/negated-globs/lint-this-file.css | 1 + .../fixtures/globs/with spaces/styles.css | 1 + lib/__tests__/standalone-globs.test.js | 193 ++++++++++++++++++ lib/standalone.js | 15 ++ package.json | 1 + 12 files changed, 218 insertions(+) create mode 100644 lib/__tests__/fixtures/globs/[digit]/not-digits/styles.css create mode 100644 lib/__tests__/fixtures/globs/extglob!(s)/styles.css create mode 100644 lib/__tests__/fixtures/globs/glob+chars/glob-plus.css create mode 100644 lib/__tests__/fixtures/globs/glob-contains-plus/styles.css create mode 100644 lib/__tests__/fixtures/globs/got!negate/negate/styles.css create mode 100644 lib/__tests__/fixtures/globs/got[braces] and (spaces)/styles.css create mode 100644 lib/__tests__/fixtures/globs/negated-globs/ignore/ignore-this-file.css create mode 100644 lib/__tests__/fixtures/globs/negated-globs/lint-this-file.css create mode 100644 lib/__tests__/fixtures/globs/with spaces/styles.css create mode 100644 lib/__tests__/standalone-globs.test.js diff --git a/lib/__tests__/fixtures/globs/[digit]/not-digits/styles.css b/lib/__tests__/fixtures/globs/[digit]/not-digits/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/[digit]/not-digits/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/extglob!(s)/styles.css b/lib/__tests__/fixtures/globs/extglob!(s)/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/extglob!(s)/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/glob+chars/glob-plus.css b/lib/__tests__/fixtures/globs/glob+chars/glob-plus.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/glob+chars/glob-plus.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/glob-contains-plus/styles.css b/lib/__tests__/fixtures/globs/glob-contains-plus/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/glob-contains-plus/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/got!negate/negate/styles.css b/lib/__tests__/fixtures/globs/got!negate/negate/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/got!negate/negate/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/got[braces] and (spaces)/styles.css b/lib/__tests__/fixtures/globs/got[braces] and (spaces)/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/got[braces] and (spaces)/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/negated-globs/ignore/ignore-this-file.css b/lib/__tests__/fixtures/globs/negated-globs/ignore/ignore-this-file.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/negated-globs/ignore/ignore-this-file.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/negated-globs/lint-this-file.css b/lib/__tests__/fixtures/globs/negated-globs/lint-this-file.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/negated-globs/lint-this-file.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/fixtures/globs/with spaces/styles.css b/lib/__tests__/fixtures/globs/with spaces/styles.css new file mode 100644 index 0000000000..077f6dd7c0 --- /dev/null +++ b/lib/__tests__/fixtures/globs/with spaces/styles.css @@ -0,0 +1 @@ +a {} diff --git a/lib/__tests__/standalone-globs.test.js b/lib/__tests__/standalone-globs.test.js new file mode 100644 index 0000000000..2f3f486287 --- /dev/null +++ b/lib/__tests__/standalone-globs.test.js @@ -0,0 +1,193 @@ +'use strict'; + +/* eslint-disable node/no-extraneous-require */ + +const describe = require('@jest/globals').describe; +const expect = require('@jest/globals').expect; +const it = require('@jest/globals').it; + +/* eslint-enable */ + +const path = require('path'); +const replaceBackslashes = require('../testUtils/replaceBackslashes'); +const standalone = require('../standalone'); + +const fixturesPath = replaceBackslashes(path.join(__dirname, 'fixtures', 'globs')); + +// Tests for https://github.com/stylelint/stylelint/issues/4521 + +describe('standalone globbing', () => { + describe('paths with special characters', () => { + // ref https://github.com/micromatch/micromatch#matching-features + const fixtureDirs = [ + `[digit]/not-digits`, + `with spaces`, + `extglob!(s)`, + `got!negate/negate`, + // `extglob+(s)`, // Note: +'s cause errors. Ignoring until it becomes a problem + ]; + + // https://github.com/stylelint/stylelint/issues/4193 + it.each(fixtureDirs)(`static path contains "%s"`, async (fixtureDir) => { + const cssPath = `${fixturesPath}/${fixtureDir}/styles.css`; + + const { results } = await standalone({ + files: cssPath, + config: { rules: { 'block-no-empty': true } }, + }); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + }); + + // https://github.com/stylelint/stylelint/issues/4211 + it('glob has no + character, matched path does', async () => { + const files = `${fixturesPath}/**/glob-plus.css`; // file is in dir 'glob+chars' + + const { results } = await standalone({ + files, + config: { rules: { 'block-no-empty': true } }, + }); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + + // https://github.com/stylelint/stylelint/issues/4211 + it('glob contains + character, matched path does not', async () => { + const files = `${fixturesPath}/+(g)lob-contains-plus/*.css`; + + const { results } = await standalone({ + files, + config: { rules: { 'block-no-empty': true } }, + }); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + + // https://github.com/stylelint/stylelint/issues/3272 + // should ignore 'negated-globs/ignore/styles.css' + it('negated glob patterns', async () => { + const files = [ + `${fixturesPath}/negated-globs/**/*.css`, + `!${fixturesPath}/negated-globs/ignore/**/*.css`, + ]; + + const { results } = await standalone({ + files, + config: { rules: { 'block-no-empty': true } }, + }); + + // ensure that the only result is from the unignored file + expect(results[0].source).toEqual(expect.stringContaining('lint-this-file.css')); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + + describe('mixed globs and paths with special chars', () => { + it('manual escaping', async () => { + const cssGlob = `${fixturesPath}/got\\[braces\\] and \\(spaces\\)/*.+(s|c)ss`; + + const { results } = await standalone({ + files: cssGlob, + config: { + rules: { + 'block-no-empty': true, + }, + }, + }); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + + it('setting "cwd" in globbyOptions', async () => { + const cssGlob = `*.+(s|c)ss`; + + const { results } = await standalone({ + files: cssGlob, + config: { + rules: { + 'block-no-empty': true, + }, + }, + globbyOptions: { + cwd: `${fixturesPath}/got[braces] and (spaces)/`, + }, + }); + + expect(results).toHaveLength(1); + expect(results[0].errored).toEqual(true); + expect(results[0].warnings[0]).toEqual( + expect.objectContaining({ + rule: 'block-no-empty', + severity: 'error', + }), + ); + }); + + /* eslint-disable jest/no-commented-out-tests -- Failing case for reference. Documents behaviour that doesn't work. */ + + // Note: This fails because there's no way to tell which parts of the glob are literal characters, and which are special globbing characters. + // + // 'got[braces] and (spaces)' is a literal directory path. `*.+(s|c)ss` is a glob. + + // https://github.com/stylelint/stylelint/issues/4855 + // it('glob and matched path contain different special chars, complex example', async () => { + // const cssGlob = `${fixturesPath}/got[braces] and (spaces)/*.+(s|c)ss`; + + // const { results } = await standalone({ + // files: cssGlob, + // config: { + // rules: { + // 'block-no-empty': true, + // }, + // }, + // }); + + // expect(results).toHaveLength(1); + // expect(results[0].errored).toEqual(true); + // expect(results[0].warnings[0]).toEqual( + // expect.objectContaining({ + // rule: 'block-no-empty', + // severity: 'error', + // }), + // ); + // }); + + /* eslint-enable */ + }); +}); diff --git a/lib/standalone.js b/lib/standalone.js index 16d84aa9bb..e92d9c1946 100644 --- a/lib/standalone.js +++ b/lib/standalone.js @@ -4,6 +4,7 @@ const _ = require('lodash'); const createStylelint = require('./createStylelint'); const createStylelintResult = require('./createStylelintResult'); const debug = require('debug')('stylelint:standalone'); +const fastGlob = require('fast-glob'); const FileCache = require('./utils/FileCache'); const filterFilePaths = require('./utils/filterFilePaths'); const formatters = require('./formatters'); @@ -170,6 +171,20 @@ module.exports = function (options) { fileList = [fileList]; } + fileList = fileList.map((entry) => { + if (globby.hasMagic(entry)) { + const cwd = _.get(globbyOptions, 'cwd', process.cwd()); + const absolutePath = !path.isAbsolute(entry) ? path.join(cwd, entry) : path.normalize(entry); + + if (fs.existsSync(absolutePath)) { + // This glob-like path points to a file. Return an escaped path to avoid globbing + return fastGlob.escapePath(entry); + } + } + + return entry; + }); + if (!options.disableDefaultIgnores) { fileList = fileList.concat(ALWAYS_IGNORED_GLOBS.map((glob) => `!${glob}`)); } diff --git a/package.json b/package.json index 8283cc81d2..b91ac5aec3 100644 --- a/package.json +++ b/package.json @@ -118,6 +118,7 @@ "cosmiconfig": "^7.0.0", "debug": "^4.1.1", "execall": "^2.0.0", + "fast-glob": "^3.2.4", "fastest-levenshtein": "^1.0.9", "file-entry-cache": "^5.0.1", "get-stdin": "^8.0.0", From 2b7e8ad8b43634c9d75a229ac29b3cb2e0d008ac Mon Sep 17 00:00:00 2001 From: Kevin Dew Date: Mon, 31 Aug 2020 12:09:06 +0100 Subject: [PATCH 26/34] Deprecate *-blacklist/*-requirelist/*-whitelist (#4892) * Make copies for *-blacklist/*-requirelist/*-whitelist rules As discussed in issue #4854, the desired approach is to deprecate the *-blacklist/*-requirelist/*-whitelist rules. The first step I've taken to doing this is to make copies of all the rules. The commands used to generate this commit were: - find . -name '*-allowed-list' -exec sh -c 'cp -R "$1" "${1%-allowed-list}-whitelist"' _ {} \; - find . -name '*-disallowed-list' -exec sh -c 'cp -R "$1" "${1%-disallowed-list}-blacklist"' _ {} \; - find . -name '*-required-list' -exec sh -c 'cp -R "$1" "${1%-required-list}-requirelist"' _ {} \; * Re-instate *-blacklist/*-requirelist/*-whitelist rules The aliasing approach taken for these rule renaming presented user experience problems [1]. To resolve these problems the preference is to revert on the aliasing strategy and instead return to a deprecation strategy. The first step towards this is re-instating these rules. As per the preference of jeddy3 [2] these rules are re-instated using a copy and paste strategy, with the expectation these will be removed in the next major release. An approach that didn't involve copy and pasting was previously introduced in [3] and could be looked at again if maintaining this duplicate code proves problematic. [1]: https://github.com/stylelint/stylelint/issues/4854#issuecomment-654332844 [2]: https://github.com/stylelint/stylelint/issues/4854#issuecomment-670935654 [3]: https://github.com/stylelint/stylelint/commit/e93e44c938d77021eec4893fc20327337a60d49f * Deprecate *-blacklist/*-requirelist/*-whitelist rules This applies deprecation warnings when these rules are used, tests to check there is a deprecation warning and re-includes them in documentation. * Deprecation links point to GitHub tag This reflects the documentation on deprecating stylelint rules [1] by linking to the GitHub website rather than stylelint website, so that the link can continue operating indefinitely. As suggested in the PR [2] these have been linked to the anticipated next release of stylelint, so these links will not be actually operational until this tag is made. [1]: https://github.com/stylelint/stylelint/blob/858dcd584224042654d80ce8fa8ad71f41f20808/docs/developer-guide/rules.md#deprecate-a-rule [2]: https://github.com/stylelint/stylelint/pull/4892#issuecomment-679375149 --- docs/user-guide/rules/list.md | 26 + lib/__tests__/aliasedRules.test.js | 41 -- lib/__tests__/integration.test.js | 13 - lib/rules/at-rule-allowed-list/README.md | 2 - lib/rules/at-rule-blacklist/README.md | 52 ++ .../at-rule-blacklist/__tests__/index.js | 197 ++++++ lib/rules/at-rule-blacklist/index.js | 62 ++ lib/rules/at-rule-disallowed-list/README.md | 2 - .../at-rule-property-required-list/README.md | 2 - .../at-rule-property-requirelist/README.md | 55 ++ .../__tests__/index.js | 84 +++ .../at-rule-property-requirelist/index.js | 73 +++ lib/rules/at-rule-whitelist/README.md | 67 +++ .../at-rule-whitelist/__tests__/index.js | 190 ++++++ lib/rules/at-rule-whitelist/index.js | 62 ++ lib/rules/comment-word-blacklist/README.md | 50 ++ .../comment-word-blacklist/__tests__/index.js | 347 +++++++++++ lib/rules/comment-word-blacklist/index.js | 64 ++ .../comment-word-disallowed-list/README.md | 2 - .../README.md | 2 - .../README.md | 76 +++ .../__tests__/index.js | 195 ++++++ .../index.js | 84 +++ .../README.md | 2 - .../README.md | 87 +++ .../__tests__/index.js | 200 +++++++ .../index.js | 84 +++ .../README.md | 2 - .../README.md | 107 ++++ .../__tests__/index.js | 210 +++++++ .../index.js | 66 ++ .../README.md | 2 - .../README.md | 98 +++ .../__tests__/index.js | 101 ++++ .../index.js | 66 ++ lib/rules/function-allowed-list/README.md | 2 - lib/rules/function-blacklist/README.md | 54 ++ .../function-blacklist/__tests__/index.js | 243 ++++++++ lib/rules/function-blacklist/index.js | 69 +++ lib/rules/function-disallowed-list/README.md | 2 - .../README.md | 2 - .../function-url-scheme-blacklist/README.md | 73 +++ .../__tests__/index.js | 280 +++++++++ .../function-url-scheme-blacklist/index.js | 74 +++ .../README.md | 2 - .../function-url-scheme-whitelist/README.md | 78 +++ .../__tests__/index.js | 342 +++++++++++ .../function-url-scheme-whitelist/index.js | 74 +++ lib/rules/function-whitelist/README.md | 75 +++ .../function-whitelist/__tests__/index.js | 204 +++++++ lib/rules/function-whitelist/index.js | 71 +++ lib/rules/index.js | 90 +-- .../media-feature-name-allowed-list/README.md | 2 - .../media-feature-name-blacklist/README.md | 66 ++ .../__tests__/index.js | 228 +++++++ .../media-feature-name-blacklist/index.js | 84 +++ .../README.md | 2 - .../README.md | 2 - .../README.md | 86 +++ .../__tests__/index.js | 195 ++++++ .../index.js | 97 +++ .../media-feature-name-whitelist/README.md | 66 ++ .../__tests__/index.js | 218 +++++++ .../media-feature-name-whitelist/index.js | 84 +++ lib/rules/property-allowed-list/README.md | 2 - lib/rules/property-blacklist/README.md | 66 ++ .../property-blacklist/__tests__/index.js | 182 ++++++ lib/rules/property-blacklist/index.js | 65 ++ lib/rules/property-disallowed-list/README.md | 2 - lib/rules/property-whitelist/README.md | 77 +++ .../property-whitelist/__tests__/index.js | 191 ++++++ lib/rules/property-whitelist/index.js | 65 ++ .../README.md | 2 - .../README.md | 46 ++ .../__tests__/index.js | 114 ++++ .../index.js | 73 +++ .../README.md | 2 - .../README.md | 56 ++ .../__tests__/index.js | 120 ++++ .../index.js | 73 +++ .../README.md | 2 - .../selector-combinator-blacklist/README.md | 56 ++ .../__tests__/index.js | 88 +++ .../selector-combinator-blacklist/index.js | 78 +++ .../README.md | 2 - .../selector-combinator-whitelist/README.md | 56 ++ .../__tests__/index.js | 113 ++++ .../selector-combinator-whitelist/index.js | 78 +++ .../README.md | 2 - .../selector-pseudo-class-blacklist/README.md | 55 ++ .../__tests__/index.js | 247 ++++++++ .../selector-pseudo-class-blacklist/index.js | 83 +++ .../README.md | 2 - .../selector-pseudo-class-whitelist/README.md | 55 ++ .../__tests__/index.js | 196 ++++++ .../selector-pseudo-class-whitelist/index.js | 82 +++ .../README.md | 2 - .../README.md | 56 ++ .../__tests__/index.js | 126 ++++ .../index.js | 82 +++ .../README.md | 2 - .../README.md | 56 ++ .../__tests__/index.js | 148 +++++ .../index.js | 82 +++ lib/rules/unit-allowed-list/README.md | 2 - lib/rules/unit-blacklist/README.md | 161 +++++ lib/rules/unit-blacklist/__tests__/index.js | 563 ++++++++++++++++++ lib/rules/unit-blacklist/index.js | 130 ++++ lib/rules/unit-disallowed-list/README.md | 2 - lib/rules/unit-whitelist/README.md | 117 ++++ lib/rules/unit-whitelist/__tests__/index.js | 365 ++++++++++++ lib/rules/unit-whitelist/index.js | 90 +++ lib/utils/__tests__/checkAgainstRule.test.js | 20 - 113 files changed, 9782 insertions(+), 191 deletions(-) delete mode 100644 lib/__tests__/aliasedRules.test.js create mode 100644 lib/rules/at-rule-blacklist/README.md create mode 100644 lib/rules/at-rule-blacklist/__tests__/index.js create mode 100644 lib/rules/at-rule-blacklist/index.js create mode 100644 lib/rules/at-rule-property-requirelist/README.md create mode 100644 lib/rules/at-rule-property-requirelist/__tests__/index.js create mode 100644 lib/rules/at-rule-property-requirelist/index.js create mode 100644 lib/rules/at-rule-whitelist/README.md create mode 100644 lib/rules/at-rule-whitelist/__tests__/index.js create mode 100644 lib/rules/at-rule-whitelist/index.js create mode 100644 lib/rules/comment-word-blacklist/README.md create mode 100644 lib/rules/comment-word-blacklist/__tests__/index.js create mode 100644 lib/rules/comment-word-blacklist/index.js create mode 100644 lib/rules/declaration-property-unit-blacklist/README.md create mode 100644 lib/rules/declaration-property-unit-blacklist/__tests__/index.js create mode 100644 lib/rules/declaration-property-unit-blacklist/index.js create mode 100644 lib/rules/declaration-property-unit-whitelist/README.md create mode 100644 lib/rules/declaration-property-unit-whitelist/__tests__/index.js create mode 100644 lib/rules/declaration-property-unit-whitelist/index.js create mode 100644 lib/rules/declaration-property-value-blacklist/README.md create mode 100644 lib/rules/declaration-property-value-blacklist/__tests__/index.js create mode 100644 lib/rules/declaration-property-value-blacklist/index.js create mode 100644 lib/rules/declaration-property-value-whitelist/README.md create mode 100644 lib/rules/declaration-property-value-whitelist/__tests__/index.js create mode 100644 lib/rules/declaration-property-value-whitelist/index.js create mode 100644 lib/rules/function-blacklist/README.md create mode 100644 lib/rules/function-blacklist/__tests__/index.js create mode 100644 lib/rules/function-blacklist/index.js create mode 100644 lib/rules/function-url-scheme-blacklist/README.md create mode 100644 lib/rules/function-url-scheme-blacklist/__tests__/index.js create mode 100644 lib/rules/function-url-scheme-blacklist/index.js create mode 100644 lib/rules/function-url-scheme-whitelist/README.md create mode 100644 lib/rules/function-url-scheme-whitelist/__tests__/index.js create mode 100644 lib/rules/function-url-scheme-whitelist/index.js create mode 100644 lib/rules/function-whitelist/README.md create mode 100644 lib/rules/function-whitelist/__tests__/index.js create mode 100644 lib/rules/function-whitelist/index.js create mode 100644 lib/rules/media-feature-name-blacklist/README.md create mode 100644 lib/rules/media-feature-name-blacklist/__tests__/index.js create mode 100644 lib/rules/media-feature-name-blacklist/index.js create mode 100644 lib/rules/media-feature-name-value-whitelist/README.md create mode 100644 lib/rules/media-feature-name-value-whitelist/__tests__/index.js create mode 100644 lib/rules/media-feature-name-value-whitelist/index.js create mode 100644 lib/rules/media-feature-name-whitelist/README.md create mode 100644 lib/rules/media-feature-name-whitelist/__tests__/index.js create mode 100644 lib/rules/media-feature-name-whitelist/index.js create mode 100644 lib/rules/property-blacklist/README.md create mode 100644 lib/rules/property-blacklist/__tests__/index.js create mode 100644 lib/rules/property-blacklist/index.js create mode 100644 lib/rules/property-whitelist/README.md create mode 100644 lib/rules/property-whitelist/__tests__/index.js create mode 100644 lib/rules/property-whitelist/index.js create mode 100644 lib/rules/selector-attribute-operator-blacklist/README.md create mode 100644 lib/rules/selector-attribute-operator-blacklist/__tests__/index.js create mode 100644 lib/rules/selector-attribute-operator-blacklist/index.js create mode 100644 lib/rules/selector-attribute-operator-whitelist/README.md create mode 100644 lib/rules/selector-attribute-operator-whitelist/__tests__/index.js create mode 100644 lib/rules/selector-attribute-operator-whitelist/index.js create mode 100644 lib/rules/selector-combinator-blacklist/README.md create mode 100644 lib/rules/selector-combinator-blacklist/__tests__/index.js create mode 100644 lib/rules/selector-combinator-blacklist/index.js create mode 100644 lib/rules/selector-combinator-whitelist/README.md create mode 100644 lib/rules/selector-combinator-whitelist/__tests__/index.js create mode 100644 lib/rules/selector-combinator-whitelist/index.js create mode 100644 lib/rules/selector-pseudo-class-blacklist/README.md create mode 100644 lib/rules/selector-pseudo-class-blacklist/__tests__/index.js create mode 100644 lib/rules/selector-pseudo-class-blacklist/index.js create mode 100644 lib/rules/selector-pseudo-class-whitelist/README.md create mode 100644 lib/rules/selector-pseudo-class-whitelist/__tests__/index.js create mode 100644 lib/rules/selector-pseudo-class-whitelist/index.js create mode 100644 lib/rules/selector-pseudo-element-blacklist/README.md create mode 100644 lib/rules/selector-pseudo-element-blacklist/__tests__/index.js create mode 100644 lib/rules/selector-pseudo-element-blacklist/index.js create mode 100644 lib/rules/selector-pseudo-element-whitelist/README.md create mode 100644 lib/rules/selector-pseudo-element-whitelist/__tests__/index.js create mode 100644 lib/rules/selector-pseudo-element-whitelist/index.js create mode 100644 lib/rules/unit-blacklist/README.md create mode 100644 lib/rules/unit-blacklist/__tests__/index.js create mode 100644 lib/rules/unit-blacklist/index.js create mode 100644 lib/rules/unit-whitelist/README.md create mode 100644 lib/rules/unit-whitelist/__tests__/index.js create mode 100644 lib/rules/unit-whitelist/index.js diff --git a/docs/user-guide/rules/list.md b/docs/user-guide/rules/list.md index 6cd7c29dd7..9c4f023149 100644 --- a/docs/user-guide/rules/list.md +++ b/docs/user-guide/rules/list.md @@ -102,10 +102,14 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Function - [`function-allowed-list`](../../../lib/rules/function-allowed-list/README.md): Specify a list of allowed functions. +- [`function-blacklist`](../../../lib/rules/function-blacklist/README.md): Specify a list of disallowed functions. **(deprecated)** - [`function-disallowed-list`](../../../lib/rules/function-disallowed-list/README.md): Specify a list of disallowed functions. - [`function-url-no-scheme-relative`](../../../lib/rules/function-url-no-scheme-relative/README.md): Disallow scheme-relative urls. - [`function-url-scheme-allowed-list`](../../../lib/rules/function-url-scheme-allowed-list/README.md): Specify a list of allowed URL schemes. +- [`function-url-scheme-blacklist`](../../../lib/rules/function-url-scheme-blacklist/README.md): Specify a list of disallowed URL schemes. **(deprecated)** - [`function-url-scheme-disallowed-list`](../../../lib/rules/function-url-scheme-disallowed-list/README.md): Specify a list of disallowed URL schemes. +- [`function-url-scheme-whitelist`](../../../lib/rules/function-url-scheme-whitelist/README.md): Specify a list of allowed URL schemes. **(deprecated)** +- [`function-whitelist`](../../../lib/rules/function-whitelist/README.md): Specify a list of allowed functions. **(deprecated)** ### Keyframes @@ -122,7 +126,9 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Unit - [`unit-allowed-list`](../../../lib/rules/unit-allowed-list/README.md): Specify a list of allowed units. +- [`unit-blacklist`](../../../lib/rules/unit-blacklist/README.md): Specify a list of disallowed units. **(deprecated)** - [`unit-disallowed-list`](../../../lib/rules/unit-disallowed-list/README.md): Specify a list of disallowed units. +- [`unit-whitelist`](../../../lib/rules/unit-whitelist/README.md): Specify a list of allowed units. **(deprecated)** ### Shorthand property @@ -139,17 +145,23 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Property - [`property-allowed-list`](../../../lib/rules/property-allowed-list/README.md): Specify a list of allowed properties. +- [`property-blacklist`](../../../lib/rules/property-blacklist/README.md): Specify a list of disallowed properties. **(deprecated)** - [`property-disallowed-list`](../../../lib/rules/property-disallowed-list/README.md): Specify a list of disallowed properties. - [`property-no-vendor-prefix`](../../../lib/rules/property-no-vendor-prefix/README.md): Disallow vendor prefixes for properties (Autofixable). +- [`property-whitelist`](../../../lib/rules/property-whitelist/README.md): Specify a list of allowed properties. **(deprecated)** ### Declaration - [`declaration-block-no-redundant-longhand-properties`](../../../lib/rules/declaration-block-no-redundant-longhand-properties/README.md): Disallow longhand properties that can be combined into one shorthand property. - [`declaration-no-important`](../../../lib/rules/declaration-no-important/README.md): Disallow `!important` within declarations. - [`declaration-property-unit-allowed-list`](../../../lib/rules/declaration-property-unit-allowed-list/README.md): Specify a list of allowed property and unit pairs within declarations. +- [`declaration-property-unit-blacklist`](../../../lib/rules/declaration-property-unit-blacklist/README.md): Specify a list of disallowed property and unit pairs within declarations. **(deprecated)** - [`declaration-property-unit-disallowed-list`](../../../lib/rules/declaration-property-unit-disallowed-list/README.md): Specify a list of disallowed property and unit pairs within declarations. +- [`declaration-property-unit-whitelist`](../../../lib/rules/declaration-property-unit-whitelist/README.md): Specify a list of allowed property and unit pairs within declarations. **(deprecated)** - [`declaration-property-value-allowed-list`](../../../lib/rules/declaration-property-value-allowed-list/README.md): Specify a list of allowed property and value pairs within declarations. +- [`declaration-property-value-blacklist`](../../../lib/rules/declaration-property-value-blacklist/README.md): Specify a list of disallowed property and value pairs within declarations. **(deprecated)** - [`declaration-property-value-disallowed-list`](../../../lib/rules/declaration-property-value-disallowed-list/README.md): Specify a list of disallowed property and value pairs within declarations. +- [`declaration-property-value-whitelist`](../../../lib/rules/declaration-property-value-whitelist/README.md): Specify a list of allowed property and value pairs within declarations. **(deprecated)** ### Declaration block @@ -158,10 +170,14 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### Selector - [`selector-attribute-operator-allowed-list`](../../../lib/rules/selector-attribute-operator-allowed-list/README.md): Specify a list of allowed attribute operators. +- [`selector-attribute-operator-blacklist`](../../../lib/rules/selector-attribute-operator-blacklist/README.md): Specify a list of disallowed attribute operators. **(deprecated)** - [`selector-attribute-operator-disallowed-list`](../../../lib/rules/selector-attribute-operator-disallowed-list/README.md): Specify a list of disallowed attribute operators. +- [`selector-attribute-operator-whitelist`](../../../lib/rules/selector-attribute-operator-whitelist/README.md): Specify a list of allowed attribute operators. **(deprecated)** - [`selector-class-pattern`](../../../lib/rules/selector-class-pattern/README.md): Specify a pattern for class selectors. - [`selector-combinator-allowed-list`](../../../lib/rules/selector-combinator-allowed-list/README.md): Specify a list of allowed combinators. +- [`selector-combinator-blacklist`](../../../lib/rules/selector-combinator-blacklist/README.md): Specify a list of disallowed combinators. **(deprecated)** - [`selector-combinator-disallowed-list`](../../../lib/rules/selector-combinator-disallowed-list/README.md): Specify a list of disallowed combinators. +- [`selector-combinator-whitelist`](../../../lib/rules/selector-combinator-whitelist/README.md): Specify a list of allowed combinators. **(deprecated)** - [`selector-id-pattern`](../../../lib/rules/selector-id-pattern/README.md): Specify a pattern for ID selectors. - [`selector-max-attribute`](../../../lib/rules/selector-max-attribute/README.md): Limit the number of attribute selectors in a selector. - [`selector-max-class`](../../../lib/rules/selector-max-class/README.md): Limit the number of classes in a selector. @@ -177,17 +193,23 @@ Grouped first by the following categories and then by the [_thing_](http://apps. - [`selector-no-qualifying-type`](../../../lib/rules/selector-no-qualifying-type/README.md): Disallow qualifying a selector by type. - [`selector-no-vendor-prefix`](../../../lib/rules/selector-no-vendor-prefix/README.md): Disallow vendor prefixes for selectors (Autofixable). - [`selector-pseudo-class-allowed-list`](../../../lib/rules/selector-pseudo-class-allowed-list/README.md): Specify a list of allowed pseudo-class selectors. +- [`selector-pseudo-class-blacklist`](../../../lib/rules/selector-pseudo-class-blacklist/README.md): Specify a list of disallowed pseudo-class selectors. **(deprecated)** - [`selector-pseudo-class-disallowed-list`](../../../lib/rules/selector-pseudo-class-disallowed-list/README.md): Specify a list of disallowed pseudo-class selectors. +- [`selector-pseudo-class-whitelist`](../../../lib/rules/selector-pseudo-class-whitelist/README.md): Specify a list of allowed pseudo-class selectors. **(deprecated)** - [`selector-pseudo-element-allowed-list`](../../../lib/rules/selector-pseudo-element-allowed-list/README.md): Specify a list of allowed pseudo-element selectors. +- [`selector-pseudo-element-blacklist`](../../../lib/rules/selector-pseudo-element-blacklist/README.md): Specify a list of disallowed pseudo-element selectors. **(deprecated)** - [`selector-pseudo-element-colon-notation`](../../../lib/rules/selector-pseudo-element-colon-notation/README.md): Specify single or double colon notation for applicable pseudo-elements (Autofixable). - [`selector-pseudo-element-disallowed-list`](../../../lib/rules/selector-pseudo-element-disallowed-list/README.md): Specify a list of disallowed pseudo-element selectors. +- [`selector-pseudo-element-whitelist`](../../../lib/rules/selector-pseudo-element-whitelist/README.md): Specify a list of allowed pseudo-element selectors. **(deprecated)** ### Media feature - [`media-feature-name-allowed-list`](../../../lib/rules/media-feature-name-allowed-list/README.md): Specify a list of allowed media feature names. +- [`media-feature-name-blacklist`](../../../lib/rules/media-feature-name-blacklist/README.md): Specify a list of disallowed media feature names. **(deprecated)** - [`media-feature-name-disallowed-list`](../../../lib/rules/media-feature-name-disallowed-list/README.md): Specify a list of disallowed media feature names. - [`media-feature-name-no-vendor-prefix`](../../../lib/rules/media-feature-name-no-vendor-prefix/README.md): Disallow vendor prefixes for media feature names (Autofixable). - [`media-feature-name-value-allowed-list`](../../../lib/rules/media-feature-name-value-allowed-list/README.md): Specify a list of allowed media feature name and value pairs. +- [`media-feature-name-whitelist`](../../../lib/rules/media-feature-name-whitelist/README.md): Specify a list of allowed media feature names. **(deprecated)** ### Custom media @@ -196,12 +218,16 @@ Grouped first by the following categories and then by the [_thing_](http://apps. ### At-rule - [`at-rule-allowed-list`](../../../lib/rules/at-rule-allowed-list/README.md): Specify a list of allowed at-rules. +- [`at-rule-blacklist`](../../../lib/rules/at-rule-blacklist/README.md): Specify a list of disallowed at-rules. **(deprecated)** - [`at-rule-disallowed-list`](../../../lib/rules/at-rule-disallowed-list/README.md): Specify a list of disallowed at-rules. - [`at-rule-no-vendor-prefix`](../../../lib/rules/at-rule-no-vendor-prefix/README.md): Disallow vendor prefixes for at-rules (Autofixable). - [`at-rule-property-required-list`](../../../lib/rules/at-rule-property-required-list/README.md): Specify a list of required properties for an at-rule. +- [`at-rule-property-requirelist`](../../../lib/rules/at-rule-property-requirelist/README.md): Specify a list of required properties for an at-rule. **(deprecated)** +- [`at-rule-whitelist`](../../../lib/rules/at-rule-whitelist/README.md): Specify a list of allowed at-rules. **(deprecated)** ### Comment +- [`comment-word-blacklist`](../../../lib/rules/comment-word-blacklist/README.md): Specify a list of disallowed words within comments. **(deprecated)** - [`comment-word-disallowed-list`](../../../lib/rules/comment-word-disallowed-list/README.md): Specify a list of disallowed words within comments. ### General / Sheet diff --git a/lib/__tests__/aliasedRules.test.js b/lib/__tests__/aliasedRules.test.js deleted file mode 100644 index 50a2eecaa4..0000000000 --- a/lib/__tests__/aliasedRules.test.js +++ /dev/null @@ -1,41 +0,0 @@ -'use strict'; - -const rules = require('../rules'); - -const whitelistAndBlacklistRulePrefixes = [ - 'at-rule', - 'declaration-property-unit', - 'declaration-property-value', - 'function', - 'function-url-scheme', - 'media-feature-name', - 'property', - 'selector-attribute-operator', - 'selector-combinator', - 'selector-pseudo-class', - 'selector-pseudo-element', - 'unit', -]; - -const whitelistRulePrefixes = whitelistAndBlacklistRulePrefixes.concat([ - 'media-feature-name-value', -]); - -whitelistRulePrefixes.forEach((prefix) => { - it(`aliases ${prefix}-whitelist to ${prefix}-allowed-list`, () => - expect(rules[`${prefix}-whitelist`].ruleName).toEqual(`${prefix}-allowed-list`)); -}); - -const blacklistRulePrefixes = whitelistAndBlacklistRulePrefixes.concat(['comment-word']); - -blacklistRulePrefixes.forEach((prefix) => { - it(`aliases ${prefix}-blacklist to ${prefix}-disallowed-list`, () => - expect(rules[`${prefix}-blacklist`].ruleName).toEqual(`${prefix}-disallowed-list`)); -}); - -const requirelistRulePrefixes = ['at-rule-property']; - -requirelistRulePrefixes.forEach((prefix) => { - it(`aliases ${prefix}-requirelist to ${prefix}-required-list`, () => - expect(rules[`${prefix}-requirelist`].ruleName).toEqual(`${prefix}-required-list`)); -}); diff --git a/lib/__tests__/integration.test.js b/lib/__tests__/integration.test.js index df73623bf7..feddcbf36a 100644 --- a/lib/__tests__/integration.test.js +++ b/lib/__tests__/integration.test.js @@ -143,19 +143,6 @@ it('Scss integration test', () => { }); }); -it('rule aliasing integration test', () => { - return postcss() - .use(stylelint({ rules: { 'unit-blacklist': ['px'] } })) - .process('a { top: 10px; }', { from: undefined }) - .then((result) => { - const error = result.messages[0]; - - expect(error).toBeTruthy(); - expect(error.rule).toBe('unit-disallowed-list'); - expect(error.text).toBe('Unexpected unit "px" (unit-disallowed-list)'); - }); -}); - describe('integration test null option', () => { let results; diff --git a/lib/rules/at-rule-allowed-list/README.md b/lib/rules/at-rule-allowed-list/README.md index 8755baf322..995c21d40e 100644 --- a/lib/rules/at-rule-allowed-list/README.md +++ b/lib/rules/at-rule-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed at-rules. * At-rules like this */ ``` -This rule was previously called, and is aliased as, `at-rule-whitelist`. - ## Options `array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` diff --git a/lib/rules/at-rule-blacklist/README.md b/lib/rules/at-rule-blacklist/README.md new file mode 100644 index 0000000000..454160549b --- /dev/null +++ b/lib/rules/at-rule-blacklist/README.md @@ -0,0 +1,52 @@ +# at-rule-blacklist + +**_Deprecated: Instead use the [`at-rule-disallowed-list`](../at-rule-disallowed-list/README.md) rule._** + +Specify a list of disallowed at-rules. + + +```css + @keyframes name {} +/** ↑ + * At-rules like this */ +``` + +## Options + +`array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` + +Given: + +``` +["extend", "keyframes"] +``` + +The following patterns are considered violations: + + +```css +a { @extend placeholder; } +``` + + +```css +@keyframes name { + from { top: 10px; } + to { top: 20px; } +} +``` + + +```css +@-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } +} +``` + +The following patterns are _not_ considered violations: + + +```css +@import "path/to/file.css"; +``` diff --git a/lib/rules/at-rule-blacklist/__tests__/index.js b/lib/rules/at-rule-blacklist/__tests__/index.js new file mode 100644 index 0000000000..b7a1af7846 --- /dev/null +++ b/lib/rules/at-rule-blacklist/__tests__/index.js @@ -0,0 +1,197 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['extend'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'at-rule-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['extend', 'supports', 'keyframes'], + + accept: [ + { + code: 'a { color: pink; }', + description: 'Some random code.', + }, + { + code: '@mixin name ($p) {}', + description: '@rule not from a disallowed list.', + }, + ], + + reject: [ + { + code: 'a { @extend %placeholder; }', + message: messages.rejected('extend'), + line: 1, + column: 5, + description: '@rule from a disallowed list, is a Sass directive.', + }, + { + code: ` + a { + @extend + %placeholder; + } + `, + message: messages.rejected('extend'), + line: 3, + column: 9, + description: '@rule from a disallowed list; newline after its name.', + }, + { + code: ` + @keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('keyframes'), + line: 2, + description: '@rule from a disallowed list; independent rule.', + }, + { + code: ` + @Keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('Keyframes'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; messed case.', + }, + { + code: ` + @-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('-moz-keyframes'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; has vendor prefix.', + }, + { + code: ` + @-WEBKET-KEYFRAMES name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('-WEBKET-KEYFRAMES'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; has vendor prefix.', + }, + ], +}); + +testRule({ + ruleName, + + config: ['keyframes'], + + accept: [ + { + code: 'a { color: pink; }', + description: 'Some random code.', + }, + { + code: '@mixin name ($p) {}', + description: '@rule not from a disallowed list.', + }, + ], + + reject: [ + { + code: ` + @keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('keyframes'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule.', + }, + { + code: ` + @Keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('Keyframes'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; messed case.', + }, + { + code: ` + @-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('-moz-keyframes'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; has vendor prefix.', + }, + { + code: ` + @-WEBKET-KEYFRAMES name { + from { top: 10px; } + to { top: 20px; } + } + `, + message: messages.rejected('-WEBKET-KEYFRAMES'), + line: 2, + column: 7, + description: '@rule from a disallowed list; independent rule; has vendor prefix.', + }, + ], +}); + +testRule({ + ruleName, + syntax: 'less', + config: ['keyframes'], + + accept: [ + { + code: ` + .keyframes() { margin: 0; } + + span { .keyframes(); } + `, + description: 'ignore Less mixin which are treated as at-rule', + }, + ], +}); diff --git a/lib/rules/at-rule-blacklist/index.js b/lib/rules/at-rule-blacklist/index.js new file mode 100644 index 0000000000..3e056130e4 --- /dev/null +++ b/lib/rules/at-rule-blacklist/index.js @@ -0,0 +1,62 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'at-rule-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected at-rule "${name}"`, +}); + +function rule(listInput) { + // To allow for just a string as a parameter (not only arrays of strings) + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'at-rule-disallowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkAtRules((atRule) => { + const name = atRule.name; + + if (!isStandardSyntaxAtRule(atRule)) { + return; + } + + if (!list.includes(postcss.vendor.unprefixed(name).toLowerCase())) { + return; + } + + report({ + message: messages.rejected(name), + node: atRule, + result, + ruleName, + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/at-rule-disallowed-list/README.md b/lib/rules/at-rule-disallowed-list/README.md index 0baefb6134..336dc9d1a5 100644 --- a/lib/rules/at-rule-disallowed-list/README.md +++ b/lib/rules/at-rule-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed at-rules. * At-rules like this */ ``` -This rule was previously called, and is aliased as, `at-rule-blacklist`. - ## Options `array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` diff --git a/lib/rules/at-rule-property-required-list/README.md b/lib/rules/at-rule-property-required-list/README.md index 002bf1b02c..eb4eb944c6 100644 --- a/lib/rules/at-rule-property-required-list/README.md +++ b/lib/rules/at-rule-property-required-list/README.md @@ -9,8 +9,6 @@ Specify a list of required properties for an at-rule. * At-rule and required property names */ ``` -This rule was previously called, and is aliased as, `at-rule-requirelist`. - ## Options `object`: `{ "at-rule-name": ["array", "of", "properties"] }` diff --git a/lib/rules/at-rule-property-requirelist/README.md b/lib/rules/at-rule-property-requirelist/README.md new file mode 100644 index 0000000000..6108023b72 --- /dev/null +++ b/lib/rules/at-rule-property-requirelist/README.md @@ -0,0 +1,55 @@ +# at-rule-property-requirelist + +**_Deprecated: Instead use the [`at-rule-property-required-list`](../at-rule-property-required-list/README.md) rule._** + +Specify a list of required properties for an at-rule. + + +```css + @font-face { font-display: swap; font-family: 'foo'; } +/** ↑ ↑ ↑ + * At-rule and required property names */ +``` + +## Options + +`object`: `{ "at-rule-name": ["array", "of", "properties"] }` + +Given: + +``` +{ + "font-face": ["font-display", "font-family", "font-style"] +} +``` + +The following patterns are considered violations: + + +```css +@font-face { + font-family: 'foo'; + src: url('./fonts/foo.woff2') format('woff2'); +} +``` + + +```css +@font-face { + font-family: 'foo'; + font-style: normal; + src: url('./fonts/foo.woff2') format('woff2'); +} +``` + +The following patterns are _not_ considered violations: + + +```css +@font-face { + font-display: swap; + font-family: 'foo'; + font-style: normal; + src: url('./fonts/foo.woff2') format('woff2'); +} +``` diff --git a/lib/rules/at-rule-property-requirelist/__tests__/index.js b/lib/rules/at-rule-property-requirelist/__tests__/index.js new file mode 100644 index 0000000000..183e7643b4 --- /dev/null +++ b/lib/rules/at-rule-property-requirelist/__tests__/index.js @@ -0,0 +1,84 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: { page: ['margin'] }, + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'at-rule-property-required-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: { + 'font-face': ['font-display', 'font-family'], + page: ['margin'], + }, + + accept: [ + { + code: "@font-face { font-display: auto; font-family: 'Arvo'; }", + description: '@font-face with both required properties', + }, + { + code: "@font-face { font-display: auto; font-family: 'Arvo'; src: url('abc'); /* IE9 */ }", + description: '@font-face with inner comment', + }, + { + code: "@FONT-FACE { FONT-DISPLAY: AUTO; FONT-FAMILY: 'ARVO'; }", + description: '@font-face with both required properties (case-sensitive)', + }, + { + code: '@page { padding: 0.5cm; margin: 1cm; }', + description: '@page with required property', + }, + { + code: '@counter-style counter { system: cyclic; }', + description: 'at-rule not specified in config', + }, + { + code: '@mixin invalid-at-rule { @content; }', + description: '@mixin with invalid at-rule', + }, + ], + + reject: [ + { + code: '@font-face { font-display: auto; }', + description: '@font-face with missing property', + message: messages.expected('font-family', 'font-face'), + }, + { + code: '@FONT-FACE { FONT-DISPLAY: AUTO; }', + description: '@font-face with missing property (case-sensitive)', + message: messages.expected('font-family', 'font-face'), + }, + { + code: "@font-face { font-family: 'Arvo'; font-weight: normal }", + description: '@font-face with missing property', + message: messages.expected('font-display', 'font-face'), + }, + { + code: '@page { padding: 0.5cm }', + description: '@page with missing property', + message: messages.expected('margin', 'page'), + }, + ], +}); diff --git a/lib/rules/at-rule-property-requirelist/index.js b/lib/rules/at-rule-property-requirelist/index.js new file mode 100644 index 0000000000..e979f78b41 --- /dev/null +++ b/lib/rules/at-rule-property-requirelist/index.js @@ -0,0 +1,73 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'at-rule-property-requirelist'; + +const messages = ruleMessages(ruleName, { + expected: (property, atRule) => `Expected property "${property}" for at-rule "${atRule}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'at-rule-property-required-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkAtRules((atRule) => { + if (!isStandardSyntaxAtRule(atRule)) { + return; + } + + const { name, nodes } = atRule; + const atRuleName = name.toLowerCase(); + + if (!list[atRuleName]) { + return; + } + + list[atRuleName].forEach((property) => { + const propertyName = property.toLowerCase(); + + const hasProperty = nodes.find( + ({ type, prop }) => type === 'decl' && prop.toLowerCase() === propertyName, + ); + + if (hasProperty) { + return; + } + + return report({ + message: messages.expected(propertyName, atRuleName), + node: atRule, + result, + ruleName, + }); + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; + +module.exports = rule; diff --git a/lib/rules/at-rule-whitelist/README.md b/lib/rules/at-rule-whitelist/README.md new file mode 100644 index 0000000000..f6e0a006a3 --- /dev/null +++ b/lib/rules/at-rule-whitelist/README.md @@ -0,0 +1,67 @@ +# at-rule-whitelist + +**_Deprecated: Instead use the [`at-rule-allowed-list`](../at-rule-allowed-list/README.md) rule._** + +Specify a list of allowed at-rules. + + +```css + @keyframes name {} +/** ↑ + * At-rules like this */ +``` + +## Options + +`array|string`: `["array", "of", "unprefixed", "at-rules"]|"at-rule"` + +Given: + +``` +["extend", "keyframes"] +``` + +The following patterns are considered violations: + + +```css +@import "path/to/file.css"; +``` + + +```css +@media screen and (max-width: 1024px) { + a { display: none; } +} +``` + +The following patterns are _not_ considered violations: + + +```css +a { @extend placeholder; } +``` + + +```css +@keyframes name { + from { top: 10px; } + to { top: 20px; } +} +``` + + +```css +@KEYFRAMES name { + from { top: 10px; } + to { top: 20px; } +} +``` + + +```css +@-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } +} +``` diff --git a/lib/rules/at-rule-whitelist/__tests__/index.js b/lib/rules/at-rule-whitelist/__tests__/index.js new file mode 100644 index 0000000000..74f79a3e8c --- /dev/null +++ b/lib/rules/at-rule-whitelist/__tests__/index.js @@ -0,0 +1,190 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['extend'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'at-rule-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['extend', 'import', 'keyframes'], + + accept: [ + { + code: 'a { color: pink; }', + description: 'Some random code.', + }, + { + code: 'a { @extend %placeholder; }', + description: '@rule from an allowed list, is a Sass directive.', + }, + { + code: ` + a { + @extend + %placeholder; + } + `, + description: '@rule from an allowed list; newline after its name.', + }, + { + code: ` + @keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule.', + }, + { + code: ` + @Keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; messed case.', + }, + { + code: ` + @-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; has vendor prefix.', + }, + { + code: ` + @-WEBKET-KEYFRAMES name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; has vendor prefix.', + }, + ], + + reject: [ + { + code: ` + @mixin name () {} + `, + line: 2, + columt: 7, + message: messages.rejected('mixin'), + description: '@rule not from an allowed list; independent rule.', + }, + ], +}); + +testRule({ + ruleName, + skipBasicChecks: true, + + config: ['keyframes'], + + accept: [ + { + code: ` + @keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule.', + }, + { + code: ` + @Keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; messed case.', + }, + { + code: ` + @-moz-keyframes name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; has vendor prefix.', + }, + { + code: ` + @-WEBKET-KEYFRAMES name { + from { top: 10px; } + to { top: 20px; } + } + `, + description: '@rule from an allowed list; independent rule; has vendor prefix.', + }, + ], + + reject: [ + { + code: ` + @mixin name ($p) {} + `, + message: messages.rejected('mixin'), + line: 2, + column: 7, + description: '@rule not from an allowed list.', + }, + { + code: "@import 'path/to/file.css';", + message: messages.rejected('import'), + line: 1, + column: 1, + description: '@rule not from an allowed list.', + }, + { + code: '@media screen and (max-witdh: 1000px) {}', + message: messages.rejected('media'), + line: 1, + column: 1, + description: '@rule not from an allowed list.', + }, + ], +}); + +testRule({ + ruleName, + syntax: 'less', + config: ['keyframes'], + skipBasicChecks: true, + + accept: [ + { + code: ` + .mixin() { margin: 0; } + + span { .mixin(); } + `, + description: 'ignore Less mixin which are treated as at-rule', + }, + ], +}); diff --git a/lib/rules/at-rule-whitelist/index.js b/lib/rules/at-rule-whitelist/index.js new file mode 100644 index 0000000000..716ee578b7 --- /dev/null +++ b/lib/rules/at-rule-whitelist/index.js @@ -0,0 +1,62 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxAtRule = require('../../utils/isStandardSyntaxAtRule'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'at-rule-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected at-rule "${name}"`, +}); + +function rule(listInput) { + // To allow for just a string as a parameter (not only arrays of strings) + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'at-rule-allowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkAtRules((atRule) => { + const name = atRule.name; + + if (!isStandardSyntaxAtRule(atRule)) { + return; + } + + if (list.includes(postcss.vendor.unprefixed(name).toLowerCase())) { + return; + } + + report({ + message: messages.rejected(name), + node: atRule, + result, + ruleName, + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/comment-word-blacklist/README.md b/lib/rules/comment-word-blacklist/README.md new file mode 100644 index 0000000000..bcac8e8b90 --- /dev/null +++ b/lib/rules/comment-word-blacklist/README.md @@ -0,0 +1,50 @@ +# comment-word-blacklist + +**_Deprecated: Instead use the [`comment-word-disallowed-list`](../comment-word-disallowed-list/README.md) rule._** + +Specify a list of disallowed words within comments. + + +```css + /* words within comments */ +/** ↑ ↑ ↑ + * These three words */ +``` + +**Caveat:** Comments within _selector and value lists_ are currently ignored. + +## Options + +`array|string|regexp`: `["array", "of", "words", /or/, "/regex/"]|"word"|"/regex/"` + +If a string is surrounded with `"/"` (e.g. `"/^TODO:/"`), it is interpreted as a regular expression. + +Given: + +``` +["/^TODO:/", "badword"] +``` + +The following patterns are considered violations: + + +```css +/* TODO: */ +``` + + +```css +/* TODO: add fallback */ +``` + + +```css +/* some badword */ +``` + +The following patterns are _not_ considered violations: + + +```css +/* comment */ +``` diff --git a/lib/rules/comment-word-blacklist/__tests__/index.js b/lib/rules/comment-word-blacklist/__tests__/index.js new file mode 100644 index 0000000000..70a331716c --- /dev/null +++ b/lib/rules/comment-word-blacklist/__tests__/index.js @@ -0,0 +1,347 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['bad-word'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'comment-word-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['bad-word'], + + accept: [ + { + code: '/* comment */', + }, + { + code: '/*# bad-word */', + }, + ], + + reject: [ + { + code: '/* Comment with bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/* bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/*** bad-word ***/', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/*! bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/** bad-word **/', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + ], +}); + +testRule({ + ruleName, + config: ['/^TODO:/', 'bad-word'], + + accept: [ + { + code: '/* comment */', + }, + { + code: '/* comment comment */', + }, + { + code: '/* comment\ncomment */', + }, + { + code: '/* comment\n\ncomment */', + }, + { + code: '/** comment */', + }, + { + code: '/**** comment ***/', + }, + { + code: '/*\ncomment\n*/', + }, + { + code: '/*\tcomment */', + }, + { + code: '/*! copyright */', + }, + { + code: '/*# sourcemap */', + }, + { + code: '/*# sourcemap bad-word */', + }, + { + code: 'a { color: pink; /* comment */\ntop: 0; }', + }, + { + code: 'a {} /* comment */', + }, + { + code: '/* todo */', + }, + { + code: '/* todo: */', + }, + { + code: '/* todo: comment */', + }, + { + code: '/* tOdO: comment */', + }, + { + code: '/* Todo: comment */', + }, + { + code: '/*! Todo: comment */', + }, + { + code: '/*# Todo: comment */', + }, + { + code: '/** TODO: comment **/', + }, + { + code: '/*** TODO: comment ***/', + }, + ], + + reject: [ + { + code: '/* TODO: */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* TODO: comment */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* TODO: comment\n next line */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* TODO: comment\n next line */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* TODO: comment\r\n next line */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* TODO: comment\n\n next line */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/*\n TODO: comment */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/*\r\n TODO: comment */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/*\n\n TODO: comment */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/*\r\n\r\n TODO: comment */', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '/* bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/* Comment with bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/*! copyright bad-word */', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/** bad-word **/', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + { + code: '/*** bad-word ***/', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + ], +}); + +testRule({ + ruleName, + syntax: 'scss', + config: [['/^TODO:/', 'bad-word']], + + accept: [ + { + code: '// comment', + }, + { + code: '// todo', + }, + { + code: '// todo:', + }, + { + code: '// Todo:', + }, + { + code: '// tOdO:', + }, + ], + + reject: [ + { + code: '// TODO:', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '// TODO: comment', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '// bad-word', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + ], +}); + +testRule({ + ruleName, + syntax: 'less', + config: ['/^TODO:/', 'bad-word'], + + accept: [ + { + code: '// comment', + }, + { + code: '// todo:', + }, + { + code: '// Todo:', + }, + { + code: '// tOdO:', + }, + ], + + reject: [ + { + code: '// TODO:', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '// TODO: comment', + message: messages.rejected('/^TODO:/'), + line: 1, + column: 1, + }, + { + code: '// bad-word', + message: messages.rejected('bad-word'), + line: 1, + column: 1, + }, + ], +}); + +testRule({ + ruleName, + config: [/^TODO:/, 'bad-word'], + + accept: [ + { + code: '/* comment */', + }, + ], + + reject: [ + { + code: '/* TODO: */', + message: messages.rejected(/^TODO:/), + line: 1, + column: 1, + }, + ], +}); diff --git a/lib/rules/comment-word-blacklist/index.js b/lib/rules/comment-word-blacklist/index.js new file mode 100644 index 0000000000..b58df52d93 --- /dev/null +++ b/lib/rules/comment-word-blacklist/index.js @@ -0,0 +1,64 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const containsString = require('../../utils/containsString'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'comment-word-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (pattern) => `Unexpected word matching pattern "${pattern}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'comment-word-disallowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkComments((comment) => { + const text = comment.text; + const rawComment = comment.toString(); + const firstFourChars = rawComment.substr(0, 4); + + // Return early if sourcemap + if (firstFourChars === '/*# ') { + return; + } + + const matchesWord = matchesStringOrRegExp(text, list) || containsString(text, list); + + if (!matchesWord) { + return; + } + + report({ + message: messages.rejected(matchesWord.pattern), + node: comment, + result, + ruleName, + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/comment-word-disallowed-list/README.md b/lib/rules/comment-word-disallowed-list/README.md index 5578dc894a..814667b43c 100644 --- a/lib/rules/comment-word-disallowed-list/README.md +++ b/lib/rules/comment-word-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed words within comments. * These three words */ ``` -This rule was previously called, and is aliased as, `comment-word-blacklist`. - **Caveat:** Comments within _selector and value lists_ are currently ignored. ## Options diff --git a/lib/rules/declaration-property-unit-allowed-list/README.md b/lib/rules/declaration-property-unit-allowed-list/README.md index 8ff7d6d235..48a95c973d 100644 --- a/lib/rules/declaration-property-unit-allowed-list/README.md +++ b/lib/rules/declaration-property-unit-allowed-list/README.md @@ -9,8 +9,6 @@ a { width: 100px; } * These properties and these units */ ``` -This rule was previously called, and is aliased as, `declaration-property-unit-whitelist`. - ## Options `object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` diff --git a/lib/rules/declaration-property-unit-blacklist/README.md b/lib/rules/declaration-property-unit-blacklist/README.md new file mode 100644 index 0000000000..7537255e43 --- /dev/null +++ b/lib/rules/declaration-property-unit-blacklist/README.md @@ -0,0 +1,76 @@ +# declaration-property-unit-blacklist + +**_Deprecated: Instead use the [`declaration-property-unit-disallowed-list`](../declaration-property-unit-disallowed-list/README.md) rule._** + +Specify a list of disallowed property and unit pairs within declarations. + + +```css +a { width: 100px; } +/** ↑ ↑ + * These properties and these units */ +``` + +## Options + +`object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` + +If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. + +Given: + +``` +{ + "font-size": ["em", "px"], + "/^animation/": ["s"] +} +``` + +The following patterns are considered violations: + + +```css +a { font-size: 1em; } +``` + + +```css +a { animation: animation-name 5s ease; } +``` + + +```css +a { -webkit-animation: animation-name 5s ease; } +``` + + +```css +a { animation-duration: 5s; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { font-size: 1.2rem; } +``` + + +```css +a { height: 100px; } +``` + + +```css +a { animation: animation-name 500ms ease; } +``` + + +```css +a { -webkit-animation: animation-name 500ms ease; } +``` + + +```css +a { animation-duration: 500ms; } +``` diff --git a/lib/rules/declaration-property-unit-blacklist/__tests__/index.js b/lib/rules/declaration-property-unit-blacklist/__tests__/index.js new file mode 100644 index 0000000000..bf4f9a2fff --- /dev/null +++ b/lib/rules/declaration-property-unit-blacklist/__tests__/index.js @@ -0,0 +1,195 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [{ margin: ['em'] }], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [ + { + 'font-size': ['px', 'em'], + margin: ['em'], + 'background-position': ['%'], + animation: ['s'], + }, + ], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { top: 0; }', + }, + { + code: 'a { color: #000; }', + }, + { + code: 'a { margin: 0 0 0 0 }', + }, + { + code: 'a { margin: 0 10px 5rem 2in; }', + }, + { + code: 'a { margin: 0 10pX 5rem 2in; }', + }, + { + code: 'a { margin: 0 10PX 5rem 2in; }', + }, + { + code: 'a { background-position: top right, 1em 5vh; }', + }, + { + code: 'a { margin: calc(30vh - 10vh); }', + }, + { + code: 'a { animation: animation-name 300ms ease; }', + }, + { + code: 'a { -webkit-animation: animation-name 300ms ease; }', + }, + { + code: 'a { animation-duration: 3s; }', + }, + { + code: 'a { -webkit-animation-duration: 3s; }', + }, + { + code: 'a { font-size: /* 100px */ 1.2rem; }', + description: 'ignore unit within comments', + }, + { + code: 'a::before { font-size: "10px"}', + description: 'ignore unit within quotes', + }, + { + code: 'a { font-size: $fs10px; }', + description: 'ignore preprocessor variable includes unit', + }, + { + code: 'a { font-size: --some-fs-10px; }', + description: 'ignore css variable includes unit', + }, + ], + + reject: [ + { + code: 'a { font-size: 12px; }', + message: messages.rejected('font-size', 'px'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 12pX; }', + message: messages.rejected('font-size', 'pX'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 12PX; }', + message: messages.rejected('font-size', 'PX'), + line: 1, + column: 16, + }, + { + code: 'a { margin: 10px 0 5em; }', + message: messages.rejected('margin', 'em'), + line: 1, + column: 20, + }, + { + code: 'a { background-position: 0 10%; }', + message: messages.rejected('background-position', '%'), + line: 1, + column: 28, + }, + { + code: 'a { background-position: top right, 0 10%; }', + message: messages.rejected('background-position', '%'), + line: 1, + column: 39, + }, + { + code: 'a { margin: calc(10vh - 10em); }', + message: messages.rejected('margin', 'em'), + column: 25, + }, + { + code: 'a { animation: foo 3s; }', + message: messages.rejected('animation', 's'), + }, + { + code: 'a { -webkit-animation: foo 3s; }', + message: messages.rejected('-webkit-animation', 's'), + }, + ], +}); + +testRule({ + ruleName, + + config: [ + { + '/^animation/': ['s'], + }, + ], + + skipBasicChecks: true, + + accept: [ + { + code: 'a { animation: animation-name 300ms ease; }', + }, + { + code: 'a { -webkit-animation: animation-name 300ms ease; }', + }, + { + code: 'a { animation-duration: 300ms; }', + }, + { + code: 'a { -webkit-animation-duration: 300ms; }', + }, + ], + + reject: [ + { + code: 'a { animation: animation-name 3s ease; }', + message: messages.rejected('animation', 's'), + }, + { + code: 'a { -webkit-animation: animation-name 3s ease; }', + message: messages.rejected('-webkit-animation', 's'), + }, + { + code: 'a { animation-duration: 3s; }', + message: messages.rejected('animation-duration', 's'), + }, + { + code: 'a { -webkit-animation-duration: 3s; }', + message: messages.rejected('-webkit-animation-duration', 's'), + }, + ], +}); diff --git a/lib/rules/declaration-property-unit-blacklist/index.js b/lib/rules/declaration-property-unit-blacklist/index.js new file mode 100644 index 0000000000..db1d840dd2 --- /dev/null +++ b/lib/rules/declaration-property-unit-blacklist/index.js @@ -0,0 +1,84 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'declaration-property-unit-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (property, unit) => `Unexpected unit "${unit}" for property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + const prop = decl.prop; + const value = decl.value; + + const unprefixedProp = postcss.vendor.unprefixed(prop); + + const propList = _.find(list, (units, propIdentifier) => + matchesStringOrRegExp(unprefixedProp, propIdentifier), + ); + + if (!propList) { + return; + } + + valueParser(value).walk((node) => { + // Ignore wrong units within `url` function + if (node.type === 'function' && node.value.toLowerCase() === 'url') { + return false; + } + + if (node.type === 'string') { + return; + } + + const unit = getUnitFromValueNode(node); + + if (!unit || (unit && !propList.includes(unit.toLowerCase()))) { + return; + } + + report({ + message: messages.rejected(prop, unit), + node: decl, + index: declarationValueIndex(decl) + node.sourceIndex, + result, + ruleName, + }); + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/declaration-property-unit-disallowed-list/README.md b/lib/rules/declaration-property-unit-disallowed-list/README.md index 50d0cc81f0..088d42a3af 100644 --- a/lib/rules/declaration-property-unit-disallowed-list/README.md +++ b/lib/rules/declaration-property-unit-disallowed-list/README.md @@ -9,8 +9,6 @@ a { width: 100px; } * These properties and these units */ ``` -This rule was previously called, and is aliased as, `declaration-property-unit-blacklist`. - ## Options `object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` diff --git a/lib/rules/declaration-property-unit-whitelist/README.md b/lib/rules/declaration-property-unit-whitelist/README.md new file mode 100644 index 0000000000..da73901d63 --- /dev/null +++ b/lib/rules/declaration-property-unit-whitelist/README.md @@ -0,0 +1,87 @@ +# declaration-property-unit-whitelist + +**_Deprecated: Instead use the [`declaration-property-unit-allowed-list`](../declaration-property-unit-allowed-list/README.md) rule._** + +Specify a list of allowed property and unit pairs within declarations. + + +```css +a { width: 100px; } +/** ↑ ↑ + * These properties and these units */ +``` + +## Options + +`object`: `{ "unprefixed-property-name": ["array", "of", "units"] }` + +If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. + +Given: + +``` +{ + "font-size": ["em", "px"], + "/^animation/": ["s"], + "line-height": [] +} +``` + +The following patterns are considered violations: + + +```css +a { font-size: 1.2rem; } +``` + + +```css +a { animation: animation-name 500ms ease; } +``` + + +```css +a { -webkit-animation: animation-name 500ms ease; } +``` + + +```css +a { animation-duration: 500ms; } +``` + + +```css +a { line-height: 13px; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { font-size: 1em; } +``` + + +```css +a { height: 100px; } +``` + + +```css +a { animation: animation-name 5s ease; } +``` + + +```css +a { -webkit-animation: animation-name 5s ease; } +``` + + +```css +a { animation-duration: 5s; } +``` + + +```css +a { line-height: 1; } +``` diff --git a/lib/rules/declaration-property-unit-whitelist/__tests__/index.js b/lib/rules/declaration-property-unit-whitelist/__tests__/index.js new file mode 100644 index 0000000000..9850fb4cfc --- /dev/null +++ b/lib/rules/declaration-property-unit-whitelist/__tests__/index.js @@ -0,0 +1,200 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [{ margin: ['em'] }], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [ + { + 'font-size': ['px', 'em'], + margin: ['em'], + 'background-position': ['%'], + animation: ['s'], + 'line-height': [], + }, + ], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { top: 0; }', + }, + { + code: 'a { color: #000; }', + }, + { + code: 'a { margin: 0 0 0 0; }', + }, + { + code: 'a { margin: 0 10em; }', + }, + { + code: 'a { margin: 0 10eM; }', + }, + { + code: 'a { margin: 0 10EM; }', + }, + { + code: 'a { background-position: top right, 0 50%; }', + }, + { + code: 'a { margin: calc(30em - 10em); }', + }, + { + code: 'a { animation: animation-name 1s ease; }', + }, + { + code: 'a { -webkit-animation: animation-name 1s ease; }', + }, + { + code: 'a { line-height: 1; }', + }, + { + code: 'a { font-size: /* 1.2rem */ 12px; }', + description: 'ignore unit within comments', + }, + { + code: 'a::before { font-size: "1.2rem"}', + description: 'ignore unit within quotes', + }, + { + code: 'a { font-size: $fs1rem; }', + description: 'ignore preprocessor variable includes unit', + }, + { + code: 'a { font-size: --some-fs-1rem; }', + description: 'ignore css variable includes unit', + }, + ], + + reject: [ + { + code: 'a { font-size: 1.2rem; }', + message: messages.rejected('font-size', 'rem'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 1.2rEm; }', + message: messages.rejected('font-size', 'rEm'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 1.2REM; }', + message: messages.rejected('font-size', 'REM'), + line: 1, + column: 16, + }, + { + code: 'a { margin: 10em 0 1rem; }', + message: messages.rejected('margin', 'rem'), + line: 1, + column: 20, + }, + { + code: 'a { background-position: 0 10px; }', + message: messages.rejected('background-position', 'px'), + line: 1, + column: 28, + }, + { + code: 'a { background-position: top right, 0 10px; }', + message: messages.rejected('background-position', 'px'), + line: 1, + column: 39, + }, + { + code: 'a { margin: calc(10em - 10px); }', + message: messages.rejected('margin', 'px'), + column: 25, + }, + { + code: 'a { animation: animation-name 300ms ease; }', + message: messages.rejected('animation', 'ms'), + column: 31, + }, + { + code: 'a { -webkit-animation: animation-name 300ms ease; }', + message: messages.rejected('-webkit-animation', 'ms'), + column: 39, + }, + { + code: 'a { line-height: 1.2em; }', + message: messages.rejected('line-height', 'em'), + column: 18, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + { + '/^animation/': ['ms'], + }, + ], + + skipBasicChecks: true, + + accept: [ + { + code: 'a { animation: animation-name 300ms ease; }', + }, + { + code: 'a { -webkit-animation: animation-name 300ms ease; }', + }, + { + code: 'a { animation-duration: 300ms; }', + }, + { + code: 'a { -webkit-animation-duration: 300ms; }', + }, + ], + + reject: [ + { + code: 'a { animation: animation-name 3s ease; }', + message: messages.rejected('animation', 's'), + }, + { + code: 'a { -webkit-animation: animation-name 3s ease; }', + message: messages.rejected('-webkit-animation', 's'), + }, + { + code: 'a { animation-duration: 3s; }', + message: messages.rejected('animation-duration', 's'), + }, + { + code: 'a { -webkit-animation-duration: 3s; }', + message: messages.rejected('-webkit-animation-duration', 's'), + }, + ], +}); diff --git a/lib/rules/declaration-property-unit-whitelist/index.js b/lib/rules/declaration-property-unit-whitelist/index.js new file mode 100644 index 0000000000..cd2dc9eef0 --- /dev/null +++ b/lib/rules/declaration-property-unit-whitelist/index.js @@ -0,0 +1,84 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'declaration-property-unit-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (property, unit) => `Unexpected unit "${unit}" for property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-unit-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + const prop = decl.prop; + const value = decl.value; + + const unprefixedProp = postcss.vendor.unprefixed(prop); + + const propList = _.find(list, (units, propIdentifier) => + matchesStringOrRegExp(unprefixedProp, propIdentifier), + ); + + if (!propList) { + return; + } + + valueParser(value).walk((node) => { + // Ignore wrong units within `url` function + if (node.type === 'function' && node.value.toLowerCase() === 'url') { + return false; + } + + if (node.type === 'string') { + return; + } + + const unit = getUnitFromValueNode(node); + + if (!unit || (unit && propList.indexOf(unit.toLowerCase())) !== -1) { + return; + } + + report({ + message: messages.rejected(prop, unit), + node: decl, + index: declarationValueIndex(decl) + node.sourceIndex, + result, + ruleName, + }); + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/declaration-property-value-allowed-list/README.md b/lib/rules/declaration-property-value-allowed-list/README.md index 32ff898097..41371ddd09 100644 --- a/lib/rules/declaration-property-value-allowed-list/README.md +++ b/lib/rules/declaration-property-value-allowed-list/README.md @@ -9,8 +9,6 @@ a { text-transform: uppercase; } * These properties and these values */ ``` -This rule was previously called, and is aliased as, `declaration-property-value-whitelist`. - ## Options `object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex"] }` diff --git a/lib/rules/declaration-property-value-blacklist/README.md b/lib/rules/declaration-property-value-blacklist/README.md new file mode 100644 index 0000000000..9edd6c9b1d --- /dev/null +++ b/lib/rules/declaration-property-value-blacklist/README.md @@ -0,0 +1,107 @@ +# declaration-property-value-blacklist + +**_Deprecated: Instead use the [`declaration-property-value-disallowed-list`](../declaration-property-value-disallowed-list/README.md) rule._** + +Specify a list of disallowed property and value pairs within declarations. + + +```css +a { text-transform: uppercase; } +/** ↑ ↑ + * These properties and these values */ +``` + +## Options + +`object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex", /regex/] }` + +If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. + +The same goes for values. Keep in mind that a regular expression value is matched against the entire value of the declaration, not specific parts of it. For example, a value like `"10px solid rgba( 255 , 0 , 0 , 0.5 )"` will _not_ match `"/^solid/"` (notice beginning of the line boundary) but _will_ match `"/\\s+solid\\s+/"` or `"/\\bsolid\\b/"`. + +Be careful with regex matching not to accidentally consider quoted string values and `url()` arguments. For example, `"/red/"` will match value such as `"1px dotted red"` as well as `"\"foo\""` and `"white url(/mysite.com/red.png)"`. + +Given: + +``` +{ + "transform": ["/scale3d/", "/rotate3d/", "/translate3d/"], + "position": ["fixed"], + "color": ["/^green/"], + "/^animation/": ["/ease/"] +} +``` + +The following patterns are considered violations: + + +```css +a { position: fixed; } +``` + + +```css +a { transform: scale3d(1, 2, 3); } +``` + + +```css +a { -webkit-transform: scale3d(1, 2, 3); } +``` + + +```css +a { color: green; } +``` + + +```css +a { animation: foo 2s ease-in-out; } +``` + + +```css +a { animation-timing-function: ease-in-out; } +``` + + +```css +a { -webkit-animation-timing-function: ease-in-out; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { position: relative; } +``` + + +```css +a { transform: scale(2); } +``` + + +```css +a { -webkit-transform: scale(2); } +``` + + +```css +a { color: lightgreen; } +``` + + +```css +a { animation: foo 2s linear; } +``` + + +```css +a { animation-timing-function: linear; } +``` + + +```css +a { -webkit-animation-timing-function: linear; } +``` diff --git a/lib/rules/declaration-property-value-blacklist/__tests__/index.js b/lib/rules/declaration-property-value-blacklist/__tests__/index.js new file mode 100644 index 0000000000..a1d3005a29 --- /dev/null +++ b/lib/rules/declaration-property-value-blacklist/__tests__/index.js @@ -0,0 +1,210 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [{ color: ['red'] }], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [ + { + // regular string + 'text-transform': ['uppercase'], + // regexes + transform: ['/scale3d/', '/rotate3d/', '/translate3d/'], + // mixed string and regex + color: ['red', 'green', 'blue', '/^sea/'], + }, + ], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { color: lightgreen; }', + }, + { + code: 'a { text-transform: lowercase; }', + }, + { + code: 'a { transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(12px, 50%); }', + }, + { + code: 'a { -webkit-transform: matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(12px, 50%); }', + }, + { + code: 'a { color: /* red */ pink; }', + description: 'ignore value within comments', + }, + { + code: 'a::before { color: "red"}', + description: 'ignore value within quotes', + }, + { + code: 'a { color: $red; }', + description: 'ignore preprocessor variable includes value', + }, + { + code: 'a { color: --some-red; }', + description: 'ignore css variable includes value', + }, + { + code: 'a { color: darkseagreen }', + }, + ], + + reject: [ + { + code: 'a { color: red; }', + message: messages.rejected('color', 'red'), + line: 1, + column: 5, + }, + { + code: 'a { color: green }', + message: messages.rejected('color', 'green'), + line: 1, + column: 5, + }, + { + code: 'a { text-transform: uppercase; }', + message: messages.rejected('text-transform', 'uppercase'), + line: 1, + column: 5, + }, + { + code: 'a { transform: scale3d(1, 2, 3) }', + message: messages.rejected('transform', 'scale3d(1, 2, 3)'), + line: 1, + column: 5, + }, + { + code: 'a { -webkit-transform: scale3d(1, 2, 3) }', + message: messages.rejected('-webkit-transform', 'scale3d(1, 2, 3)'), + column: 5, + }, + { + code: 'a { color: seagreen }', + message: messages.rejected('color', 'seagreen'), + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + { + '/^animation/': ['/ease/'], + }, + ], + + skipBasicChecks: true, + + accept: [ + { + code: 'a { animation: foo 1s linear; }', + }, + { + code: 'a { -webkit-animation: foo 1s linear; }', + }, + { + code: 'a { animation-timing-function: linear; }', + }, + { + code: 'a { -webkit-animation-timing-function: linear; }', + }, + ], + + reject: [ + { + code: 'a { animation: foo 1s ease-in-out; }', + message: messages.rejected('animation', 'foo 1s ease-in-out'), + }, + { + code: 'a { -webkit-animation: foo 1s ease-in-out; }', + message: messages.rejected('-webkit-animation', 'foo 1s ease-in-out'), + }, + { + code: 'a { animation-timing-function: ease-in-out; }', + message: messages.rejected('animation-timing-function', 'ease-in-out'), + }, + { + code: 'a { -webkit-animation-timing-function: ease-in-out; }', + message: messages.rejected('-webkit-animation-timing-function', 'ease-in-out'), + }, + ], +}); + +testRule({ + ruleName, + + config: [ + { + '/^animation/': [/ease/], + }, + ], + + skipBasicChecks: true, + + accept: [ + { + code: 'a { animation: foo 1s linear; }', + }, + ], + + reject: [ + { + code: 'a { animation: foo 1s ease-in-out; }', + message: messages.rejected('animation', 'foo 1s ease-in-out'), + }, + { + code: 'a { -webkit-animation: foo 1s ease-in-out; }', + message: messages.rejected('-webkit-animation', 'foo 1s ease-in-out'), + }, + { + code: 'a { animation-timing-function: ease-in-out; }', + message: messages.rejected('animation-timing-function', 'ease-in-out'), + }, + { + code: 'a { -webkit-animation-timing-function: ease-in-out; }', + message: messages.rejected('-webkit-animation-timing-function', 'ease-in-out'), + }, + ], +}); + +testRule({ + ruleName, + config: { position: ['fixed'] }, + skipBasicChecks: true, + accept: [ + { + code: 'a { font-size: 1em; }', + description: 'irrelevant CSS', + }, + ], +}); diff --git a/lib/rules/declaration-property-value-blacklist/index.js b/lib/rules/declaration-property-value-blacklist/index.js new file mode 100644 index 0000000000..3550bf70e4 --- /dev/null +++ b/lib/rules/declaration-property-value-blacklist/index.js @@ -0,0 +1,66 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'declaration-property-value-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (property, value) => `Unexpected value "${value}" for property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + const prop = decl.prop; + const value = decl.value; + + const unprefixedProp = postcss.vendor.unprefixed(prop); + const propList = _.find(list, (values, propIdentifier) => + matchesStringOrRegExp(unprefixedProp, propIdentifier), + ); + + if (_.isEmpty(propList)) { + return; + } + + if (!matchesStringOrRegExp(value, propList)) { + return; + } + + report({ + message: messages.rejected(prop, value), + node: decl, + result, + ruleName, + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/declaration-property-value-disallowed-list/README.md b/lib/rules/declaration-property-value-disallowed-list/README.md index ea583a2f9f..982799a29d 100644 --- a/lib/rules/declaration-property-value-disallowed-list/README.md +++ b/lib/rules/declaration-property-value-disallowed-list/README.md @@ -9,8 +9,6 @@ a { text-transform: uppercase; } * These properties and these values */ ``` -This rule was previously called, and is aliased as, `declaration-property-value-blacklist`. - ## Options `object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex", /regex/] }` diff --git a/lib/rules/declaration-property-value-whitelist/README.md b/lib/rules/declaration-property-value-whitelist/README.md new file mode 100644 index 0000000000..2e7f2b9848 --- /dev/null +++ b/lib/rules/declaration-property-value-whitelist/README.md @@ -0,0 +1,98 @@ +# declaration-property-value-whitelist + +**_Deprecated: Instead use the [`declaration-property-value-allowed-list`](../declaration-property-value-allowed-list/README.md) rule._** + +Specify a list of allowed property and value pairs within declarations. + + +```css +a { text-transform: uppercase; } +/** ↑ ↑ + * These properties and these values */ +``` + +## Options + +`object`: `{ "unprefixed-property-name": ["array", "of", "values"], "unprefixed-property-name": ["/regex/", "non-regex"] }` + +If a property name is found in the object, only the listed property values are allowed. This rule complains about all non-matching values. (If the property name is not included in the object, anything goes.) + +If a property name is surrounded with `"/"` (e.g. `"/^animation/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^animation/` will match `animation`, `animation-duration`, `animation-timing-function`, etc. + +The same goes for values. Keep in mind that a regular expression value is matched against the entire value of the declaration, not specific parts of it. For example, a value like `"10px solid rgba( 255 , 0 , 0 , 0.5 )"` will _not_ match `"/^solid/"` (notice beginning of the line boundary) but _will_ match `"/\\s+solid\\s+/"` or `"/\\bsolid\\b/"`. + +Be careful with regex matching not to accidentally consider quoted string values and `url()` arguments. For example, `"/red/"` will match value such as `"1px dotted red"` as well as `"\"red\""` and `"white url(/mysite.com/red.png)"`. + +Given: + +``` +{ + "transform": ["/scale/"], + "whitespace": ["nowrap"], + "/color/": ["/^green/"] +} +``` + +The following patterns are considered violations: + + +```css +a { whitespace: pre; } +``` + + +```css +a { transform: translate(1, 1); } +``` + + +```css +a { -webkit-transform: translate(1, 1); } +``` + + +```css +a { color: pink; } +``` + + +```css +a { background-color: pink; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { color: pink; } +``` + + +```css +a { whitespace: nowrap; } +``` + + +```css +a { transform: scale(1, 1); } +``` + + +```css +a { -webkit-transform: scale(1, 1); } +``` + + +```css +a { color: green; } +``` + + +```css +a { background-color: green; } +``` + + +```css +a { background: pink; } +``` diff --git a/lib/rules/declaration-property-value-whitelist/__tests__/index.js b/lib/rules/declaration-property-value-whitelist/__tests__/index.js new file mode 100644 index 0000000000..7f674ab4b7 --- /dev/null +++ b/lib/rules/declaration-property-value-whitelist/__tests__/index.js @@ -0,0 +1,101 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [{ transform: ['/scale/'] }], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [ + { + transform: ['/scale/'], + whitespace: ['nowrap'], + '/color/': ['/^green/'], + }, + ], + + accept: [ + { + code: 'div { whitespace: nowrap; }', + }, + { + code: 'a { transform: scale(1, 1); }', + }, + { + code: 'a { -webkit-transform: scale(1, 1); }', + }, + { + code: 'a { color: green; }', + }, + { + code: 'a { background-color: green; }', + }, + ], + + reject: [ + { + code: 'div { whitespace: pre; }', + message: messages.rejected('whitespace', 'pre'), + line: 1, + column: 7, + }, + { + code: 'a { transform: translate(1, 1); }', + message: messages.rejected('transform', 'translate(1, 1)'), + line: 1, + column: 5, + }, + { + code: 'a { -webkit-transform: translate(1, 1); }', + message: messages.rejected('-webkit-transform', 'translate(1, 1)'), + line: 1, + column: 5, + }, + { + code: 'a { color: pink; }', + message: messages.rejected('color', 'pink'), + line: 1, + column: 5, + }, + { + code: 'a { background-color: pink; }', + message: messages.rejected('background-color', 'pink'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + config: { position: ['static'] }, + skipBasicChecks: true, + accept: [ + { + code: 'a { font-size: 1em; }', + description: 'irrelevant CSS', + }, + ], +}); diff --git a/lib/rules/declaration-property-value-whitelist/index.js b/lib/rules/declaration-property-value-whitelist/index.js new file mode 100644 index 0000000000..3a20e2b340 --- /dev/null +++ b/lib/rules/declaration-property-value-whitelist/index.js @@ -0,0 +1,66 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'declaration-property-value-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (property, value) => `Unexpected value "${value}" for property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'declaration-property-value-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + const prop = decl.prop; + const value = decl.value; + + const unprefixedProp = postcss.vendor.unprefixed(prop); + const propList = _.find(list, (values, propIdentifier) => + matchesStringOrRegExp(unprefixedProp, propIdentifier), + ); + + if (_.isEmpty(propList)) { + return; + } + + if (matchesStringOrRegExp(value, propList)) { + return; + } + + report({ + message: messages.rejected(prop, value), + node: decl, + result, + ruleName, + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/function-allowed-list/README.md b/lib/rules/function-allowed-list/README.md index e8229a835a..92b304d491 100644 --- a/lib/rules/function-allowed-list/README.md +++ b/lib/rules/function-allowed-list/README.md @@ -9,8 +9,6 @@ a { transform: scale(1); } * This function */ ``` -This rule was previously called, and is aliased as, `function-whitelist`. - ## Options `array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` diff --git a/lib/rules/function-blacklist/README.md b/lib/rules/function-blacklist/README.md new file mode 100644 index 0000000000..9cb80e361c --- /dev/null +++ b/lib/rules/function-blacklist/README.md @@ -0,0 +1,54 @@ +# function-blacklist + +**_Deprecated: Instead use the [`function-disallowed-list`](../function-disallowed-list/README.md) rule._** + +Specify a list of disallowed functions. + + +```css +a { transform: scale(1); } +/** ↑ + * This function */ +``` + +## Options + +`array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` + +If a string is surrounded with `"/"` (e.g. `"/^rgb/"`), it is interpreted as a regular expression. + +Given: + +``` +["scale", "rgba", "linear-gradient"] +``` + +The following patterns are considered violations: + + +```css +a { transform: scale(1); } +``` + + +```css +a { + color: rgba(0, 0, 0, 0.5); +} +``` + + +```css +a { + background: + red, + -moz-linear-gradient(45deg, blue, red); +} +``` + +The following patterns are _not_ considered violations: + + +```css +a { background: red; } +``` diff --git a/lib/rules/function-blacklist/__tests__/index.js b/lib/rules/function-blacklist/__tests__/index.js new file mode 100644 index 0000000000..7d7db8d4ff --- /dev/null +++ b/lib/rules/function-blacklist/__tests__/index.js @@ -0,0 +1,243 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['rgba'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'function-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['rgba', 'scale', 'linear-gradient'], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { transform: SCALE(1); }', + }, + { + code: 'a { transform: sCaLe(1); }', + }, + { + code: 'a { transform: rotate(7deg) }', + }, + { + code: 'a { transform: rOtAtE(7deg) }', + }, + { + code: 'a { transform: ROTATE(7deg) }', + }, + { + code: 'a { background: -webkit-radial-gradient(red, green, blue); }', + }, + { + code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', + }, + { + code: '@media (max-width: 10px) { a { color: color(rgb(0, 0, 0) lightness(50%)); } }', + }, + { + code: '$scale: (value, value2)', + description: 'Sass list ignored', + }, + ], + + reject: [ + { + code: 'a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 16, + }, + { + code: 'a { transform : scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 17, + }, + { + code: 'a\n{ transform: scale(1); }', + message: messages.rejected('scale'), + line: 2, + column: 14, + }, + { + code: 'a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 19, + }, + { + code: ' a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 18, + }, + { + code: 'a { color: rgba(0, 0, 0, 0) }', + message: messages.rejected('rgba'), + line: 1, + column: 12, + }, + { + code: 'a { color: color(rgba(0, 0, 0, 0) lightness(50%)); }', + message: messages.rejected('rgba'), + line: 1, + column: 18, + }, + { + code: 'a { background: red, -moz-linear-gradient(45deg, blue, red); }', + message: messages.rejected('-moz-linear-gradient'), + line: 1, + column: 22, + }, + { + code: '@media (max-width: 10px) { a { color: color(rgba(0, 0, 0) lightness(50%)); } }', + message: messages.rejected('rgba'), + line: 1, + column: 45, + }, + ], +}); + +testRule({ + ruleName, + + config: ['/rgb/'], + + accept: [ + { + code: 'a { color: hsl(208, 100%, 97%); }', + }, + ], + + reject: [ + { + code: 'a { color: rgb(0, 0, 0); }', + message: messages.rejected('rgb'), + line: 1, + column: 12, + }, + { + code: 'a { color: rgba(0, 0, 0); }', + message: messages.rejected('rgba'), + line: 1, + column: 12, + }, + ], +}); + +testRule({ + ruleName, + + config: [/rgb/], + + accept: [ + { + code: 'a { color: hsl(208, 100%, 97%); }', + }, + ], + + reject: [ + { + code: 'a { color: rgb(0, 0, 0); }', + message: messages.rejected('rgb'), + line: 1, + column: 12, + }, + { + code: 'a { color: rgba(0, 0, 0); }', + message: messages.rejected('rgba'), + line: 1, + column: 12, + }, + ], +}); + +testRule({ + ruleName, + + config: ['skewx', 'translateX', 'SCALEX', '/rotate/i', '/MATRIX/'], + + accept: [ + { + code: 'a { transform: stewX(10deg); }', + }, + { + code: 'a { transform: translateY(5px); }', + }, + { + code: 'a { transform: scaleX(1); }', + }, + { + code: 'a { transform: matrix3d(a1); }', + }, + ], + + reject: [ + { + code: 'a { transform: skewx(10deg); }', + message: messages.rejected('skewx'), + line: 1, + column: 16, + }, + { + code: 'a { transform: translateX(5px); }', + message: messages.rejected('translateX'), + line: 1, + column: 16, + }, + { + code: 'a { transform: SCALEX(1); }', + message: messages.rejected('SCALEX'), + line: 1, + column: 16, + }, + { + code: 'a { transform: rotatex(60deg); }', + message: messages.rejected('rotatex'), + line: 1, + column: 16, + }, + { + code: 'a { transform: rotateX(60deg); }', + message: messages.rejected('rotateX'), + line: 1, + column: 16, + }, + { + code: 'a { transform: ROTATEX(60deg); }', + message: messages.rejected('ROTATEX'), + line: 1, + column: 16, + }, + { + code: 'a { transform: MATRIX3d(a1); }', + message: messages.rejected('MATRIX3d'), + line: 1, + column: 16, + }, + ], +}); diff --git a/lib/rules/function-blacklist/index.js b/lib/rules/function-blacklist/index.js new file mode 100644 index 0000000000..e26654a22d --- /dev/null +++ b/lib/rules/function-blacklist/index.js @@ -0,0 +1,69 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'function-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected function "${name}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'function-disallowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkDecls((decl) => { + const value = decl.value; + + valueParser(value).walk((node) => { + if (node.type !== 'function') { + return; + } + + if (!isStandardSyntaxFunction(node)) { + return; + } + + if (!matchesStringOrRegExp(postcss.vendor.unprefixed(node.value), list)) { + return; + } + + report({ + message: messages.rejected(node.value), + node: decl, + index: declarationValueIndex(decl) + node.sourceIndex, + result, + ruleName, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/function-disallowed-list/README.md b/lib/rules/function-disallowed-list/README.md index 8f622db3ae..e6dad004a2 100644 --- a/lib/rules/function-disallowed-list/README.md +++ b/lib/rules/function-disallowed-list/README.md @@ -9,8 +9,6 @@ a { transform: scale(1); } * This function */ ``` -This rule was previously called, and is aliased as, `function-blacklist`. - ## Options `array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` diff --git a/lib/rules/function-url-scheme-allowed-list/README.md b/lib/rules/function-url-scheme-allowed-list/README.md index 8a2d49154c..64cbbdcfd6 100644 --- a/lib/rules/function-url-scheme-allowed-list/README.md +++ b/lib/rules/function-url-scheme-allowed-list/README.md @@ -9,8 +9,6 @@ a { background-image: url('http://www.example.com/file.jpg'); } * This URL scheme */ ``` -This rule was previously called, and is aliased as, `function-url-scheme-whitelist`. - A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. This rule ignores: diff --git a/lib/rules/function-url-scheme-blacklist/README.md b/lib/rules/function-url-scheme-blacklist/README.md new file mode 100644 index 0000000000..14fb678310 --- /dev/null +++ b/lib/rules/function-url-scheme-blacklist/README.md @@ -0,0 +1,73 @@ +# function-url-scheme-blacklist + +**_Deprecated: Instead use the [`function-url-scheme-disallowed-list`](../function-url-scheme-disallowed-list/README.md) rule._** + +Specify a list of disallowed URL schemes. + + +```css +a { background-image: url('http://www.example.com/file.jpg'); } +/** ↑ + * This URL scheme */ +``` + +A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. + +This rule ignores: + +- URL arguments without an existing URL scheme +- URL arguments with variables or variable interpolation (`$sass`, `@less`, `--custom-property`, `#{$var}`, `@{var}`, `$(var)`) + +## Options + +`array|string|regex`: `["array", "of", /schemes/ or "/regex/"]|"scheme"|/regex/` + +Given: + +``` +["ftp", "/^http/"] +``` + +The following patterns are considered violations: + + +```css +a { background-image: url('ftp://www.example.com/file.jpg'); } +``` + + +```css +a { background-image: url('http://www.example.com/file.jpg'); } +``` + + +```css +a { background-image: url('https://www.example.com/file.jpg'); } +``` + +The following patterns are _not_ considered violations: + + +```css +a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); } +``` + + +```css +a { background-image: url('example.com/file.jpg'); } +``` + + +```css +a { background-image: url('/example.com/file.jpg'); } +``` + + +```css +a { background-image: url('//example.com/file.jpg'); } +``` + + +```css +a { background-image: url('./path/to/file.jpg'); } +``` diff --git a/lib/rules/function-url-scheme-blacklist/__tests__/index.js b/lib/rules/function-url-scheme-blacklist/__tests__/index.js new file mode 100644 index 0000000000..d4ec6f2dbc --- /dev/null +++ b/lib/rules/function-url-scheme-blacklist/__tests__/index.js @@ -0,0 +1,280 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['https'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: [[]], + + accept: [ + { + code: "a { background: url('http://www.example.com/file.jpg'); }", + }, + ], +}); + +testRule({ + ruleName, + config: [''], + + accept: [ + { + code: "a { background: url('http://www.example.com/file.jpg'); }", + }, + ], +}); + +testRule({ + ruleName, + config: ['https', 'data'], + + accept: [ + { + code: 'a { background: url(); }', + }, + { + code: "a { background: url(''); }", + }, + { + code: 'a { background: url(""); }', + }, + { + code: 'a { background: url(:); }', + }, + { + code: 'a { background: url(://); }', + }, + { + code: 'a { background: url(//); }', + }, + { + code: 'a { background: url(/); }', + }, + { + code: 'a { background: url(./); }', + }, + { + code: 'a { background: url(./file.jpg); }', + }, + { + code: 'a { background: url(../file.jpg); }', + }, + { + code: 'a { background: URL(../file.jpg); }', + }, + { + code: "a { background: url('../file.jpg'); }", + }, + { + code: 'a { background: url("../file.jpg"); }', + }, + { + code: "a { background: url('/path/to/file.jpg'); }", + }, + { + code: 'a { background: url(//www.example.com/file.jpg); }', + }, + { + code: 'a { background: url("//www.example.com/file.jpg"); }', + }, + { + code: "a { background: url('http://www.example.com/file.jpg'); }", + }, + { + code: "a { background-image: url('http://example.com:3000'); }", + }, + { + code: "a { background-image: url('//example.com:3000'); }", + }, + { + code: "@font-face { font-family: 'foo'; src: url('/path/to/foo.ttf'); }", + }, + { + code: 'a { background: url(HTTP://example.com/file.jpg); }', + description: 'ignore case', + }, + { + code: 'a { background: some-url(); }', + description: 'ignore contain url function', + }, + { + code: 'a { background: url($image); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(@image); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(http://#{$host}/path); }', + description: 'ignore interpolation', + }, + { + code: "a { background: url('http://@{host}/path'); }", + description: 'ignore interpolation', + }, + { + code: 'a { background: url(http://$(host)/path); }', + description: 'ignore interpolation', + }, + { + code: 'a { background: url(var(--image)); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(example.com); }', + description: 'schemeless url', + }, + { + code: 'a { background: url(example.com:3000); }', + description: 'schemeless url and port', + }, + { + code: 'a { background: url(http://example.com:3000); }', + description: 'url with scheme and port', + }, + ], + + reject: [ + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + message: messages.rejected('data'), + line: 1, + column: 27, + }, + { + code: 'a { background: url(HTTPS://www.example.com/file.jpg); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: "a { background: url('https://www.example.com/file.jpg'); }", + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: 'a { background: url("https://www.example.com/file.jpg"); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: "a { background: url('https://example.com:3000'); }", + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: "@font-face { font-family: 'foo'; src: url('https://www.example.com/file.jpg'); }", + message: messages.rejected('https'), + line: 1, + column: 43, + }, + { + code: "a { background: no-repeat center/80% url('https://www.example.com/file.jpg'); }", + message: messages.rejected('https'), + line: 1, + column: 42, + }, + ], +}); + +testRule({ + ruleName, + + config: [['/^http/']], + + accept: [ + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + }, + { + code: 'a { background: url(./file.jpg); }', + }, + ], + + reject: [ + { + code: 'a { background: url(https://example.com/file.jpg); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: 'a { background: url(HTTPS://example.com/file.jpg); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: 'a { background: url(http://example.com/file.jpg); }', + message: messages.rejected('http'), + line: 1, + column: 21, + }, + ], +}); + +testRule({ + ruleName, + + config: [[/^http/]], + + accept: [ + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + }, + { + code: 'a { background: url(./file.jpg); }', + }, + ], + + reject: [ + { + code: 'a { background: url(https://example.com/file.jpg); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: 'a { background: url(HTTPS://example.com/file.jpg); }', + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: 'a { background: url(http://example.com/file.jpg); }', + message: messages.rejected('http'), + line: 1, + column: 21, + }, + ], +}); diff --git a/lib/rules/function-url-scheme-blacklist/index.js b/lib/rules/function-url-scheme-blacklist/index.js new file mode 100644 index 0000000000..c85bb0f68a --- /dev/null +++ b/lib/rules/function-url-scheme-blacklist/index.js @@ -0,0 +1,74 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const functionArgumentsSearch = require('../../utils/functionArgumentsSearch'); +const getSchemeFromUrl = require('../../utils/getSchemeFromUrl'); +const isStandardSyntaxUrl = require('../../utils/isStandardSyntaxUrl'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'function-url-scheme-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (scheme) => `Unexpected URL scheme "${scheme}:"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => { + const unspacedUrlString = _.trim(args, ' '); + + if (!isStandardSyntaxUrl(unspacedUrlString)) { + return; + } + + const urlString = _.trim(unspacedUrlString, '\'"'); + const scheme = getSchemeFromUrl(urlString); + + if (scheme === null) { + return; + } + + if (!matchesStringOrRegExp(scheme, list)) { + return; + } + + report({ + message: messages.rejected(scheme), + node: decl, + index, + result, + ruleName, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/function-url-scheme-disallowed-list/README.md b/lib/rules/function-url-scheme-disallowed-list/README.md index a6dadce430..11e4d73d7e 100644 --- a/lib/rules/function-url-scheme-disallowed-list/README.md +++ b/lib/rules/function-url-scheme-disallowed-list/README.md @@ -9,8 +9,6 @@ a { background-image: url('http://www.example.com/file.jpg'); } * This URL scheme */ ``` -This rule was previously called, and is aliased as, `function-url-scheme-blacklist`. - A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. This rule ignores: diff --git a/lib/rules/function-url-scheme-whitelist/README.md b/lib/rules/function-url-scheme-whitelist/README.md new file mode 100644 index 0000000000..ece68797d7 --- /dev/null +++ b/lib/rules/function-url-scheme-whitelist/README.md @@ -0,0 +1,78 @@ +# function-url-scheme-whitelist + +**_Deprecated: Instead use the [`function-url-scheme-allowed-list`](../function-url-scheme-allowed-list/README.md) rule._** + +Specify a list of allowed URL schemes. + + +```css +a { background-image: url('http://www.example.com/file.jpg'); } +/** ↑ + * This URL scheme */ +``` + +A [URL scheme](https://url.spec.whatwg.org/#syntax-url-scheme) consists of alphanumeric, `+`, `-`, and `.` characters. It can appear at the start of a URL and is followed by `:`. + +This rule ignores: + +- URL arguments without an existing URL scheme +- URL arguments with variables or variable interpolation (`$sass`, `@less`, `--custom-property`, `#{$var}`, `@{var}`, `$(var)`) + +## Options + +`array|string|regex`: `["array", "of", /schemes/ or "/regex/"]|"scheme"|/regex/` + +Given: + +``` +["data", "/^http/"] +``` + +The following patterns are considered violations: + + +```css +a { background-image: url('file://file.jpg'); } +``` + +The following patterns are _not_ considered violations: + + +```css +a { background-image: url('example.com/file.jpg'); } +``` + + +```css +a { background-image: url('/example.com/file.jpg'); } +``` + + +```css +a { background-image: url('//example.com/file.jpg'); } +``` + + +```css +a { background-image: url('./path/to/file.jpg'); } +``` + + +```css +a { background-image: url('http://www.example.com/file.jpg'); } +``` + + +```css +a { background-image: url('https://www.example.com/file.jpg'); } +``` + + +```css +a { background-image: url('HTTPS://www.example.com/file.jpg'); } +``` + + +```css +a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); } +``` diff --git a/lib/rules/function-url-scheme-whitelist/__tests__/index.js b/lib/rules/function-url-scheme-whitelist/__tests__/index.js new file mode 100644 index 0000000000..f6e3823f86 --- /dev/null +++ b/lib/rules/function-url-scheme-whitelist/__tests__/index.js @@ -0,0 +1,342 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['https'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['https', 'data'], + + accept: [ + { + code: 'a { background: url(); }', + }, + { + code: "a { background: url(''); }", + }, + { + code: 'a { background: url(""); }', + }, + { + code: 'a { background: url(:); }', + }, + { + code: 'a { background: url(://); }', + }, + { + code: 'a { background: url(//); }', + }, + { + code: 'a { background: url(/); }', + }, + { + code: 'a { background: url(./); }', + }, + { + code: 'a { background: url(./file.jpg); }', + }, + { + code: 'a { background: url(../file.jpg); }', + }, + { + code: 'a { background: URL(../file.jpg); }', + }, + { + code: "a { background: url('../file.jpg'); }", + }, + { + code: 'a { background: url("../file.jpg"); }', + }, + { + code: "a { background: url('/path/to/file.jpg'); }", + }, + { + code: 'a { background: url(//www.example.com/file.jpg); }', + }, + { + code: 'a { background: url("//www.example.com/file.jpg"); }', + }, + { + code: "a { background: url('https://www.example.com/file.jpg'); }", + }, + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + }, + { + code: "a { background-image: url('https://example.com:3000'); }", + }, + { + code: "a { background-image: url('//example.com:3000'); }", + }, + { + code: "@font-face { font-family: 'foo'; src: url('/path/to/foo.ttf'); }", + }, + { + code: 'a { background: url(HTTPS://example.com/file.jpg); }', + description: 'ignore case', + }, + { + code: 'a { background: some-url(); }', + description: 'ignore contain url function', + }, + { + code: 'a { background: url($image); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(@image); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(http://#{$host}/path); }', + description: 'ignore interpolation', + }, + { + code: "a { background: url('http://@{host}/path'); }", + description: 'ignore interpolation', + }, + { + code: 'a { background: url(http://$(host)/path); }', + description: 'ignore interpolation', + }, + { + code: 'a { background: url(var(--image)); }', + description: 'ignore variable', + }, + { + code: 'a { background: url(example.com); }', + description: 'schemeless url', + }, + { + code: 'a { background: url(example.com:3000); }', + description: 'schemeless url and port', + }, + { + code: 'a { background: url(https://example.com:3000); }', + description: 'url with scheme and port', + }, + ], + + reject: [ + { + code: 'a { background: url(http://www.example.com/file.jpg); }', + message: messages.rejected('http'), + line: 1, + column: 21, + }, + { + code: "a { background: url('http://www.example.com/file.jpg'); }", + message: messages.rejected('http'), + line: 1, + column: 21, + }, + { + code: 'a { background: url("http://www.example.com/file.jpg"); }', + message: messages.rejected('http'), + line: 1, + column: 21, + }, + { + code: "a { background: url('http://example.com:3000'); }", + message: messages.rejected('http'), + line: 1, + column: 21, + }, + { + code: "@font-face { font-family: 'foo'; src: url('http://www.example.com/file.jpg'); }", + message: messages.rejected('http'), + line: 1, + column: 43, + }, + { + code: "a { background: no-repeat center/80% url('http://www.example.com/file.jpg'); }", + message: messages.rejected('http'), + line: 1, + column: 42, + }, + ], +}); + +testRule({ + ruleName, + config: [[]], + + accept: [ + { + code: "a { background: url('/path/to/file.jpg'); }", + }, + { + code: 'a { background: url(//www.example.com/file.jpg); }', + }, + { + code: 'a { background: url("//www.example.com/file.jpg"); }', + }, + { + code: 'a { background: url(example.com:3000); }', + }, + ], + + reject: [ + { + code: "a { background: url('https://www.example.com/file.jpg'); }", + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + message: messages.rejected('data'), + line: 1, + column: 27, + }, + ], +}); + +testRule({ + ruleName, + config: [''], + + accept: [ + { + code: "a { background: url('/path/to/file.jpg'); }", + }, + { + code: 'a { background: url(//www.example.com/file.jpg); }', + }, + { + code: 'a { background: url("//www.example.com/file.jpg"); }', + }, + { + code: 'a { background: url(example.com:3000); }', + }, + ], + + reject: [ + { + code: "a { background: url('https://www.example.com/file.jpg'); }", + message: messages.rejected('https'), + line: 1, + column: 21, + }, + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + message: messages.rejected('data'), + line: 1, + column: 27, + }, + ], +}); + +testRule({ + ruleName, + // primaryOptionArray + config: ['uri', 'file', 'https'], + + accept: [ + { + code: 'a { background: url(https://example.com/file.jpg); }', + }, + ], + + reject: [ + { + code: 'a { background: url(http://example.com/file.jpg); }', + message: messages.rejected('http'), + line: 1, + column: 21, + }, + ], +}); + +testRule({ + ruleName, + + config: [['/^http/']], + + accept: [ + { + code: 'a { background: url(http://example.com/file.jpg); }', + }, + { + code: 'a { background: url(HTTP://example.com/file.jpg); }', + }, + { + code: 'a { background: url(https://example.com/file.jpg); }', + }, + ], + + reject: [ + { + code: 'a { background: url(ftp://example.com/file.jpg); }', + message: messages.rejected('ftp'), + line: 1, + column: 21, + }, + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + message: messages.rejected('data'), + line: 1, + column: 27, + }, + ], +}); + +testRule({ + ruleName, + + config: [[/^http/]], + + accept: [ + { + code: 'a { background: url(http://example.com/file.jpg); }', + }, + { + code: 'a { background: url(HTTP://example.com/file.jpg); }', + }, + { + code: 'a { background: url(https://example.com/file.jpg); }', + }, + ], + + reject: [ + { + code: 'a { background: url(ftp://example.com/file.jpg); }', + message: messages.rejected('ftp'), + line: 1, + column: 21, + }, + { + code: + "a { background-image: url('data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs='); }", + message: messages.rejected('data'), + line: 1, + column: 27, + }, + ], +}); diff --git a/lib/rules/function-url-scheme-whitelist/index.js b/lib/rules/function-url-scheme-whitelist/index.js new file mode 100644 index 0000000000..320453c993 --- /dev/null +++ b/lib/rules/function-url-scheme-whitelist/index.js @@ -0,0 +1,74 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const functionArgumentsSearch = require('../../utils/functionArgumentsSearch'); +const getSchemeFromUrl = require('../../utils/getSchemeFromUrl'); +const isStandardSyntaxUrl = require('../../utils/isStandardSyntaxUrl'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'function-url-scheme-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (scheme) => `Unexpected URL scheme "${scheme}:"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'function-url-scheme-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkDecls((decl) => { + functionArgumentsSearch(decl.toString().toLowerCase(), 'url', (args, index) => { + const unspacedUrlString = _.trim(args, ' '); + + if (!isStandardSyntaxUrl(unspacedUrlString)) { + return; + } + + const urlString = _.trim(unspacedUrlString, '\'"'); + const scheme = getSchemeFromUrl(urlString); + + if (scheme === null) { + return; + } + + if (matchesStringOrRegExp(scheme, list)) { + return; + } + + report({ + message: messages.rejected(scheme), + node: decl, + index, + result, + ruleName, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/function-whitelist/README.md b/lib/rules/function-whitelist/README.md new file mode 100644 index 0000000000..f3620b3b4b --- /dev/null +++ b/lib/rules/function-whitelist/README.md @@ -0,0 +1,75 @@ +# function-whitelist + +**_Deprecated: Instead use the [`function-allowed-list`](../function-allowed-list/README.md) rule._** + +Specify a list of allowed functions. + + +```css +a { transform: scale(1); } +/** ↑ + * This function */ +``` + +## Options + +`array|string`: `["array", "of", "unprefixed", /functions/ or "regex"]|"function"|"/regex/"` + +If a string is surrounded with `"/"` (e.g. `"/^rgb/"`), it is interpreted as a regular expression. + +Given: + +``` +["scale", "rgba", "linear-gradient"] +``` + +The following patterns are considered violations: + + +```css +a { transform: rotate(1); } +``` + + +```css +a { + color: hsla(170, 50%, 45%, 1) +} +``` + + +```css +a { + background: + red, + -webkit-radial-gradient(red, green, blue); +} +``` + +The following patterns are _not_ considered violations: + + +```css +a { background: red; } +``` + + +```css +a { transform: scale(1); } +``` + + +```css +a { + color: rgba(0, 0, 0, 0.5); +} +``` + + +```css +a { + background: + red, + -moz-linear-gradient(45deg, blue, red); +} +``` diff --git a/lib/rules/function-whitelist/__tests__/index.js b/lib/rules/function-whitelist/__tests__/index.js new file mode 100644 index 0000000000..e2843265d8 --- /dev/null +++ b/lib/rules/function-whitelist/__tests__/index.js @@ -0,0 +1,204 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['rgba'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'function-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['rotate', 'rgb', 'radial-gradient', 'lightness', 'color'], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { transform: rotate(7deg) }', + }, + { + code: 'a { background: -webkit-radial-gradient(red, green, blue); }', + }, + { + code: 'a { color: color(rgb(0, 0, 0) lightness(50%)); }', + }, + { + code: '@media (max-width: 10px) { a { color: color(rgb(0, 0, 0) lightness(50%)); } }', + }, + { + code: '$list: (value, value2)', + description: 'Sass list ignored', + }, + ], + + reject: [ + { + code: 'a { transform: rOtAtE(7deg) }', + message: messages.rejected('rOtAtE'), + line: 1, + column: 16, + }, + { + code: 'a { transform: ROTATE(7deg) }', + message: messages.rejected('ROTATE'), + line: 1, + column: 16, + }, + { + code: 'a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 16, + }, + { + code: 'a { transform: sCaLe(1); }', + message: messages.rejected('sCaLe'), + line: 1, + column: 16, + }, + { + code: 'a { transform: SCALE(1); }', + message: messages.rejected('SCALE'), + line: 1, + column: 16, + }, + { + code: 'a { transform : scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 17, + }, + { + code: 'a\n{ transform: scale(1); }', + message: messages.rejected('scale'), + line: 2, + column: 14, + }, + { + code: 'a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 19, + }, + { + code: ' a { transform: scale(1); }', + message: messages.rejected('scale'), + line: 1, + column: 18, + }, + { + code: 'a { color: rgba(0, 0, 0, 0) }', + message: messages.rejected('rgba'), + line: 1, + column: 12, + }, + { + code: 'a { color: color(rgba(0, 0, 0, 0) lightness(50%)); }', + message: messages.rejected('rgba'), + line: 1, + column: 18, + }, + { + code: 'a { background: red, -moz-linear-gradient(45deg, blue, red); }', + message: messages.rejected('-moz-linear-gradient'), + line: 1, + column: 22, + }, + { + code: '@media (max-width: 10px) { a { color: color(rgba(0, 0, 0) lightness(50%)); } }', + message: messages.rejected('rgba'), + line: 1, + column: 45, + }, + ], +}); + +testRule({ + ruleName, + config: ['translate'], + skipBasicChecks: true, + + accept: [ + { + code: 'a { transform: translate(1px); }', + }, + ], + + reject: [ + { + code: 'a { transform: scale(4); }', + message: messages.rejected('scale'), + line: 1, + column: 16, + }, + ], +}); + +testRule({ + ruleName, + + config: ['/rgb/'], + + accept: [ + { + code: 'a { color: rgb(0, 0, 0); }', + }, + { + code: 'a { color: rgba(0, 0, 0, 0); }', + }, + ], + + reject: [ + { + code: 'a { color: hsl(208, 100%, 97%); }', + message: messages.rejected('hsl'), + line: 1, + column: 12, + }, + ], +}); + +testRule({ + ruleName, + + config: [/rgb/], + + accept: [ + { + code: 'a { color: rgb(0, 0, 0); }', + }, + { + code: 'a { color: rgba(0, 0, 0, 0); }', + }, + ], + + reject: [ + { + code: 'a { color: hsl(208, 100%, 97%); }', + message: messages.rejected('hsl'), + line: 1, + column: 12, + }, + ], +}); diff --git a/lib/rules/function-whitelist/index.js b/lib/rules/function-whitelist/index.js new file mode 100644 index 0000000000..95627bb108 --- /dev/null +++ b/lib/rules/function-whitelist/index.js @@ -0,0 +1,71 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const isStandardSyntaxFunction = require('../../utils/isStandardSyntaxFunction'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'function-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected function "${name}"`, +}); + +function rule(listInput) { + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'function-allowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkDecls((decl) => { + const value = decl.value; + + valueParser(value).walk((node) => { + if (node.type !== 'function') { + return; + } + + if (!isStandardSyntaxFunction(node)) { + return; + } + + if (matchesStringOrRegExp(postcss.vendor.unprefixed(node.value), list)) { + return; + } + + report({ + message: messages.rejected(node.value), + node: decl, + index: declarationValueIndex(decl) + node.sourceIndex, + result, + ruleName, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/index.js b/lib/rules/index.js index 390bb34432..a2ee0d5260 100644 --- a/lib/rules/index.js +++ b/lib/rules/index.js @@ -10,8 +10,7 @@ const importLazy = require('import-lazy'); const rules = { 'alpha-value-notation': importLazy(() => require('./alpha-value-notation'))(), 'at-rule-allowed-list': importLazy(() => require('./at-rule-allowed-list'))(), - // Renamed to at-rule-disallowed-list - 'at-rule-blacklist': importLazy(() => require('./at-rule-disallowed-list'))(), + 'at-rule-blacklist': importLazy(() => require('./at-rule-blacklist'))(), 'at-rule-disallowed-list': importLazy(() => require('./at-rule-disallowed-list'))(), 'at-rule-empty-line-before': importLazy(() => require('./at-rule-empty-line-before'))(), 'at-rule-name-case': importLazy(() => require('./at-rule-name-case'))(), @@ -21,13 +20,11 @@ const rules = { 'at-rule-no-unknown': importLazy(() => require('./at-rule-no-unknown'))(), 'at-rule-no-vendor-prefix': importLazy(() => require('./at-rule-no-vendor-prefix'))(), 'at-rule-property-required-list': importLazy(() => require('./at-rule-property-required-list'))(), - // Renamed to at-rule-required-list - 'at-rule-property-requirelist': importLazy(() => require('./at-rule-property-required-list'))(), + 'at-rule-property-requirelist': importLazy(() => require('./at-rule-property-requirelist'))(), 'at-rule-semicolon-newline-after': importLazy(() => require('./at-rule-semicolon-newline-after'), )(), - // Renamed to at-rule-allowed-list - 'at-rule-whitelist': importLazy(() => require('./at-rule-allowed-list'))(), + 'at-rule-whitelist': importLazy(() => require('./at-rule-whitelist'))(), 'block-closing-brace-empty-line-before': importLazy(() => require('./block-closing-brace-empty-line-before'), )(), @@ -65,8 +62,7 @@ const rules = { 'comment-empty-line-before': importLazy(() => require('./comment-empty-line-before'))(), 'comment-no-empty': importLazy(() => require('./comment-no-empty'))(), 'comment-whitespace-inside': importLazy(() => require('./comment-whitespace-inside'))(), - // Renamed to comment-word-disallowed-list - 'comment-word-blacklist': importLazy(() => require('./comment-word-disallowed-list'))(), + 'comment-word-blacklist': importLazy(() => require('./comment-word-blacklist'))(), 'comment-word-disallowed-list': importLazy(() => require('./comment-word-disallowed-list'))(), 'custom-media-pattern': importLazy(() => require('./custom-media-pattern'))(), 'custom-property-empty-line-before': importLazy(() => @@ -112,30 +108,26 @@ const rules = { 'declaration-property-unit-allowed-list': importLazy(() => require('./declaration-property-unit-allowed-list'), )(), - // Renamed to declaration-property-unit-disallowed-list 'declaration-property-unit-blacklist': importLazy(() => - require('./declaration-property-unit-disallowed-list'), + require('./declaration-property-unit-blacklist'), )(), 'declaration-property-unit-disallowed-list': importLazy(() => require('./declaration-property-unit-disallowed-list'), )(), - // Renamed to declaration-property-unit-allowed-list 'declaration-property-unit-whitelist': importLazy(() => - require('./declaration-property-unit-allowed-list'), + require('./declaration-property-unit-whitelist'), )(), 'declaration-property-value-allowed-list': importLazy(() => require('./declaration-property-value-allowed-list'), )(), - // Renamed to declaration-property-value-disallowed-list 'declaration-property-value-blacklist': importLazy(() => - require('./declaration-property-value-disallowed-list'), + require('./declaration-property-value-blacklist'), )(), 'declaration-property-value-disallowed-list': importLazy(() => require('./declaration-property-value-disallowed-list'), )(), - // Renamed to declaration-property-value-allowed-list 'declaration-property-value-whitelist': importLazy(() => - require('./declaration-property-value-allowed-list'), + require('./declaration-property-value-whitelist'), )(), 'font-family-no-missing-generic-family-keyword': importLazy(() => require('./font-family-no-missing-generic-family-keyword'), @@ -144,8 +136,7 @@ const rules = { 'font-family-no-duplicate-names': importLazy(() => require('./font-family-no-duplicate-names'))(), 'font-weight-notation': importLazy(() => require('./font-weight-notation'))(), 'function-allowed-list': importLazy(() => require('./function-allowed-list'))(), - // Renamed to function-disallowed-list - 'function-blacklist': importLazy(() => require('./function-disallowed-list'))(), + 'function-blacklist': importLazy(() => require('./function-blacklist'))(), 'function-calc-no-invalid': importLazy(() => require('./function-calc-no-invalid'))(), 'function-calc-no-unspaced-operator': importLazy(() => require('./function-calc-no-unspaced-operator'), @@ -173,20 +164,13 @@ const rules = { 'function-url-scheme-allowed-list': importLazy(() => require('./function-url-scheme-allowed-list'), )(), - // Renamed to function-url-scheme-disallowed-list - 'function-url-scheme-blacklist': importLazy(() => - require('./function-url-scheme-disallowed-list'), - )(), + 'function-url-scheme-blacklist': importLazy(() => require('./function-url-scheme-blacklist'))(), 'function-url-scheme-disallowed-list': importLazy(() => require('./function-url-scheme-disallowed-list'), )(), - // Renamed to function-url-scheme-allowed-list - 'function-url-scheme-whitelist': importLazy(() => - require('./function-url-scheme-allowed-list'), - )(), + 'function-url-scheme-whitelist': importLazy(() => require('./function-url-scheme-whitelist'))(), 'function-whitespace-after': importLazy(() => require('./function-whitespace-after'))(), - // Renamed to function-allowed-list - 'function-whitelist': importLazy(() => require('./function-allowed-list'))(), + 'function-whitelist': importLazy(() => require('./function-whitelist'))(), 'hue-degree-notation': importLazy(() => require('./hue-degree-notation'))(), 'keyframe-declaration-no-important': importLazy(() => require('./keyframe-declaration-no-important'), @@ -206,10 +190,7 @@ const rules = { 'media-feature-name-allowed-list': importLazy(() => require('./media-feature-name-allowed-list'), )(), - // Renamed to media-feature-name-disallowed-list - 'media-feature-name-blacklist': importLazy(() => - require('./media-feature-name-disallowed-list'), - )(), + 'media-feature-name-blacklist': importLazy(() => require('./media-feature-name-blacklist'))(), 'media-feature-name-case': importLazy(() => require('./media-feature-name-case'))(), 'media-feature-name-disallowed-list': importLazy(() => require('./media-feature-name-disallowed-list'), @@ -222,10 +203,9 @@ const rules = { require('./media-feature-name-value-allowed-list'), )(), 'media-feature-name-value-whitelist': importLazy(() => - require('./media-feature-name-value-allowed-list'), + require('./media-feature-name-value-whitelist'), )(), - // Renamed to media-feature-name-allowed-list - 'media-feature-name-whitelist': importLazy(() => require('./media-feature-name-allowed-list'))(), + 'media-feature-name-whitelist': importLazy(() => require('./media-feature-name-whitelist'))(), 'media-feature-parentheses-space-inside': importLazy(() => require('./media-feature-parentheses-space-inside'), )(), @@ -265,14 +245,12 @@ const rules = { 'number-max-precision': importLazy(() => require('./number-max-precision'))(), 'number-no-trailing-zeros': importLazy(() => require('./number-no-trailing-zeros'))(), 'property-allowed-list': importLazy(() => require('./property-allowed-list'))(), - // Renamed to property-disallowed-list - 'property-blacklist': importLazy(() => require('./property-disallowed-list'))(), + 'property-blacklist': importLazy(() => require('./property-blacklist'))(), 'property-case': importLazy(() => require('./property-case'))(), 'property-disallowed-list': importLazy(() => require('./property-disallowed-list'))(), 'property-no-unknown': importLazy(() => require('./property-no-unknown'))(), 'property-no-vendor-prefix': importLazy(() => require('./property-no-vendor-prefix'))(), - // Renamed to property-allowed-list - 'property-whitelist': importLazy(() => require('./property-allowed-list'))(), + 'property-whitelist': importLazy(() => require('./property-whitelist'))(), 'rule-empty-line-before': importLazy(() => require('./rule-empty-line-before'))(), 'selector-attribute-brackets-space-inside': importLazy(() => require('./selector-attribute-brackets-space-inside'), @@ -280,9 +258,8 @@ const rules = { 'selector-attribute-operator-allowed-list': importLazy(() => require('./selector-attribute-operator-allowed-list'), )(), - // Renamed to selector-attribute-operator-disallowed-list 'selector-attribute-operator-blacklist': importLazy(() => - require('./selector-attribute-operator-disallowed-list'), + require('./selector-attribute-operator-blacklist'), )(), 'selector-attribute-operator-disallowed-list': importLazy(() => require('./selector-attribute-operator-disallowed-list'), @@ -293,19 +270,15 @@ const rules = { 'selector-attribute-operator-space-before': importLazy(() => require('./selector-attribute-operator-space-before'), )(), - // Renamed to selector-attribute-operator-allowed-list 'selector-attribute-operator-whitelist': importLazy(() => - require('./selector-attribute-operator-allowed-list'), + require('./selector-attribute-operator-whitelist'), )(), 'selector-attribute-quotes': importLazy(() => require('./selector-attribute-quotes'))(), 'selector-class-pattern': importLazy(() => require('./selector-class-pattern'))(), 'selector-combinator-allowed-list': importLazy(() => require('./selector-combinator-allowed-list'), )(), - // Renamed to selector-combinator-disallowed-list - 'selector-combinator-blacklist': importLazy(() => - require('./selector-combinator-disallowed-list'), - )(), + 'selector-combinator-blacklist': importLazy(() => require('./selector-combinator-blacklist'))(), 'selector-combinator-disallowed-list': importLazy(() => require('./selector-combinator-disallowed-list'), )(), @@ -315,10 +288,7 @@ const rules = { 'selector-combinator-space-before': importLazy(() => require('./selector-combinator-space-before'), )(), - // Renamed to selector-combinator-allowed-list - 'selector-combinator-whitelist': importLazy(() => - require('./selector-combinator-allowed-list'), - )(), + 'selector-combinator-whitelist': importLazy(() => require('./selector-combinator-whitelist'))(), 'selector-descendant-combinator-no-non-space': importLazy(() => require('./selector-descendant-combinator-no-non-space'), )(), @@ -353,9 +323,8 @@ const rules = { 'selector-pseudo-class-allowed-list': importLazy(() => require('./selector-pseudo-class-allowed-list'), )(), - // Renamed to selector-pseudo-class-disallowed-list 'selector-pseudo-class-blacklist': importLazy(() => - require('./selector-pseudo-class-disallowed-list'), + require('./selector-pseudo-class-blacklist'), )(), 'selector-pseudo-class-case': importLazy(() => require('./selector-pseudo-class-case'))(), 'selector-pseudo-class-disallowed-list': importLazy(() => @@ -367,16 +336,14 @@ const rules = { 'selector-pseudo-class-parentheses-space-inside': importLazy(() => require('./selector-pseudo-class-parentheses-space-inside'), )(), - // Renamed to selector-pseudo-class-allowed-list 'selector-pseudo-class-whitelist': importLazy(() => - require('./selector-pseudo-class-allowed-list'), + require('./selector-pseudo-class-whitelist'), )(), 'selector-pseudo-element-allowed-list': importLazy(() => require('./selector-pseudo-element-allowed-list'), )(), - // Renamed to selector-pseudo-element-disallowed-list 'selector-pseudo-element-blacklist': importLazy(() => - require('./selector-pseudo-element-disallowed-list'), + require('./selector-pseudo-element-blacklist'), )(), 'selector-pseudo-element-case': importLazy(() => require('./selector-pseudo-element-case'))(), 'selector-pseudo-element-colon-notation': importLazy(() => @@ -388,9 +355,8 @@ const rules = { 'selector-pseudo-element-no-unknown': importLazy(() => require('./selector-pseudo-element-no-unknown'), )(), - // Renamed to selector-pseudo-element-allowed-list 'selector-pseudo-element-whitelist': importLazy(() => - require('./selector-pseudo-element-allowed-list'), + require('./selector-pseudo-element-whitelist'), )(), 'selector-type-case': importLazy(() => require('./selector-type-case'))(), 'selector-type-no-unknown': importLazy(() => require('./selector-type-no-unknown'))(), @@ -402,13 +368,11 @@ const rules = { 'time-min-milliseconds': importLazy(() => require('./time-min-milliseconds'))(), 'unicode-bom': importLazy(() => require('./unicode-bom'))(), 'unit-allowed-list': importLazy(() => require('./unit-allowed-list'))(), - // Renamed to unit-disallowed-list - 'unit-blacklist': importLazy(() => require('./unit-disallowed-list'))(), + 'unit-blacklist': importLazy(() => require('./unit-blacklist'))(), 'unit-case': importLazy(() => require('./unit-case'))(), 'unit-disallowed-list': importLazy(() => require('./unit-disallowed-list'))(), 'unit-no-unknown': importLazy(() => require('./unit-no-unknown'))(), - // Renamed to unit-allowed-list - 'unit-whitelist': importLazy(() => require('./unit-allowed-list'))(), + 'unit-whitelist': importLazy(() => require('./unit-whitelist'))(), 'value-keyword-case': importLazy(() => require('./value-keyword-case'))(), 'value-list-comma-newline-after': importLazy(() => require('./value-list-comma-newline-after'))(), 'value-list-comma-newline-before': importLazy(() => diff --git a/lib/rules/media-feature-name-allowed-list/README.md b/lib/rules/media-feature-name-allowed-list/README.md index 4c5c28abcf..255b865f1f 100644 --- a/lib/rules/media-feature-name-allowed-list/README.md +++ b/lib/rules/media-feature-name-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed media feature names. * This media feature name */ ``` -This rule was previously called, and is aliased as, `media-feature-name-whitelist`. - ## Options `array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` diff --git a/lib/rules/media-feature-name-blacklist/README.md b/lib/rules/media-feature-name-blacklist/README.md new file mode 100644 index 0000000000..e89f5753cf --- /dev/null +++ b/lib/rules/media-feature-name-blacklist/README.md @@ -0,0 +1,66 @@ +# media-feature-name-blacklist + +**_Deprecated: Instead use the [`media-feature-name-disallowed-list`](../media-feature-name-disallowed-list/README.md) rule._** + +Specify a list of disallowed media feature names. + + +```css +@media (min-width: 700px) {} +/** ↑ + * This media feature name */ +``` + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` + +Given: + +``` +["max-width", "/^my-/"] +``` + +The following patterns are considered violations: + + +```css +@media (max-width: 50em) {} +``` + + +```css +@media (my-width: 50em) {} +``` + + +```css +@media (max-width < 50em) {} +``` + + +```css +@media (10em < my-height < 50em) {} +``` + +The following patterns are _not_ considered violations: + + +```css +@media (min-width: 50em) {} +``` + + +```css +@media print and (min-resolution: 300dpi) {} +``` + + +```css +@media (min-width >= 50em) {} +``` + + +```css +@media (10em < width < 50em) {} +``` diff --git a/lib/rules/media-feature-name-blacklist/__tests__/index.js b/lib/rules/media-feature-name-blacklist/__tests__/index.js new file mode 100644 index 0000000000..bd28913d70 --- /dev/null +++ b/lib/rules/media-feature-name-blacklist/__tests__/index.js @@ -0,0 +1,228 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['max-width'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['max-width', '--wide-viewport', 'width', '/^my-/', 'color'], + + accept: [ + { + code: '@media (min-width: 50em) { }', + }, + { + code: '@media (MaX-wIdTh: 50em) { }', + }, + { + code: '@media (MiN-wIdTh: 50em) { }', + }, + { + code: '@media (height <= 50em) { }', + }, + { + code: '@media (400px < height < 1000px) { }', + }, + { + code: '@media (--wide-viewport) { }', + description: 'ignore custom media query', + }, + { + code: '@media (/* max-width: 50em */ min-width: 50em) { }', + description: 'ignore comments', + }, + { + code: '@media (monochrome) { }', + description: 'boolean feature name', + }, + ], + + reject: [ + { + code: '@media (max-width: 50em) { }', + message: messages.rejected('max-width'), + line: 1, + column: 9, + }, + { + code: '@media print and (max-width: 50em) { }', + message: messages.rejected('max-width'), + line: 1, + column: 19, + }, + { + code: '@media handheld and (min-width: 20em), screen and (max-width: 20em) { }', + message: messages.rejected('max-width'), + line: 1, + column: 52, + }, + { + code: '@media (my-width: 50em) { }', + message: messages.rejected('my-width'), + line: 1, + column: 9, + }, + { + code: '@media (color) { }', + message: messages.rejected('color'), + line: 1, + column: 9, + }, + { + code: '@media (width: 50em) { }', + message: messages.rejected('width'), + line: 1, + column: 9, + }, + { + code: '@media (20em < width <= 50em) { }', + message: messages.rejected('width'), + line: 1, + column: 16, + }, + { + code: '@media (10em < max-width <= 50em) and (width > 50em) { }', + warnings: [ + { + message: messages.rejected('max-width'), + line: 1, + column: 16, + }, + { + message: messages.rejected('width'), + line: 1, + column: 40, + }, + ], + }, + ], +}); + +testRule({ + ruleName, + config: [/^my-/], + + accept: [ + { + code: '@media (min-width: 50em) { }', + }, + ], + + reject: [ + { + code: '@media (my-width: 50em) { }', + message: messages.rejected('my-width'), + line: 1, + column: 9, + }, + { + code: '@media (my-width >= 50em) { }', + message: messages.rejected('my-width'), + line: 1, + column: 9, + }, + { + code: '@media (10em < my-width <= 50em) { }', + message: messages.rejected('my-width'), + line: 1, + column: 16, + }, + { + code: '@media (50em < my-width) { }', + message: messages.rejected('my-width'), + line: 1, + column: 16, + }, + ], +}); + +testRule({ + ruleName, + config: ['feature-name'], + syntax: 'less', + + accept: [ + { + code: '@media @feature-name and (orientation: landscape) { }', + }, + { + code: '@media @feature-name { }', + }, + ], +}); + +testRule({ + ruleName, + config: ['feature-name', 'width'], + syntax: 'scss', + + accept: [ + { + code: '@media not all and ($feature-name) { }', + }, + { + code: '@media not all and ($FEATURE-NAME) { }', + }, + { + code: '@media not all and (#{feature-name}) { }', + }, + { + code: '@media not all and (#{FEATURE-NAME}) { }', + }, + { + code: '@media ($feature-name: $value) { }', + }, + { + code: '@media ($FEATURE-NAME: $value) { }', + }, + { + code: '@media (#{$feature-name}: $value) { }', + }, + { + code: '@media (#{$FEATURE-NAME}: $value) { }', + }, + { + code: "@media ('min-' + $width: $value) { }", + }, + { + code: "@media ('MIN-' + $WIDTH: $value) { }", + }, + { + code: "@media ($value + 'width': $value) { }", + }, + { + code: "@media ($VALUE + 'WIDTH': $value) { }", + }, + { + code: '@media (#{$width}: $value) { }', + }, + { + code: '@media (#{$WIDTH}: $value) { }', + }, + { + code: '@media #{$feature-name} { }', + }, + ], +}); diff --git a/lib/rules/media-feature-name-blacklist/index.js b/lib/rules/media-feature-name-blacklist/index.js new file mode 100644 index 0000000000..40f0a54db1 --- /dev/null +++ b/lib/rules/media-feature-name-blacklist/index.js @@ -0,0 +1,84 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); +const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); +const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const mediaParser = require('postcss-media-query-parser').default; +const rangeContextNodeParser = require('../rangeContextNodeParser'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'media-feature-name-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected media feature name "${name}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkAtRules(/^media$/i, (atRule) => { + mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => { + const parent = mediaFeatureNode.parent; + const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value); + + let value; + let sourceIndex; + + if (mediaFeatureRangeContext) { + const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); + + value = parsedRangeContext.name.value; + sourceIndex = parsedRangeContext.name.sourceIndex; + } else { + value = mediaFeatureNode.value; + sourceIndex = mediaFeatureNode.sourceIndex; + } + + if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) { + return; + } + + if (!matchesStringOrRegExp(value, list)) { + return; + } + + report({ + index: atRuleParamIndex(atRule) + sourceIndex, + message: messages.rejected(value), + node: atRule, + ruleName, + result, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/media-feature-name-disallowed-list/README.md b/lib/rules/media-feature-name-disallowed-list/README.md index aa4b012208..cd232e1736 100644 --- a/lib/rules/media-feature-name-disallowed-list/README.md +++ b/lib/rules/media-feature-name-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed media feature names. * This media feature name */ ``` -This rule was previously called, and is aliased as, `media-feature-name-blacklist`. - ## Options `array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` diff --git a/lib/rules/media-feature-name-value-allowed-list/README.md b/lib/rules/media-feature-name-value-allowed-list/README.md index 0e45c430d8..e81fd3cf29 100644 --- a/lib/rules/media-feature-name-value-allowed-list/README.md +++ b/lib/rules/media-feature-name-value-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed media feature name and value pairs. * These features and values */ ``` -This rule was previously called, and is aliased as, `media-feature-name-value-whitelist`. - ## Options ```js diff --git a/lib/rules/media-feature-name-value-whitelist/README.md b/lib/rules/media-feature-name-value-whitelist/README.md new file mode 100644 index 0000000000..3a975e64d7 --- /dev/null +++ b/lib/rules/media-feature-name-value-whitelist/README.md @@ -0,0 +1,86 @@ +# media-feature-name-value-whitelist + +**_Deprecated: Instead use the [`media-feature-name-value-allowed-list`](../media-feature-name-value-allowed-list/README.md) rule._** + +Specify a list of allowed media feature name and value pairs. + + +```css +@media screen and (min-width: 768px) {} +/** ↑ ↑ + * These features and values */ +``` + +## Options + +```js +{ + "unprefixed-media-feature-name": ["array", "of", "values"], + "/unprefixed-media-feature-name/": ["/regex/", "non-regex", /real-regex/] +} +``` + +If a media feature name is found in the object, only its allowed-listed values are +allowed. If the media feature name is not included in the object, anything goes. + +If a name or value is surrounded with `/` (e.g. `"/width$/"`), it is interpreted +as a regular expression. For example, `/width$/` will match `max-width` and +`min-width`. + +Given: + +``` +{ + "min-width": ["768px", "1024px"], + "/resolution/": ["/dpcm$/"] +} +``` + +The following patterns are considered violations: + + +```css +@media screen and (min-width: 1000px) {} +``` + + +```css +@media screen and (min-resolution: 2dpi) {} +``` + + +```css +@media screen and (min-width > 1000px) {} +``` + +The following patterns are _not_ considered violations: + + +```css +@media screen and (min-width: 768px) {} +``` + + +```css +@media screen and (min-width: 1024px) {} +``` + + +```css +@media screen and (orientation: portrait) {} +``` + + +```css +@media screen and (min-resolution: 2dpcm) {} +``` + + +```css +@media screen and (resolution: 10dpcm) {} +``` + + +```css +@media screen and (768px < min-width) {} +``` diff --git a/lib/rules/media-feature-name-value-whitelist/__tests__/index.js b/lib/rules/media-feature-name-value-whitelist/__tests__/index.js new file mode 100644 index 0000000000..e7d1f0baf2 --- /dev/null +++ b/lib/rules/media-feature-name-value-whitelist/__tests__/index.js @@ -0,0 +1,195 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [{ color: [] }], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-value-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: [ + { + 'min-width': ['768px', '$sm'], + '/resolution/': ['/dpcm$/'], // Only dpcm unit + color: [], // Test boolean context + width: [], // Test range context + }, + ], + + accept: [ + { + code: '@media screen and (min-width: 768px) {}', + description: 'Specified media feature', + }, + { + code: '@media screen and ( min-width : 768px ) {}', + description: 'Whitespace', + }, + { + code: '@media screen and (max-width: 1000px) {}', + description: 'Unspecified media feature', + }, + { + code: '@media screen and ( min-resolution : 2dpcm ) {}', + description: 'Regex feature name and Regex value', + }, + { + code: '@media screen and (resolution: 10.1dpcm) {}', + description: 'Floating point value', + }, + { + code: '@media screen and (min-width: $sm) {}', + description: 'Non-standard syntax in allowed list', + }, + { + code: '@media (color) {}', + description: 'Boolean context, media feature in allowed list', + }, + { + code: '@media (update) {}', + description: 'Boolean context, media feature NOT in allowed list', + }, + { + code: '@media (update /* pw:ned */) {}', + description: 'Boolean context with colon in comments', + }, + { + code: '@media screen and (min-width <= 768px) {}', + description: 'Range context, media feature in allowed list', + }, + ], + + reject: [ + { + code: '@media screen and (min-width: 1000px) {}', + message: messages.rejected('min-width', '1000px'), + line: 1, + column: 31, + }, + { + code: '@media screen (min-width: 768px) and (min-width: 1000px) {}', + description: 'Media feature multiple', + message: messages.rejected('min-width', '1000px'), + line: 1, + column: 50, + }, + { + code: '@media screen (min-width: 768px)\nand (min-width: 1000px) {}', + description: 'Media feature multiline', + message: messages.rejected('min-width', '1000px'), + line: 2, + column: 17, + }, + { + code: '@media screen and (min-width: 768PX) {}', + description: 'Case sensitive', + message: messages.rejected('min-width', '768PX'), + line: 1, + column: 31, + }, + { + code: '@media screen and (min-width: $md) {}', + description: 'Non-standard syntax NOT in allowed list', + message: messages.rejected('min-width', '$md'), + line: 1, + column: 31, + }, + { + code: '@media screen and (min-resolution: 2dpi) {}', + message: messages.rejected('min-resolution', '2dpi'), + line: 1, + column: 37, + }, + { + code: '@media screen and (min-width > 500px) {}', + message: messages.rejected('min-width', '500px'), + line: 1, + column: 32, + }, + { + code: '@media screen and (400px < min-width) {}', + message: messages.rejected('min-width', '400px'), + line: 1, + column: 20, + }, + { + code: '@media (400px < min-width < 500px) and (min-width < 1200px)', + warnings: [ + { + message: messages.rejected('min-width', '400px'), + line: 1, + column: 9, + }, + { + message: messages.rejected('min-width', '500px'), + line: 1, + column: 29, + }, + { + message: messages.rejected('min-width', '1200px'), + line: 1, + column: 53, + }, + ], + }, + ], +}); + +testRule({ + ruleName, + config: [ + { + '/resolution/': [/dpcm$/], // Only dpcm unit + }, + ], + + accept: [ + { + code: '@media screen and (min-width: 768px) {}', + description: 'Specified media feature', + }, + { + code: '@media screen and ( min-resolution : 2dpcm ) {}', + description: 'Regex feature name and Regex value', + }, + { + code: '@media screen and (resolution: 10.1dpcm) {}', + description: 'Floating point value', + }, + ], + + reject: [ + { + code: '@media screen and (min-resolution: 2dpi) {}', + message: messages.rejected('min-resolution', '2dpi'), + line: 1, + column: 37, + }, + { + code: '@media screen and (min-resolution > 2dpi) {}', + message: messages.rejected('min-resolution', '2dpi'), + line: 1, + column: 38, + }, + ], +}); diff --git a/lib/rules/media-feature-name-value-whitelist/index.js b/lib/rules/media-feature-name-value-whitelist/index.js new file mode 100644 index 0000000000..3eb18856e5 --- /dev/null +++ b/lib/rules/media-feature-name-value-whitelist/index.js @@ -0,0 +1,97 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const mediaParser = require('postcss-media-query-parser').default; +const postcss = require('postcss'); +const rangeContextNodeParser = require('../rangeContextNodeParser'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'media-feature-name-value-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (name, value) => `Unexpected value "${value}" for name "${name}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isObject], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-value-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkAtRules(/^media$/i, (atRule) => { + mediaParser(atRule.params).walk(/^media-feature-expression$/i, (node) => { + const mediaFeatureRangeContext = isRangeContextMediaFeature(node.parent.value); + + // Ignore boolean + if (!node.value.includes(':') && !mediaFeatureRangeContext) { + return; + } + + const mediaFeatureNode = _.find(node.nodes, { type: 'media-feature' }); + + let mediaFeatureName; + let values = []; + + if (mediaFeatureRangeContext) { + const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); + + mediaFeatureName = parsedRangeContext.name.value; + values = parsedRangeContext.values; + } else { + mediaFeatureName = mediaFeatureNode.value; + values.push(_.find(node.nodes, { type: 'value' })); + } + + for (let i = 0; i < values.length; i++) { + const valueNode = values[i]; + const value = valueNode.value; + const unprefixedMediaFeatureName = postcss.vendor.unprefixed(mediaFeatureName); + + const allowedValues = _.find(list, (v, featureName) => + matchesStringOrRegExp(unprefixedMediaFeatureName, featureName), + ); + + if (allowedValues === undefined) { + return; + } + + if (matchesStringOrRegExp(value, allowedValues)) { + return; + } + + report({ + index: atRuleParamIndex(atRule) + valueNode.sourceIndex, + message: messages.rejected(mediaFeatureName, value), + node: atRule, + ruleName, + result, + }); + } + }); + }); + }; +} + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/media-feature-name-whitelist/README.md b/lib/rules/media-feature-name-whitelist/README.md new file mode 100644 index 0000000000..292ab9afe9 --- /dev/null +++ b/lib/rules/media-feature-name-whitelist/README.md @@ -0,0 +1,66 @@ +# media-feature-name-whitelist + +**_Deprecated: Instead use the [`media-feature-name-allowed-list`](../media-feature-name-allowed-list/README.md) rule._** + +Specify a list of allowed media feature names. + + +```css +@media (min-width: 700px) {} +/** ↑ + * This media feature name */ +``` + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", /media-features/ or "regex"]|"media-feature"|/regex/` + +Given: + +``` +["max-width", "/^my-/"] +``` + +The following patterns are considered violations: + + +```css +@media (min-width: 50em) {} +``` + + +```css +@media print and (min-resolution: 300dpi) {} +``` + + +```css +@media (min-width < 50em) {} +``` + + +```css +@media (10em < min-width < 50em) {} +``` + +The following patterns are _not_ considered violations: + + +```css +@media (max-width: 50em) {} +``` + + +```css +@media (my-width: 50em) {} +``` + + +```css +@media (max-width > 50em) {} +``` + + +```css +@media (10em < my-width < 50em) {} +``` diff --git a/lib/rules/media-feature-name-whitelist/__tests__/index.js b/lib/rules/media-feature-name-whitelist/__tests__/index.js new file mode 100644 index 0000000000..f0af8f625b --- /dev/null +++ b/lib/rules/media-feature-name-whitelist/__tests__/index.js @@ -0,0 +1,218 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['max-width'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['max-width', '/^my-/', 'color'], + + accept: [ + { + code: '@media (max-width: 50em) { }', + }, + { + code: '@media (--wide-viewport) { }', + description: 'ignore custom media query', + }, + { + code: '@media (/* min-width: 50em */ max-width: 50em) { }', + description: 'ignore comments', + }, + { + code: '@media (max-width <= 50em) { }', + }, + { + code: '@media (400px < my-width < 1000px) { }', + }, + { + code: '@media (my-width: 50em) { }', + }, + { + code: '@media (my-max-width: 50em) { }', + }, + { + code: '@media print and (max-width: 50em) { }', + }, + { + code: '@media (color) { }', + }, + ], + + reject: [ + { + code: '@media (MaX-wIdTh: 50em) { }', + message: messages.rejected('MaX-wIdTh'), + line: 1, + column: 9, + }, + { + code: '@media (min-width: 50em) { }', + message: messages.rejected('min-width'), + line: 1, + column: 9, + }, + { + code: '@media (-webkit-min-device-pixel-ratio: 2) { }', + message: messages.rejected('-webkit-min-device-pixel-ratio'), + line: 1, + column: 9, + }, + { + code: '@media handheld and (max-width: 20em), screen and (min-width: 20em) { }', + message: messages.rejected('min-width'), + line: 1, + column: 52, + }, + { + code: '@media (monochrome) { }', + message: messages.rejected('monochrome'), + line: 1, + column: 9, + }, + { + code: '@media (width: 50em) { }', + message: messages.rejected('width'), + line: 1, + column: 9, + }, + { + code: '@media (50em < width) { }', + message: messages.rejected('width'), + line: 1, + column: 16, + }, + { + code: '@media (10em < width <= 50em) { }', + message: messages.rejected('width'), + line: 1, + column: 16, + }, + { + code: '@media (max-width <= 50em) and (10em < min-width < 50em) { }', + message: messages.rejected('min-width'), + line: 1, + column: 40, + }, + ], +}); + +testRule({ + ruleName, + config: [/^my-/], + + accept: [ + { + code: '@media (my-width: 50em) { }', + }, + { + code: '@media (my-max-width: 50em) { }', + }, + { + code: '@media (my-width >= 50em) { }', + }, + { + code: '@media (10em < my-max-width <= 50em) { }', + }, + ], + + reject: [ + { + code: '@media (MaX-wIdTh: 50em) { }', + message: messages.rejected('MaX-wIdTh'), + line: 1, + column: 9, + }, + ], +}); + +testRule({ + ruleName, + config: ['max-width', 'orientation'], + syntax: 'less', + + accept: [ + { + code: '@media @feature-name and (orientation: landscape) { }', + }, + { + code: '@media @feature-name { }', + }, + ], +}); + +testRule({ + ruleName, + config: ['max-width'], + syntax: 'scss', + + accept: [ + { + code: '@media not all and ($feature-name) { }', + }, + { + code: '@media not all and ($FEATURE-NAME) { }', + }, + { + code: '@media not all and (#{feature-name}) { }', + }, + { + code: '@media not all and (#{FEATURE-NAME}) { }', + }, + { + code: '@media ($feature-name: $value) { }', + }, + { + code: '@media ($FEATURE-NAME: $value) { }', + }, + { + code: '@media (#{$feature-name}: $value) { }', + }, + { + code: '@media (#{$FEATURE-NAME}: $value) { }', + }, + { + code: "@media ('min-' + $width: $value) { }", + }, + { + code: "@media ('MIN-' + $WIDTH: $value) { }", + }, + { + code: "@media ($value + 'width': $value) { }", + }, + { + code: "@media ($VALUE + 'WIDTH': $value) { }", + }, + { + code: '@media (#{$width}: $value) { }', + }, + { + code: '@media (#{$WIDTH}: $value) { }', + }, + { + code: '@media #{$feature-name} { }', + }, + ], +}); diff --git a/lib/rules/media-feature-name-whitelist/index.js b/lib/rules/media-feature-name-whitelist/index.js new file mode 100644 index 0000000000..ebfdff9fb6 --- /dev/null +++ b/lib/rules/media-feature-name-whitelist/index.js @@ -0,0 +1,84 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const isCustomMediaQuery = require('../../utils/isCustomMediaQuery'); +const isRangeContextMediaFeature = require('../../utils/isRangeContextMediaFeature'); +const isStandardSyntaxMediaFeatureName = require('../../utils/isStandardSyntaxMediaFeatureName'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const mediaParser = require('postcss-media-query-parser').default; +const rangeContextNodeParser = require('../rangeContextNodeParser'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'media-feature-name-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (name) => `Unexpected media feature name "${name}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'media-feature-name-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkAtRules(/^media$/i, (atRule) => { + mediaParser(atRule.params).walk(/^media-feature$/i, (mediaFeatureNode) => { + const parent = mediaFeatureNode.parent; + const mediaFeatureRangeContext = isRangeContextMediaFeature(parent.value); + + let value; + let sourceIndex; + + if (mediaFeatureRangeContext) { + const parsedRangeContext = rangeContextNodeParser(mediaFeatureNode); + + value = parsedRangeContext.name.value; + sourceIndex = parsedRangeContext.name.sourceIndex; + } else { + value = mediaFeatureNode.value; + sourceIndex = mediaFeatureNode.sourceIndex; + } + + if (!isStandardSyntaxMediaFeatureName(value) || isCustomMediaQuery(value)) { + return; + } + + if (matchesStringOrRegExp(value, list)) { + return; + } + + report({ + index: atRuleParamIndex(atRule) + sourceIndex, + message: messages.rejected(value), + node: atRule, + ruleName, + result, + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/property-allowed-list/README.md b/lib/rules/property-allowed-list/README.md index 4383c3164c..e2b2250e1a 100644 --- a/lib/rules/property-allowed-list/README.md +++ b/lib/rules/property-allowed-list/README.md @@ -9,8 +9,6 @@ a { display: block; } * This property */ ``` -This rule was previously called, and is aliased as, `property-whitelist`. - This rule ignores variables (`$sass`, `@less`, `--custom-property`). ## Options diff --git a/lib/rules/property-blacklist/README.md b/lib/rules/property-blacklist/README.md new file mode 100644 index 0000000000..b244fb8584 --- /dev/null +++ b/lib/rules/property-blacklist/README.md @@ -0,0 +1,66 @@ +# property-blacklist + +**_Deprecated: Instead use the [`property-disallowed-list`](../property-disallowed-list/README.md) rule._** + +Specify a list of disallowed properties. + + +```css +a { text-rendering: optimizeLegibility; } +/** ↑ + * This property */ +``` + +## Options + +`array|string`: `["array", "of", "unprefixed", /properties/ or "regex"]|"property"|"/regex/"`|/regex/ + +If a string is surrounded with `"/"` (e.g. `"/^background/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^background/` will match `background`, `background-size`, `background-color`, etc. + +Given: + +``` +["text-rendering", "animation", "/^background/"] +``` + +The following patterns are considered violations: + + +```css +a { text-rendering: optimizeLegibility; } +``` + + +```css +a { + animation: my-animation 2s; + color: pink; +} +``` + + +```css +a { -webkit-animation: my-animation 2s; } +``` + + +```css +a { background: pink; } +``` + + +```css +a { background-size: cover; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { color: pink; } +``` + + +```css +a { no-background: sure; } +``` diff --git a/lib/rules/property-blacklist/__tests__/index.js b/lib/rules/property-blacklist/__tests__/index.js new file mode 100644 index 0000000000..68a3c450aa --- /dev/null +++ b/lib/rules/property-blacklist/__tests__/index.js @@ -0,0 +1,182 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'property-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [''], + + accept: [ + { + code: 'a { color: pink; }', + }, + ], +}); + +testRule({ + ruleName, + + config: [[]], + + accept: [ + { + code: 'a { color: pink; }', + }, + ], +}); + +testRule({ + ruleName, + + config: ['transform', 'background-size'], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { background: red; }', + }, + { + code: 'a { top: 0; color: pink; }', + }, + { + code: 'a { $scss: 0; }', + }, + { + code: 'a { @less: 0; }', + }, + { + code: 'a { --custom-property: 0; }', + }, + ], + + reject: [ + { + code: 'a { transform: scale(1); }', + message: messages.rejected('transform'), + line: 1, + column: 5, + }, + { + code: 'a { color: pink; background-size: cover; }', + message: messages.rejected('background-size'), + line: 1, + column: 18, + }, + { + code: 'a { color: pink; -webkit-transform: scale(1); }', + message: messages.rejected('-webkit-transform'), + line: 1, + column: 18, + }, + ], +}); + +testRule({ + ruleName, + + config: [['/^background/']], + + accept: [ + { + code: 'a { color: pink; }', + }, + { + code: 'a { no-background: sure; }', + }, + { + code: 'a { $scss: 0; }', + }, + { + code: 'a { @less: 0; }', + }, + { + code: 'a { --custom-property: 0; }', + }, + ], + + reject: [ + { + code: 'a { background: pink; }', + message: messages.rejected('background'), + line: 1, + column: 5, + }, + { + code: 'a { background-size: cover; }', + message: messages.rejected('background-size'), + line: 1, + column: 5, + }, + { + code: 'a { background-image: none; }', + message: messages.rejected('background-image'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: [[/^background/]], + + accept: [ + { + code: 'a { color: pink; }', + }, + ], + + reject: [ + { + code: 'a { background-size: cover; }', + message: messages.rejected('background-size'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: ['/margin/'], + + accept: [ + { + code: 'a { $margin: 0; }', + }, + { + code: 'a { @margin: 0; }', + }, + { + code: 'a { --margin: 0; }', + }, + ], +}); diff --git a/lib/rules/property-blacklist/index.js b/lib/rules/property-blacklist/index.js new file mode 100644 index 0000000000..6744c9dc16 --- /dev/null +++ b/lib/rules/property-blacklist/index.js @@ -0,0 +1,65 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isCustomProperty = require('../../utils/isCustomProperty'); +const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'property-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (property) => `Unexpected property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'property-disallowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkDecls((decl) => { + const prop = decl.prop; + + if (!isStandardSyntaxProperty(prop)) { + return; + } + + if (isCustomProperty(prop)) { + return; + } + + if (!matchesStringOrRegExp(postcss.vendor.unprefixed(prop), list)) { + return; + } + + report({ + message: messages.rejected(prop), + node: decl, + result, + ruleName, + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/property-disallowed-list/README.md b/lib/rules/property-disallowed-list/README.md index 012981f710..81edc3444f 100644 --- a/lib/rules/property-disallowed-list/README.md +++ b/lib/rules/property-disallowed-list/README.md @@ -9,8 +9,6 @@ a { text-rendering: optimizeLegibility; } * This property */ ``` -This rule was previously called, and is aliased as, `property-blacklist`. - ## Options `array|string`: `["array", "of", "unprefixed", /properties/ or "regex"]|"property"|"/regex/"`|/regex/ diff --git a/lib/rules/property-whitelist/README.md b/lib/rules/property-whitelist/README.md new file mode 100644 index 0000000000..1500c0ca19 --- /dev/null +++ b/lib/rules/property-whitelist/README.md @@ -0,0 +1,77 @@ +# property-whitelist + +**_Deprecated: Instead use the [`property-allowed-list`](../property-allowed-list/README.md) rule._** + +Specify a list of allowed properties. + + +```css +a { display: block; } +/** ↑ + * This property */ +``` + +This rule ignores variables (`$sass`, `@less`, `--custom-property`). + +## Options + +`array|string`: `["array", "of", "unprefixed", /properties/ or "regex"]|"property"|"/regex/"`|/regex/ + +If a string is surrounded with `"/"` (e.g. `"/^background/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^background/` will match `background`, `background-size`, `background-color`, etc. + +Given: + +``` +["display", "animation", "/^background/"] +``` + +The following patterns are considered violations: + + +```css +a { color: pink; } +``` + + +```css +a { + animation: my-animation 2s; + color: pink; +} +``` + + +```css +a { borkgrund: orange; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { display: block; } +``` + + +```css +a { -webkit-animation: my-animation 2s; } +``` + + +```css +a { + animation: my-animation 2s; + -webkit-animation: my-animation 2s; + display: block; +} +``` + + +```css +a { background: pink; } +``` + + +```css +a { background-color: pink; } +``` diff --git a/lib/rules/property-whitelist/__tests__/index.js b/lib/rules/property-whitelist/__tests__/index.js new file mode 100644 index 0000000000..65efbc1efb --- /dev/null +++ b/lib/rules/property-whitelist/__tests__/index.js @@ -0,0 +1,191 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: [], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'property-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: [''], + + reject: [ + { + code: 'a { color: pink; }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: [[]], + + reject: [ + { + code: 'a { color: pink; }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: ['transform', 'background-size'], + + accept: [ + { + code: 'a { background-size: cover; }', + }, + { + code: 'a { transform: scale(1); }', + }, + { + code: 'a { -webkit-transform: scale(1); }', + }, + { + code: 'a { transform: scale(1); background-size: cover; }', + }, + { + code: 'a { transform: scale(1); -webkit-transform: scale(1); background-size: cover; }', + }, + { + code: 'a { $scss: 0; }', + }, + { + code: 'a { @less: 0; }', + }, + { + code: 'a { --custom-property: 0; }', + }, + ], + + reject: [ + { + code: 'a { background: pink; }', + message: messages.rejected('background'), + line: 1, + column: 5, + }, + { + code: 'a { color: pink; }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + { + code: 'a { overflow: hidden; background-size: cover; }', + message: messages.rejected('overflow'), + line: 1, + column: 5, + }, + { + code: 'a { color: orange; -webkit-transform: scale(1); }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: [['/^background/']], + + accept: [ + { + code: 'a { background: pink; }', + }, + { + code: 'a { background-color: pink; }', + }, + { + code: 'a { background-image: none; }', + }, + { + code: 'a { $scss: 0; }', + }, + { + code: 'a { @less: 0; }', + }, + { + code: 'a { --custom-property: 0; }', + }, + ], + + reject: [ + { + code: 'a { color: pink; }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: [[/^background/]], + + accept: [ + { + code: 'a { background-image: none; }', + }, + ], + + reject: [ + { + code: 'a { color: pink; }', + message: messages.rejected('color'), + line: 1, + column: 5, + }, + ], +}); + +testRule({ + ruleName, + + config: ['/margin/'], + + accept: [ + { + code: 'a { $padding: 0; }', + }, + { + code: 'a { @padding: 0; }', + }, + { + code: 'a { --padding: 0; }', + }, + ], +}); diff --git a/lib/rules/property-whitelist/index.js b/lib/rules/property-whitelist/index.js new file mode 100644 index 0000000000..81f4fb0f8a --- /dev/null +++ b/lib/rules/property-whitelist/index.js @@ -0,0 +1,65 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isCustomProperty = require('../../utils/isCustomProperty'); +const isStandardSyntaxProperty = require('../../utils/isStandardSyntaxProperty'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'property-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (property) => `Unexpected property "${property}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'property-allowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + root.walkDecls((decl) => { + const prop = decl.prop; + + if (!isStandardSyntaxProperty(prop)) { + return; + } + + if (isCustomProperty(prop)) { + return; + } + + if (matchesStringOrRegExp(postcss.vendor.unprefixed(prop), list)) { + return; + } + + report({ + message: messages.rejected(prop), + node: decl, + result, + ruleName, + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-allowed-list/README.md b/lib/rules/selector-attribute-operator-allowed-list/README.md index 6cdbae223b..557d9ec0a8 100644 --- a/lib/rules/selector-attribute-operator-allowed-list/README.md +++ b/lib/rules/selector-attribute-operator-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed attribute operators. * This operator */ ``` -This rule was previously called, and is aliased as, `selector-attribute-operator-whitelist`. - ## Options `array|string`: `["array", "of", "operators"]|"operator"` diff --git a/lib/rules/selector-attribute-operator-blacklist/README.md b/lib/rules/selector-attribute-operator-blacklist/README.md new file mode 100644 index 0000000000..f3e54f4629 --- /dev/null +++ b/lib/rules/selector-attribute-operator-blacklist/README.md @@ -0,0 +1,46 @@ +# selector-attribute-operator-blacklist + +**_Deprecated: Instead use the [`selector-attribute-operator-disallowed-list`](../selector-attribute-operator-disallowed-list/README.md) rule._** + +Specify a list of disallowed attribute operators. + + +```css +[target="_blank"] {} +/** ↑ + * This operator */ +``` + +## Options + +`array|string`: `["array", "of", "operators"]|"operator"` + +Given: + +``` +["*="] +``` + +The following patterns are considered violations: + + +```css +[class*="test"] {} +``` + +The following patterns are _not_ considered violations: + + +```css +[target] {} +``` + + +```css +[target="_blank"] {} +``` + + +```css +[class|="top"] {} +``` diff --git a/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js b/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js new file mode 100644 index 0000000000..e6d9f654d3 --- /dev/null +++ b/lib/rules/selector-attribute-operator-blacklist/__tests__/index.js @@ -0,0 +1,114 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['~='], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['*=', '~='], + + accept: [ + { + code: 'a[target] { }', + }, + { + code: 'a[target="_blank"] { }', + }, + { + code: '[class|="top"] { }', + }, + { + code: '[class^=top] { }', + }, + { + code: '[class$="test"] { }', + }, + { + code: ':root { --foo: 1px; }', + description: 'custom property in root', + }, + { + code: 'html { --foo: 1px; }', + description: 'custom property in selector', + }, + { + code: ':root { --custom-property-set: {} }', + description: 'custom property set in root', + }, + { + code: 'html { --custom-property-set: {} }', + description: 'custom property set in selector', + }, + ], + + reject: [ + { + code: '[title~="flower"] { }', + message: messages.rejected('~='), + line: 1, + column: 7, + }, + { + code: '[ title~="flower" ] { }', + message: messages.rejected('~='), + line: 1, + column: 8, + }, + { + code: '[title ~= "flower"] { }', + message: messages.rejected('~='), + line: 1, + column: 8, + }, + { + code: '[class*=te] { }', + message: messages.rejected('*='), + line: 1, + column: 7, + }, + ], +}); + +testRule({ + ruleName, + + config: ['*='], + + accept: [ + { + code: 'a[target="_blank"] { }', + }, + ], + + reject: [ + { + code: '[title*="foo"] { }', + message: messages.rejected('*='), + line: 1, + column: 7, + }, + ], +}); diff --git a/lib/rules/selector-attribute-operator-blacklist/index.js b/lib/rules/selector-attribute-operator-blacklist/index.js new file mode 100644 index 0000000000..d28b3d09ea --- /dev/null +++ b/lib/rules/selector-attribute-operator-blacklist/index.js @@ -0,0 +1,73 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const parseSelector = require('../../utils/parseSelector'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-attribute-operator-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (operator) => `Unexpected operator "${operator}"`, +}); + +function rule(listInput) { + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + if (!rule.selector.includes('[') || !rule.selector.includes('=')) { + return; + } + + parseSelector(rule.selector, result, rule, (selectorTree) => { + selectorTree.walkAttributes((attributeNode) => { + const operator = attributeNode.operator; + + if (!operator || (operator && !list.includes(operator))) { + return; + } + + report({ + message: messages.rejected(operator), + node: rule, + index: attributeNode.sourceIndex + attributeNode.offsetOf('operator'), + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-attribute-operator-disallowed-list/README.md b/lib/rules/selector-attribute-operator-disallowed-list/README.md index 97b51a25d3..62cbb512bc 100644 --- a/lib/rules/selector-attribute-operator-disallowed-list/README.md +++ b/lib/rules/selector-attribute-operator-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed attribute operators. * This operator */ ``` -This rule was previously called, and is aliased as, `selector-attribute-operator-blacklist`. - ## Options `array|string`: `["array", "of", "operators"]|"operator"` diff --git a/lib/rules/selector-attribute-operator-whitelist/README.md b/lib/rules/selector-attribute-operator-whitelist/README.md new file mode 100644 index 0000000000..364d8266e6 --- /dev/null +++ b/lib/rules/selector-attribute-operator-whitelist/README.md @@ -0,0 +1,56 @@ +# selector-attribute-operator-whitelist + +**_Deprecated: Instead use the [`selector-attribute-operator-allowed-list`](../selector-attribute-operator-allowed-list/README.md) rule._** + +Specify a list of allowed attribute operators. + + +```css +[target="_blank"] {} +/** ↑ + * This operator */ +``` + +## Options + +`array|string`: `["array", "of", "operators"]|"operator"` + +Given: + +``` +["=", "|="] +``` + +The following patterns are considered violations: + + +```css +[class*="test"] {} +``` + + +```css +[title~="flower"] {} +``` + + +```css +[class^="top"] {} +``` + +The following patterns are _not_ considered violations: + + +```css +[target] {} +``` + + +```css +[target="_blank"] {} +``` + + +```css +[class|="top"] {} +``` diff --git a/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js b/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js new file mode 100644 index 0000000000..e43b0c1683 --- /dev/null +++ b/lib/rules/selector-attribute-operator-whitelist/__tests__/index.js @@ -0,0 +1,120 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['='], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['=', '|='], + + accept: [ + { + code: 'a[target] { }', + }, + { + code: 'a[target="_blank"] { }', + }, + { + code: '[class|="top"] { }', + }, + { + code: ':root { --foo: 1px; }', + description: 'custom property in root', + }, + { + code: 'html { --foo: 1px; }', + description: 'custom property in selector', + }, + { + code: ':root { --custom-property-set: {} }', + description: 'custom property set in root', + }, + { + code: 'html { --custom-property-set: {} }', + description: 'custom property set in selector', + }, + ], + + reject: [ + { + code: '[title~="flower"] { }', + message: messages.rejected('~='), + line: 1, + column: 7, + }, + { + code: '[ title~="flower" ] { }', + message: messages.rejected('~='), + line: 1, + column: 8, + }, + { + code: '[title ~= "flower"] { }', + message: messages.rejected('~='), + line: 1, + column: 8, + }, + { + code: '[class^=top] { }', + message: messages.rejected('^='), + line: 1, + column: 7, + }, + { + code: '[class$="test"] { }', + message: messages.rejected('$='), + line: 1, + column: 7, + }, + { + code: '[class*=te] { }', + message: messages.rejected('*='), + line: 1, + column: 7, + }, + ], +}); + +testRule({ + ruleName, + + config: ['='], + + accept: [ + { + code: 'a[target="_blank"] { }', + }, + ], + + reject: [ + { + code: '[title~="flower"] { }', + message: messages.rejected('~='), + line: 1, + column: 7, + }, + ], +}); diff --git a/lib/rules/selector-attribute-operator-whitelist/index.js b/lib/rules/selector-attribute-operator-whitelist/index.js new file mode 100644 index 0000000000..34a39dfcc9 --- /dev/null +++ b/lib/rules/selector-attribute-operator-whitelist/index.js @@ -0,0 +1,73 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const parseSelector = require('../../utils/parseSelector'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-attribute-operator-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (operator) => `Unexpected operator "${operator}"`, +}); + +function rule(listInput) { + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-attribute-operator-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + if (!rule.selector.includes('[') || !rule.selector.includes('=')) { + return; + } + + parseSelector(rule.selector, result, rule, (selectorTree) => { + selectorTree.walkAttributes((attributeNode) => { + const operator = attributeNode.operator; + + if (!operator || (operator && list.includes(operator))) { + return; + } + + report({ + message: messages.rejected(operator), + node: rule, + index: attributeNode.sourceIndex + attributeNode.offsetOf('operator'), + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-combinator-allowed-list/README.md b/lib/rules/selector-combinator-allowed-list/README.md index 9181f40b93..5fdce86ffa 100644 --- a/lib/rules/selector-combinator-allowed-list/README.md +++ b/lib/rules/selector-combinator-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed combinators. * This combinator */ ``` -This rule was previously called, and is aliased as, `selector-combinator-whitelist`. - This rule normalizes the whitespace descendant combinator to be a single space. This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. diff --git a/lib/rules/selector-combinator-blacklist/README.md b/lib/rules/selector-combinator-blacklist/README.md new file mode 100644 index 0000000000..cb64dfe82b --- /dev/null +++ b/lib/rules/selector-combinator-blacklist/README.md @@ -0,0 +1,56 @@ +# selector-combinator-blacklist + +**_Deprecated: Instead use the [`selector-combinator-disallowed-list`](../selector-combinator-disallowed-list/README.md) rule._** + +Specify a list of disallowed combinators. + + +```css + a + b {} +/** ↑ + * This combinator */ +``` + +This rule normalizes the whitespace descendant combinator to be a single space. + +This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. + +## Options + +`array|string`: `["array", "of", "combinators"]|"combinator"` + +Given: + +``` +[">", " "] +``` + +The following patterns are considered violations: + + +```css +a > b {} +``` + + +```css +a b {} +``` + + +```css +a +b {} +``` + +The following patterns are _not_ considered violations: + + +```css +a + b {} +``` + + +```css +a ~ b {} +``` diff --git a/lib/rules/selector-combinator-blacklist/__tests__/index.js b/lib/rules/selector-combinator-blacklist/__tests__/index.js new file mode 100644 index 0000000000..e3ff4b7c43 --- /dev/null +++ b/lib/rules/selector-combinator-blacklist/__tests__/index.js @@ -0,0 +1,88 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['>'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-combinator-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); +testRule({ + ruleName, + config: ['>', ' '], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a, b {}', + }, + { + code: 'a /for/ b {}', + }, + { + code: 'a + b {}', + }, + { + code: 'a:not(b ~ c) {}', + }, + ], + + reject: [ + { + code: 'a b {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + { + code: 'a\tb {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + { + code: 'a\n\tb {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + { + code: 'a,\nb c {}', + message: messages.rejected(' '), + line: 2, + column: 2, + }, + { + code: 'a:not(b > c) {}', + message: messages.rejected('>'), + line: 1, + column: 9, + }, + { + code: 'a > b {}', + message: messages.rejected('>'), + line: 1, + column: 3, + }, + ], +}); diff --git a/lib/rules/selector-combinator-blacklist/index.js b/lib/rules/selector-combinator-blacklist/index.js new file mode 100644 index 0000000000..698dc7df4c --- /dev/null +++ b/lib/rules/selector-combinator-blacklist/index.js @@ -0,0 +1,78 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxCombinator = require('../../utils/isStandardSyntaxCombinator'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const parseSelector = require('../../utils/parseSelector'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-combinator-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (combinator) => `Unexpected combinator "${combinator}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-combinator-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + parseSelector(selector, result, rule, (fullSelector) => { + fullSelector.walkCombinators((combinatorNode) => { + if (!isStandardSyntaxCombinator(combinatorNode)) { + return; + } + + const value = normalizeCombinator(combinatorNode.value); + + if (!list.includes(value)) { + return; + } + + report({ + result, + ruleName, + message: messages.rejected(value), + node: rule, + index: combinatorNode.sourceIndex, + }); + }); + }); + }); + }; +} + +function normalizeCombinator(value) { + return value.replace(/\s+/g, ' '); +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-combinator-disallowed-list/README.md b/lib/rules/selector-combinator-disallowed-list/README.md index 98685b9867..ae4fe2a419 100644 --- a/lib/rules/selector-combinator-disallowed-list/README.md +++ b/lib/rules/selector-combinator-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed combinators. * This combinator */ ``` -This rule was previously called, and is aliased as, `selector-combinator-blacklist`. - This rule normalizes the whitespace descendant combinator to be a single space. This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. diff --git a/lib/rules/selector-combinator-whitelist/README.md b/lib/rules/selector-combinator-whitelist/README.md new file mode 100644 index 0000000000..49454ca37a --- /dev/null +++ b/lib/rules/selector-combinator-whitelist/README.md @@ -0,0 +1,56 @@ +# selector-combinator-whitelist + +**_Deprecated: Instead use the [`selector-combinator-allowed-list`](../selector-combinator-allowed-list/README.md) rule._** + +Specify a list of allowed combinators. + + +```css + a + b {} +/** ↑ + * This combinator */ +``` + +This rule normalizes the whitespace descendant combinator to be a single space. + +This rule ignores [reference combinators](https://www.w3.org/TR/selectors4/#idref-combinators) e.g. `/for/`. + +## Options + +`array|string`: `["array", "of", "combinators"]|"combinator"` + +Given: + +``` +[">", " "] +``` + +The following patterns are considered violations: + + +```css +a + b {} +``` + + +```css +a ~ b {} +``` + +The following patterns are _not_ considered violations: + + +```css +a > b {} +``` + + +```css +a b {} +``` + + +```css +a +b {} +``` diff --git a/lib/rules/selector-combinator-whitelist/__tests__/index.js b/lib/rules/selector-combinator-whitelist/__tests__/index.js new file mode 100644 index 0000000000..e08d23c145 --- /dev/null +++ b/lib/rules/selector-combinator-whitelist/__tests__/index.js @@ -0,0 +1,113 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['>'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-combinator-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['>', ' '], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a, b {}', + }, + { + code: 'a /for/ b {}', + }, + { + code: 'a > b {}', + }, + { + code: 'a:not(b > c) {}', + }, + { + code: 'a b {}', + }, + { + code: 'a\tb {}', + }, + { + code: 'a\nb {}', + }, + ], + + reject: [ + { + code: 'a ~ b {}', + message: messages.rejected('~'), + line: 1, + column: 3, + }, + { + code: 'a:not(b ~ c) {}', + message: messages.rejected('~'), + line: 1, + column: 9, + }, + { + code: 'a,\nb + c {}', + message: messages.rejected('+'), + line: 2, + column: 3, + }, + ], +}); + +testRule({ + ruleName, + config: ['~'], + skipBasicChecks: true, + + accept: [ + { + code: 'a ~ b {}', + }, + ], + + reject: [ + { + code: 'a b {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + { + code: 'a\tb {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + { + code: 'a\n\tb {}', + message: messages.rejected(' '), + line: 1, + column: 2, + }, + ], +}); diff --git a/lib/rules/selector-combinator-whitelist/index.js b/lib/rules/selector-combinator-whitelist/index.js new file mode 100644 index 0000000000..a2d28034c4 --- /dev/null +++ b/lib/rules/selector-combinator-whitelist/index.js @@ -0,0 +1,78 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxCombinator = require('../../utils/isStandardSyntaxCombinator'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const parseSelector = require('../../utils/parseSelector'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-combinator-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (combinator) => `Unexpected combinator "${combinator}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-combinator-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + parseSelector(selector, result, rule, (fullSelector) => { + fullSelector.walkCombinators((combinatorNode) => { + if (!isStandardSyntaxCombinator(combinatorNode)) { + return; + } + + const value = normalizeCombinator(combinatorNode.value); + + if (list.includes(value)) { + return; + } + + report({ + result, + ruleName, + message: messages.rejected(value), + node: rule, + index: combinatorNode.sourceIndex, + }); + }); + }); + }); + }; +} + +function normalizeCombinator(value) { + return value.replace(/\s+/g, ' '); +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-allowed-list/README.md b/lib/rules/selector-pseudo-class-allowed-list/README.md index b22b2711fa..5932b92623 100644 --- a/lib/rules/selector-pseudo-class-allowed-list/README.md +++ b/lib/rules/selector-pseudo-class-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed pseudo-class selectors. * This pseudo-class selector */ ``` -This rule was previously called, and is aliased as, `selector-pseudo-class-whitelist`. - This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. ## Options diff --git a/lib/rules/selector-pseudo-class-blacklist/README.md b/lib/rules/selector-pseudo-class-blacklist/README.md new file mode 100644 index 0000000000..be91d9a071 --- /dev/null +++ b/lib/rules/selector-pseudo-class-blacklist/README.md @@ -0,0 +1,55 @@ +# selector-pseudo-class-blacklist + +**_Deprecated: Instead use the [`selector-pseudo-class-disallowed-list`](../selector-pseudo-class-disallowed-list/README.md) rule._** + +Specify a list of disallowed pseudo-class selectors. + + +```css + a:hover {} +/** ↑ + * This pseudo-class selector */ +``` + +This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", /pseudo-classes/ or "/regex/"]|"pseudo-class"|/regex/` + +If a string is surrounded with `"/"` (e.g. `"/^nth-/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^nth-/` will match `nth-child`, `nth-last-child`, `nth-of-type`, etc. + +Given: + +``` +["hover", "/^nth-/"] +``` + +The following patterns are considered violations: + + +```css +a:hover {} +``` + + +```css +a:nth-of-type(5) {} +``` + + +```css +a:nth-child(2) {} +``` + +The following patterns are _not_ considered violations: + + +```css +a:focus {} +``` + + +```css +a:first-of-type {} +``` diff --git a/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js new file mode 100644 index 0000000000..9ee952df21 --- /dev/null +++ b/lib/rules/selector-pseudo-class-blacklist/__tests__/index.js @@ -0,0 +1,247 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['focus'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['focus', 'global', 'input-placeholder', 'not', 'nth-last-child', 'has'], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:hover {}', + }, + { + code: 'a:nth-child(5) {}', + }, + { + code: 'div:nth-LAST-child {}', + }, + { + code: 'input:-Ms-INPUT-placeholder {}', + }, + { + code: ':root {}', + }, + { + code: 'a:HOVER {}', + }, + { + code: 'a:hover, a:nth-child(5) {}', + }, + { + code: 'a::before {}', + }, + { + code: 'a:nth-child(5)::before {}', + }, + { + code: 'a:-moz-placeholder {}', + }, + { + code: 'a:-MOZ-PLACEholder {}', + }, + { + code: ':root { --foo: 1px; }', + description: 'custom property in root', + }, + { + code: 'html { --foo: 1px; }', + description: 'custom property in selector', + }, + { + code: ':root { --custom-property-set: {} }', + description: 'custom property set in root', + }, + { + code: 'html { --custom-property-set: {} }', + description: 'custom property set in selector', + }, + ], + + reject: [ + { + code: 'a:focus {}', + message: messages.rejected('focus'), + line: 1, + column: 2, + }, + { + code: 'a,\n:global {}', + message: messages.rejected('global'), + line: 2, + column: 1, + }, + { + code: 'input:-ms-input-placeholder {}', + message: messages.rejected('-ms-input-placeholder'), + line: 1, + column: 6, + }, + { + code: 'a:not(::selection) {}', + message: messages.rejected('not'), + line: 1, + column: 2, + }, + { + code: 'a:has(> img) {}', + message: messages.rejected('has'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: [['/^last/']], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:first-child() {}', + }, + { + code: 'a:nth-LAST-child(5) {}', + }, + ], + + reject: [ + { + code: 'a:last-child {}', + message: messages.rejected('last-child'), + line: 1, + column: 2, + }, + { + code: 'a:last-of-child {}', + message: messages.rejected('last-of-child'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: [[/^last/]], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + ], + + reject: [ + { + code: 'a:last-child {}', + message: messages.rejected('last-child'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: [[/(not|matches|has)/]], + skipBasicChecks: true, + + accept: [ + { + code: 'a:focus {}', + }, + ], + + reject: [ + { + code: 'a:not() {}', + message: messages.rejected('not'), + line: 1, + column: 2, + }, + { + code: 'body:not(div):has(span) {}', + warnings: [ + { + message: messages.rejected('not'), + line: 1, + column: 5, + }, + { + message: messages.rejected('has'), + line: 1, + column: 14, + }, + ], + }, + { + code: 'body:nt(div):not(span) {}', + message: messages.rejected('not'), + line: 1, + column: 13, + }, + { + code: 'a:has() {}', + message: messages.rejected('has'), + line: 1, + column: 2, + }, + { + code: 'a:matches() {}', + message: messages.rejected('matches'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: ['variable'], + skipBasicChecks: true, + syntax: 'scss', + + accept: [ + { + code: ':#{$variable} {}', + }, + { + code: ':#{$VARIABLE} {}', + }, + { + code: 'a:#{$variable} {}', + }, + ], +}); diff --git a/lib/rules/selector-pseudo-class-blacklist/index.js b/lib/rules/selector-pseudo-class-blacklist/index.js new file mode 100644 index 0000000000..73040ba475 --- /dev/null +++ b/lib/rules/selector-pseudo-class-blacklist/index.js @@ -0,0 +1,83 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const parseSelector = require('../../utils/parseSelector'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-pseudo-class-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (selector) => `Unexpected pseudo-class "${selector}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + if (!selector.includes(':')) { + return; + } + + parseSelector(selector, result, rule, (selectorTree) => { + selectorTree.walkPseudos((pseudoNode) => { + const value = pseudoNode.value; + + // Ignore pseudo-elements + + if (value.slice(0, 2) === '::') { + return; + } + + const name = value.slice(1); + + if (!matchesStringOrRegExp(postcss.vendor.unprefixed(name), list)) { + return; + } + + report({ + index: pseudoNode.sourceIndex, + message: messages.rejected(name), + node: rule, + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-pseudo-class-disallowed-list/README.md b/lib/rules/selector-pseudo-class-disallowed-list/README.md index bb21ebf65a..dbd5a98d31 100644 --- a/lib/rules/selector-pseudo-class-disallowed-list/README.md +++ b/lib/rules/selector-pseudo-class-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed pseudo-class selectors. * This pseudo-class selector */ ``` -This rule was previously called, and is aliased as, `selector-pseudo-class-blacklist`. - This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. ## Options diff --git a/lib/rules/selector-pseudo-class-whitelist/README.md b/lib/rules/selector-pseudo-class-whitelist/README.md new file mode 100644 index 0000000000..294f80300a --- /dev/null +++ b/lib/rules/selector-pseudo-class-whitelist/README.md @@ -0,0 +1,55 @@ +# selector-pseudo-class-whitelist + +**_Deprecated: Instead use the [`selector-pseudo-class-allowed-list`](../selector-pseudo-class-allowed-list/README.md) rule._** + +Specify a list of allowed pseudo-class selectors. + + +```css + a:hover {} +/** ↑ + * This pseudo-class selector */ +``` + +This rule ignores selectors that use variable interpolation e.g. `:#{$variable} {}`. + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", /pseudo-classes/ or "/regex/"]|"pseudo-class"|/regex/` + +If a string is surrounded with `"/"` (e.g. `"/^nth-/"`), it is interpreted as a regular expression. This allows, for example, easy targeting of shorthands: `/^nth-/` will match `nth-child`, `nth-last-child`, `nth-of-type`, etc. + +Given: + +``` +["hover", "/^nth-/"] +``` + +The following patterns are considered violations: + + +```css +a:focus {} +``` + + +```css +a:first-of-type {} +``` + +The following patterns are _not_ considered violations: + + +```css +a:hover {} +``` + + +```css +a:nth-of-type(5) {} +``` + + +```css +a:nth-child(2) {} +``` diff --git a/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js new file mode 100644 index 0000000000..136f7392a1 --- /dev/null +++ b/lib/rules/selector-pseudo-class-whitelist/__tests__/index.js @@ -0,0 +1,196 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['hover'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['hover', 'nth-child', 'root', 'placeholder', 'has'], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:hover {}', + }, + { + code: 'a:nth-child(5) {}', + }, + { + code: ':root {}', + }, + { + code: 'a:has(#id) {}', + }, + { + code: 'a:hover, a:nth-child(5) {}', + }, + { + code: 'a::before {}', + }, + { + code: 'a:nth-child(5)::before {}', + }, + { + code: 'a:-moz-placeholder {}', + }, + { + code: ':root { --foo: 1px; }', + description: 'custom property in root', + }, + { + code: 'html { --foo: 1px; }', + description: 'custom property in selector', + }, + { + code: ':root { --custom-property-set: {} }', + description: 'custom property set in root', + }, + { + code: 'html { --custom-property-set: {} }', + description: 'custom property set in selector', + }, + ], + + reject: [ + { + code: 'a:HOVER {}', + message: messages.rejected('HOVER'), + line: 1, + column: 2, + }, + { + code: 'a:-MOZ-PLACEholder {}', + message: messages.rejected('-MOZ-PLACEholder'), + line: 1, + column: 2, + }, + { + code: 'a:focus {}', + message: messages.rejected('focus'), + line: 1, + column: 2, + }, + { + code: 'div:nth-LAST-child {}', + message: messages.rejected('nth-LAST-child'), + line: 1, + column: 4, + }, + { + code: 'a,\n:global {}', + message: messages.rejected('global'), + line: 2, + column: 1, + }, + { + code: 'input:-ms-input-placeholder {}', + message: messages.rejected('-ms-input-placeholder'), + line: 1, + column: 6, + }, + { + code: 'input:-Ms-INPUT-placeholder {}', + message: messages.rejected('-Ms-INPUT-placeholder'), + line: 1, + column: 6, + }, + { + code: 'a:not(::selection) {}', + message: messages.rejected('not'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: [['/^nth/']], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:nth-child(5) {}', + }, + { + code: 'a:nth-LAST-child {}', + }, + ], + + reject: [ + { + code: 'a:hover {}', + message: messages.rejected('hover'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: [[/^nth/]], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + ], + + reject: [ + { + code: 'a:hover {}', + message: messages.rejected('hover'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: ['hover'], + skipBasicChecks: true, + syntax: 'scss', + + accept: [ + { + code: ':#{$variable} {}', + }, + { + code: ':#{$VARIABLE} {}', + }, + { + code: 'a:#{$variable} {}', + }, + ], +}); diff --git a/lib/rules/selector-pseudo-class-whitelist/index.js b/lib/rules/selector-pseudo-class-whitelist/index.js new file mode 100644 index 0000000000..8f9d8d8773 --- /dev/null +++ b/lib/rules/selector-pseudo-class-whitelist/index.js @@ -0,0 +1,82 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const parseSelector = require('../../utils/parseSelector'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-pseudo-class-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (selector) => `Unexpected pseudo-class "${selector}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-class-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + if (!selector.includes(':')) { + return; + } + + parseSelector(selector, result, rule, (selectorTree) => { + selectorTree.walkPseudos((pseudoNode) => { + const value = pseudoNode.value; + + // Ignore pseudo-elements + if (value.slice(0, 2) === '::') { + return; + } + + const name = value.slice(1); + + if (matchesStringOrRegExp(postcss.vendor.unprefixed(name), list)) { + return; + } + + report({ + index: pseudoNode.sourceIndex, + message: messages.rejected(name), + node: rule, + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-pseudo-element-allowed-list/README.md b/lib/rules/selector-pseudo-element-allowed-list/README.md index 2ed1068195..c920727f8a 100644 --- a/lib/rules/selector-pseudo-element-allowed-list/README.md +++ b/lib/rules/selector-pseudo-element-allowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of allowed pseudo-element selectors. * This pseudo-element selector */ ``` -This rule was previously called, and is aliased as, `selector-pseudo-element-whitelist`. - This rule ignores: - CSS2 pseudo-elements i.e. those prefixed with a single colon diff --git a/lib/rules/selector-pseudo-element-blacklist/README.md b/lib/rules/selector-pseudo-element-blacklist/README.md new file mode 100644 index 0000000000..bcb9cf2908 --- /dev/null +++ b/lib/rules/selector-pseudo-element-blacklist/README.md @@ -0,0 +1,56 @@ +# selector-pseudo-element-blacklist + +**_Deprecated: Instead use the [`selector-pseudo-element-disallowed-list`](../selector-pseudo-element-disallowed-list/README.md) rule._** + +Specify a list of disallowed pseudo-element selectors. + + +```css + a::before {} +/** ↑ + * This pseudo-element selector */ +``` + +This rule ignores: + +- CSS2 pseudo-elements i.e. those prefixed with a single colon +- selectors that use variable interpolation e.g. `::#{$variable} {}` + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", "pseudo-elements" or "regex"]|"pseudo-element"|/regex/` + +Given: + +``` +["before", "/^my-/i"] +``` + +The following patterns are considered violations: + + +```css +a::before {} +``` + + +```css +a::my-pseudo-element {} +``` + + +```css +a::MY-OTHER-pseudo-element {} +``` + +The following patterns are _not_ considered violations: + + +```css +a::after {} +``` + + +```css +a::not-my-pseudo-element {} +``` diff --git a/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js b/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js new file mode 100644 index 0000000000..77cf01b66b --- /dev/null +++ b/lib/rules/selector-pseudo-element-blacklist/__tests__/index.js @@ -0,0 +1,126 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['before'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['before', 'selection', /^my/i], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:hover {}', + }, + { + code: 'a::BEFORE {}', + }, + { + code: 'a::after {}', + }, + { + code: '::first-line {}', + }, + { + code: '::-webkit-first-line {}', + }, + { + code: 'a:not(::first-line) {}', + }, + { + code: 'a::their-pseudo-element {}', + }, + { + code: 'a::THEIR-other-pseudo-element {}', + }, + ], + + reject: [ + { + code: 'a::before {}', + message: messages.rejected('before'), + line: 1, + column: 2, + }, + { + code: 'a,\nb::before {}', + message: messages.rejected('before'), + line: 2, + column: 2, + }, + { + code: '::selection {}', + message: messages.rejected('selection'), + line: 1, + column: 1, + }, + { + code: '::-webkit-selection {}', + message: messages.rejected('-webkit-selection'), + line: 1, + column: 1, + }, + { + code: 'a:not(::selection) {}', + message: messages.rejected('selection'), + line: 1, + column: 7, + }, + { + code: 'a::my-pseudo-element {}', + message: messages.rejected('my-pseudo-element'), + line: 1, + column: 2, + }, + { + code: 'a::MY-OTHER-pseudo-element {}', + message: messages.rejected('MY-OTHER-pseudo-element'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: ['before'], + skipBasicChecks: true, + syntax: 'scss', + + accept: [ + { + code: '::#{$variable} {}', + }, + { + code: '::#{$VARIABLE} {}', + }, + { + code: 'a::#{$variable} {}', + }, + ], +}); diff --git a/lib/rules/selector-pseudo-element-blacklist/index.js b/lib/rules/selector-pseudo-element-blacklist/index.js new file mode 100644 index 0000000000..8333f37bbb --- /dev/null +++ b/lib/rules/selector-pseudo-element-blacklist/index.js @@ -0,0 +1,82 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const parseSelector = require('../../utils/parseSelector'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-pseudo-element-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (selector) => `Unexpected pseudo-element "${selector}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-disallowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + if (!selector.includes('::')) { + return; + } + + parseSelector(selector, result, rule, (selectorTree) => { + selectorTree.walkPseudos((pseudoNode) => { + const value = pseudoNode.value; + + // Ignore pseudo-classes + if (value[1] !== ':') { + return; + } + + const name = value.slice(2); + + if (!matchesStringOrRegExp(postcss.vendor.unprefixed(name), list)) { + return; + } + + report({ + index: pseudoNode.sourceIndex, + message: messages.rejected(name), + node: rule, + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/selector-pseudo-element-disallowed-list/README.md b/lib/rules/selector-pseudo-element-disallowed-list/README.md index 0db5b8df2c..36516836e7 100644 --- a/lib/rules/selector-pseudo-element-disallowed-list/README.md +++ b/lib/rules/selector-pseudo-element-disallowed-list/README.md @@ -9,8 +9,6 @@ Specify a list of disallowed pseudo-element selectors. * This pseudo-element selector */ ``` -This rule was previously called, and is aliased as, `selector-pseudo-element-blacklist`. - This rule ignores: - CSS2 pseudo-elements i.e. those prefixed with a single colon diff --git a/lib/rules/selector-pseudo-element-whitelist/README.md b/lib/rules/selector-pseudo-element-whitelist/README.md new file mode 100644 index 0000000000..2a24022cb0 --- /dev/null +++ b/lib/rules/selector-pseudo-element-whitelist/README.md @@ -0,0 +1,56 @@ +# selector-pseudo-element-whitelist + +**_Deprecated: Instead use the [`selector-pseudo-element-allowed-list`](../selector-pseudo-element-allowed-list/README.md) rule._** + +Specify a list of allowed pseudo-element selectors. + + +```css + a::before {} +/** ↑ + * This pseudo-element selector */ +``` + +This rule ignores: + +- CSS2 pseudo-elements i.e. those prefixed with a single colon +- selectors that use variable interpolation e.g. `::#{$variable} {}` + +## Options + +`array|string|regex`: `["array", "of", "unprefixed", "pseudo-elements" or "regex"]|"pseudo-element"|/regex/` + +Given: + +``` +["before", "/^my-/i"] +``` + +The following patterns are considered violations: + + +```css +a::after {} +``` + + +```css +a::not-my-pseudo-element {} +``` + +The following patterns are _not_ considered violations: + + +```css +a::before {} +``` + + +```css +a::my-pseudo-element {} +``` + + +```css +a::MY-OTHER-pseudo-element {} +``` diff --git a/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js b/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js new file mode 100644 index 0000000000..20823c8a20 --- /dev/null +++ b/lib/rules/selector-pseudo-element-whitelist/__tests__/index.js @@ -0,0 +1,148 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['before'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + config: ['before', 'selection', /^my/i], + skipBasicChecks: true, + + accept: [ + { + code: 'a {}', + }, + { + code: 'a:hover {}', + }, + { + code: 'a::before {}', + }, + { + code: '::selection {}', + }, + { + code: '::-webkit-selection {}', + }, + { + code: 'a:not(::selection) {}', + }, + { + code: 'a::my-pseudo-element {}', + }, + { + code: 'a::MY-other-pseudo-element {}', + }, + ], + + reject: [ + { + code: 'a::BEFORE {}', + message: messages.rejected('BEFORE'), + line: 1, + column: 2, + }, + { + code: 'a::after {}', + message: messages.rejected('after'), + line: 1, + column: 2, + }, + { + code: 'a::AFTER {}', + message: messages.rejected('AFTER'), + line: 1, + column: 2, + }, + { + code: 'a,\nb::after {}', + message: messages.rejected('after'), + line: 2, + column: 2, + }, + { + code: 'a::not-my-pseudo-element {}', + message: messages.rejected('not-my-pseudo-element'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: /^before/, + skipBasicChecks: true, + + accept: [ + { + code: '::before {}', + }, + { + code: '::before-custom {}', + }, + ], + reject: [ + { + code: 'a::after {}', + message: messages.rejected('after'), + line: 1, + column: 2, + }, + { + code: 'a::not-before {}', + message: messages.rejected('not-before'), + line: 1, + column: 2, + }, + ], +}); + +testRule({ + ruleName, + config: ['before'], + skipBasicChecks: true, + syntax: 'scss', + + accept: [ + { + code: '::#{$variable} {}', + }, + { + code: '::#{$VARIABLE} {}', + }, + { + code: 'a::#{$variable} {}', + }, + ], + reject: [ + { + code: 'a::after {}', + message: messages.rejected('after'), + line: 1, + column: 2, + }, + ], +}); diff --git a/lib/rules/selector-pseudo-element-whitelist/index.js b/lib/rules/selector-pseudo-element-whitelist/index.js new file mode 100644 index 0000000000..949785a55b --- /dev/null +++ b/lib/rules/selector-pseudo-element-whitelist/index.js @@ -0,0 +1,82 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule'); +const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp'); +const parseSelector = require('../../utils/parseSelector'); +const postcss = require('postcss'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateOptions = require('../../utils/validateOptions'); + +const ruleName = 'selector-pseudo-element-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (selector) => `Unexpected pseudo-element "${selector}"`, +}); + +function rule(list) { + return (root, result) => { + const validOptions = validateOptions(result, ruleName, { + actual: list, + possible: [_.isString, _.isRegExp], + }); + + if (!validOptions) { + return; + } + + result.warn( + `'${ruleName}' has been deprecated. Instead use 'selector-pseudo-element-allowed-list'.`, + { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }, + ); + + root.walkRules((rule) => { + if (!isStandardSyntaxRule(rule)) { + return; + } + + const selector = rule.selector; + + if (!selector.includes('::')) { + return; + } + + parseSelector(selector, result, rule, (selectorTree) => { + selectorTree.walkPseudos((pseudoNode) => { + const value = pseudoNode.value; + + // Ignore pseudo-classes + if (value[1] !== ':') { + return; + } + + const name = value.slice(2); + + if (matchesStringOrRegExp(postcss.vendor.unprefixed(name), list)) { + return; + } + + report({ + index: pseudoNode.sourceIndex, + message: messages.rejected(name), + node: rule, + result, + ruleName, + }); + }); + }); + }); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/unit-allowed-list/README.md b/lib/rules/unit-allowed-list/README.md index 2c34eda820..3f5e2de93c 100644 --- a/lib/rules/unit-allowed-list/README.md +++ b/lib/rules/unit-allowed-list/README.md @@ -9,8 +9,6 @@ a { width: 100px; } * These units */ ``` -This rule was previously called, and is aliased as, `unit-whitelist`. - ## Options `array|string`: `["array", "of", "units"]|"unit"` diff --git a/lib/rules/unit-blacklist/README.md b/lib/rules/unit-blacklist/README.md new file mode 100644 index 0000000000..bcfa8710b3 --- /dev/null +++ b/lib/rules/unit-blacklist/README.md @@ -0,0 +1,161 @@ +# unit-blacklist + +**_Deprecated: Instead use the [`unit-disallowed-list`](../unit-disallowed-list/README.md) rule._** + +Specify a list of disallowed units. + + +```css +a { width: 100px; } +/** ↑ + * These units */ +``` + +## Options + +`array|string`: `["array", "of", "units"]|"unit"` + +Given: + +``` +["px", "em", "deg"] +``` + +The following patterns are considered violations: + + +```css +a { width: 100px; } +``` + + +```css +a { font-size: 10em; } +``` + + +```css +a { transform: rotate(30deg); } +``` + +The following patterns are _not_ considered violations: + + +```css +a { font-size: 1.2rem; } +``` + + +```css +a { line-height: 1.2; } +``` + + +```css +a { height: 100vmin; } +``` + + +```css +a { animation: animation-name 5s ease; } +``` + +## Optional secondary options + +### `ignoreProperties: { unit: ["property", "/regex/", /regex/] }` + +Ignore units in the values of declarations with the specified properties. + +For example, with `["px", "vmin"]`. + +Given: + +``` +{ + "px": [ "font-size", "/^border/" ], + "vmin": [ "width" ] +} +``` + +The following patterns are _not_ considered violations: + + +```css +a { font-size: 13px; } +``` + + +```css +a { border-bottom-width: 6px; } +``` + + +```css +a { width: 100vmin; } +``` + +The following patterns are considered violations: + + +```css +a { line-height: 12px; } +``` + + +```css +a { -moz-border-radius-topright: 40px; } +``` + + +```css +a { height: 100vmin; } +``` + +### `ignoreMediaFeatureNames: { unit: ["property", "/regex/", /regex/] }` + +Ignore units for specific feature names. + +For example, with `["px", "dpi"]`. + +Given: + +``` +{ + "px": [ "min-width", "/height$/" ], + "dpi": [ "resolution" ] +} +``` + +The following patterns are _not_ considered violations: + + +```css +@media (min-width: 960px) {} +``` + + +```css +@media (max-height: 280px) {} +``` + + +```css +@media not (resolution: 300dpi) {} +``` + +The following patterns are considered violations: + + +```css +@media screen and (max-device-width: 500px) {} +``` + + +```css +@media all and (min-width: 500px) and (max-width: 200px) {} +``` + + +```css +@media print and (max-resolution: 100dpi) {} +``` diff --git a/lib/rules/unit-blacklist/__tests__/index.js b/lib/rules/unit-blacklist/__tests__/index.js new file mode 100644 index 0000000000..728701be94 --- /dev/null +++ b/lib/rules/unit-blacklist/__tests__/index.js @@ -0,0 +1,563 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['px'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'unit-disallowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['px', 'vmin'], + + accept: [ + { + code: 'a { line-height: 1; }', + }, + { + code: 'a { color: #000; }', + }, + { + code: 'a { top: 0; left: 0; }', + }, + { + code: 'a { font-size: 100%; }', + }, + { + code: 'a { line-height: 1.2rem; }', + }, + { + code: 'a { line-height: 1.2rEm; }', + }, + { + code: 'a { line-height: 1.2REM; }', + }, + { + code: 'a { font-size: .5rem; }', + }, + { + code: 'a { font-size: 0.5rem; }', + }, + { + code: 'a { margin: 0 10em 5rem 2in; }', + }, + { + code: 'a { background-position: top right, 1em 5vh; }', + }, + { + code: 'a { top: calc(10em - 3em); }', + }, + { + code: 'a { top: calc(10em*2rem); }', + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100% - 50em), silver); }', + }, + { + code: 'a { width: /* 100px */ 1em; }', + description: 'ignore unit within comments', + }, + { + code: 'a::before { content: "10px"}', + description: 'ignore unit within quotes', + }, + { + code: 'a { font-size: $fs10px; }', + description: 'ignore preprocessor variable includes unit', + }, + { + code: 'a { font-size: --some-fs-10px; }', + description: 'ignore css variable includes unit', + }, + { + code: 'a { background-url: url(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { background-url: uRl(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { background-url: URL(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { margin10px: 10em; }', + description: 'ignore property include wrong unit', + }, + { + code: 'a10px { margin: 10em; }', + description: 'ignore type selector include wrong unit', + }, + { + code: '#a10px { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: '.a10px { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: 'input[type=10px] { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: 'a:hover10px { margin: 10em; }', + description: 'ignore pseudo-class include wrong unit', + }, + { + code: 'a::before10px { margin: 10em; }', + description: 'ignore pseudo-class include wrong unit', + }, + { + code: 'a { margin: calc(100% - #{margin * 2}); }', + description: 'work with interpolation', + }, + { + code: '@media (min-width: 10em) {}', + description: '@media', + }, + { + code: '@media (min-width: 10em)\n and (max-width: 20em) {}', + description: 'complex @media', + }, + ], + + reject: [ + { + code: 'a { font-size: 13px; }', + message: messages.rejected('px'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 13pX; }', + message: messages.rejected('pX'), + line: 1, + column: 16, + }, + { + code: 'a { font-size: 13PX; }', + message: messages.rejected('PX'), + line: 1, + column: 16, + }, + { + code: 'a { width: 100vmin; }', + message: messages.rejected('vmin'), + line: 1, + column: 12, + }, + { + code: 'a { line-height: .1px; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + { + code: 'a { line-height: 0.1px; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + { + code: 'a { border-left: 1px solid #ccc; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + { + code: 'a { margin: 0 20px; }', + message: messages.rejected('px'), + line: 1, + column: 15, + }, + { + code: 'a { margin: 0 0 0 20px; }', + message: messages.rejected('px'), + line: 1, + column: 19, + }, + { + code: 'a { background-position: top right, 1em 5px; }', + message: messages.rejected('px'), + line: 1, + column: 41, + }, + { + code: 'a { top: calc(100px - 30vh); }', + message: messages.rejected('px'), + line: 1, + column: 15, + }, + { + code: 'a { top: calc(100px*2); }', + message: messages.rejected('px'), + line: 1, + column: 15, + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100vh - 5vmin), silver); }', + message: messages.rejected('vmin'), + line: 1, + column: 68, + }, + { + code: 'a { margin: calc(100% - #{$margin * 2px}); }', + message: messages.rejected('px'), + line: 1, + column: 37, + }, + { + code: '@media (min-width: 13px) {}', + message: messages.rejected('px'), + description: '@media', + line: 1, + column: 20, + }, + { + code: '@media (min-width: 10em)\n and (max-width: 20px) {}', + message: messages.rejected('px'), + description: 'complex @media', + line: 2, + column: 19, + }, + { + code: '@media (width < 10.01px) {}', + message: messages.rejected('px'), + description: 'media feature range', + line: 1, + column: 17, + }, + ], +}); + +testRule({ + ruleName, + + config: ['px'], + + accept: [ + { + code: 'a { line-height: 1em; }', + }, + ], + + reject: [ + { + code: 'a { line-height: 1px; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'vmin'], + { + ignoreProperties: { + px: ['font-size', 'margin', '/^border/'], + vmin: ['width', 'height'], + }, + }, + ], + + accept: [ + { + code: 'a { font-size: 13px; }', + }, + { + code: 'a { font-size: 13pX; }', + }, + { + code: 'a { margin: 0 20px; }', + }, + { + code: 'a { margin: 0 0 0 20Px; }', + }, + { + code: 'a { width: 100vmin; }', + }, + { + code: 'a { height: 99vmIn; }', + }, + { + code: 'a { border: 1px solid purple; }', + }, + { + code: 'a { border-bottom-width: 6px; }', + }, + ], + + reject: [ + { + code: 'a { line-height: .1px; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100vh - 5vmin), silver); }', + message: messages.rejected('vmin'), + line: 1, + column: 68, + }, + { + code: 'a { -moz-border-radius-topright: 40px; }', + message: messages.rejected('px'), + line: 1, + column: 34, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'vmin'], + { + ignoreProperties: { + px: ['font-size', 'margin', /^border/], + vmin: ['width', 'height'], + }, + }, + ], + + accept: [ + { + code: 'a { border: 1px solid purple; }', + }, + { + code: 'a { border-bottom-width: 6px; }', + }, + ], + + reject: [ + { + code: 'a { line-height: .1px; }', + message: messages.rejected('px'), + line: 1, + column: 18, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'dpi', '%'], + { + ignoreMediaFeatureNames: { + px: ['min-width', 'height'], + dpi: ['min-resolution', 'resolution'], + '%': ['width', '/^min/'], + }, + }, + ], + + accept: [ + { + code: '@media (min-width: 960px) { body { font-size: 13em } }', + }, + { + code: '@media (width: 960%) { /* body { font-size: 13em } */ }', + }, + { + code: '@media (min-width: 960%) { /* body { font-size: 13em } */ }', + }, + { + code: 'a { @media (min-width: 960px) { body { font-size: 13em } } }', + }, + { + code: '@media print and (min-resolution: 300dpi) { body { font-size: 13em } }', + }, + { + code: '@media print { body { font-size: 40pt } }', + }, + { + code: '@media screen, print { body { line-height: 1.2 } }', + }, + { + code: '@MEDIA (min-width: 960px) { body { font-size: 13em } }', + }, + { + code: '@media (MIN-WIDTH: 960px) { body { font-size: 13em } }', + }, + { + code: '@media (height > -100px) { body { background: green; } }', + }, + { + code: '@media not (resolution: -300dpi) { body { background: green; } }', + }, + { + code: '@media only screen and (min-width: 500px) { }', + }, + { + code: '@media only speech and (width > 20%) { }', + }, + { + code: '@media speech and (device-aspect-ratio: 16/9) { }', + }, + { + code: + '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2) { body { line-height: 1.4 } }', + }, + { + code: '@media screen, print { }', + }, + { + code: '@media speech and (aspect-ratio: 11/5) { }', + }, + { + code: '@media (min-width: 700px), handheld and (orientation: landscape) { }', + }, + ], + + reject: [ + { + code: '@media screen and (max-width: 500px) { }', + message: messages.rejected('px'), + line: 1, + column: 31, + }, + { + code: '@media (width: 960px) { /* body { font-size: 13em } */ }', + message: messages.rejected('px'), + line: 1, + column: 16, + }, + { + code: '@media (min-height: 960px) { /* body { font-size: 13em } */ }', + message: messages.rejected('px'), + line: 1, + column: 21, + }, + { + code: 'a { @media screen and (max-width: 500px) { } }', + message: messages.rejected('px'), + line: 1, + column: 35, + }, + { + code: '@media all and (min-width: 500px) and (max-width: 200px) { }', + message: messages.rejected('px'), + line: 1, + column: 51, + }, + { + code: '@MEDIA print { body { font-size: 60dpi } }', + message: messages.rejected('dpi'), + line: 1, + column: 34, + }, + { + code: '@media (MAX-WIDTH: 10px) { }', + message: messages.rejected('px'), + line: 1, + column: 20, + }, + { + code: '@media (min-width: 10em)\n and (max-width: 20px) { }', + message: messages.rejected('px'), + line: 2, + column: 19, + }, + { + code: '@media (width < 10.01px) {}', + message: messages.rejected('px'), + line: 1, + column: 17, + }, + { + code: '@media only speech and (max-device-width > 20%) { }', + message: messages.rejected('%'), + line: 1, + column: 44, + }, + { + code: '@media not (max-resolution: -300dpi) { body { background: green; } }', + message: messages.rejected('dpi'), + line: 1, + column: 29, + }, + { + code: + '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2) { body { line-height: 1.4px } }', + message: messages.rejected('px'), + line: 1, + column: 125, + }, + { + code: + '@media only screen and (min-width: 320px) and (height: 480px) and (-webkit-min-device-pixel-ratio: 2px) { body { line-height: 1.4 } }', + message: messages.rejected('px'), + line: 1, + column: 100, + }, + { + code: '@media screen and (min-width: 699px) and (min-width: 520px), (max-width: 1151px)', + message: messages.rejected('px'), + line: 1, + column: 74, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'dpi', '%'], + { + ignoreMediaFeatureNames: { + px: ['min-width', 'height'], + dpi: ['min-resolution', 'resolution'], + '%': ['width', /^min/], + }, + }, + ], + + accept: [ + { + code: '@media (width: 960%) { /* body { font-size: 13em } */ }', + }, + { + code: '@media (min-width: 960%) { /* body { font-size: 13em } */ }', + }, + ], + + reject: [ + { + code: '@media screen and (max-width: 500px) { }', + message: messages.rejected('px'), + line: 1, + column: 31, + }, + ], +}); diff --git a/lib/rules/unit-blacklist/index.js b/lib/rules/unit-blacklist/index.js new file mode 100644 index 0000000000..b27a5ae3e7 --- /dev/null +++ b/lib/rules/unit-blacklist/index.js @@ -0,0 +1,130 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); +const mediaParser = require('postcss-media-query-parser').default; +const optionsMatches = require('../../utils/optionsMatches'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateObjectWithArrayProps = require('../../utils/validateObjectWithArrayProps'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'unit-blacklist'; + +const messages = ruleMessages(ruleName, { + rejected: (unit) => `Unexpected unit "${unit}"`, +}); + +// a function to retrieve only the media feature name +// could be externalized in an utils function if needed in other code +const getMediaFeatureName = (mediaFeatureNode) => { + const value = mediaFeatureNode.value.toLowerCase(); + + return /((-?\w*)*)/i.exec(value)[1]; +}; + +function rule(listInput, options) { + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions( + result, + ruleName, + { + actual: list, + possible: [_.isString], + }, + { + optional: true, + actual: options, + possible: { + ignoreProperties: validateObjectWithArrayProps([_.isString, _.isRegExp]), + ignoreMediaFeatureNames: validateObjectWithArrayProps([_.isString, _.isRegExp]), + }, + }, + ); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'unit-disallowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + function check(node, nodeIndex, valueNode, input, option) { + const unit = getUnitFromValueNode(valueNode); + + // There is not unit or it is not configured as a violation + if (!unit || (unit && !list.includes(unit.toLowerCase()))) { + return; + } + + // The unit has an ignore option for the specific input + if (optionsMatches(option, unit.toLowerCase(), input)) { + return; + } + + report({ + index: nodeIndex + valueNode.sourceIndex, + message: messages.rejected(unit), + node, + result, + ruleName, + }); + } + + function checkMedia(node, value, getIndex) { + mediaParser(node.params).walk(/^media-feature$/i, (mediaFeatureNode) => { + const mediaName = getMediaFeatureName(mediaFeatureNode); + const parentValue = mediaFeatureNode.parent.value; + + valueParser(value).walk((valueNode) => { + // Ignore all non-word valueNode and + // the values not included in the parentValue string + if (valueNode.type !== 'word' || !parentValue.includes(valueNode.value)) { + return; + } + + check( + node, + getIndex(node), + valueNode, + mediaName, + options ? options.ignoreMediaFeatureNames : {}, + ); + }); + }); + } + + function checkDecl(node, value, getIndex) { + // make sure multiplication operations (*) are divided - not handled + // by postcss-value-parser + value = value.replace(/\*/g, ','); + + valueParser(value).walk((valueNode) => { + // Ignore wrong units within `url` function + if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { + return false; + } + + check(node, getIndex(node), valueNode, node.prop, options ? options.ignoreProperties : {}); + }); + } + + root.walkAtRules(/^media$/i, (atRule) => checkMedia(atRule, atRule.params, atRuleParamIndex)); + root.walkDecls((decl) => checkDecl(decl, decl.value, declarationValueIndex)); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/rules/unit-disallowed-list/README.md b/lib/rules/unit-disallowed-list/README.md index 2f20017030..e38d426968 100644 --- a/lib/rules/unit-disallowed-list/README.md +++ b/lib/rules/unit-disallowed-list/README.md @@ -9,8 +9,6 @@ a { width: 100px; } * These units */ ``` -This rule was previously called, and is aliased as, `unit-blacklist`. - ## Options `array|string`: `["array", "of", "units"]|"unit"` diff --git a/lib/rules/unit-whitelist/README.md b/lib/rules/unit-whitelist/README.md new file mode 100644 index 0000000000..c32c1333d7 --- /dev/null +++ b/lib/rules/unit-whitelist/README.md @@ -0,0 +1,117 @@ +# unit-whitelist + +**_Deprecated: Instead use the [`unit-allowed-list`](../unit-allowed-list/README.md) rule._** + +Specify a list of allowed units. + + +```css +a { width: 100px; } +/** ↑ + * These units */ +``` + +## Options + +`array|string`: `["array", "of", "units"]|"unit"` + +Given: + +``` +["px", "em", "deg"] +``` + +The following patterns are considered violations: + + +```css +a { width: 100%; } +``` + + +```css +a { font-size: 10rem; } +``` + + +```css +a { animation: animation-name 5s ease; } +``` + +The following patterns are _not_ considered violations: + + +```css +a { font-size: 1.2em; } +``` + + +```css +a { line-height: 1.2; } +``` + + +```css +a { height: 100px; } +``` + + +```css +a { height: 100PX; } +``` + + +```css +a { transform: rotate(30deg); } +``` + +## Optional secondary options + +### `ignoreProperties: { unit: ["property", "/regex/", /regex/] }` + +Ignore units in the values of declarations with the specified properties. + +For example, with `["px", "em"]`. + +Given: + +``` +{ + "rem": [ "line-height", "/^border/" ], + "%": [ "width" ] +} +``` + +The following patterns are _not_ considered violations: + + +```css +a { line-height: 0.1rem; } +``` + + +```css +a { border-bottom-width: 6rem; } +``` + + +```css +a { width: 100%; } +``` + +The following patterns are considered violations: + + +```css +a { margin: 0 20rem; } +``` + + +```css +a { -moz-border-radius-topright: 20rem; } +``` + + +```css +a { height: 100%; } +``` diff --git a/lib/rules/unit-whitelist/__tests__/index.js b/lib/rules/unit-whitelist/__tests__/index.js new file mode 100644 index 0000000000..07ef614ca0 --- /dev/null +++ b/lib/rules/unit-whitelist/__tests__/index.js @@ -0,0 +1,365 @@ +'use strict'; + +const standalone = require('../../../standalone'); +const { messages, ruleName } = require('..'); + +it('warns that the rule is deprecated', () => { + const config = { + rules: { + [ruleName]: ['px'], + }, + }; + + const code = ''; + + return standalone({ code, config }).then((output) => { + const result = output.results[0]; + + expect(result.deprecations).toHaveLength(1); + expect(result.deprecations[0].text).toEqual( + `'${ruleName}' has been deprecated. Instead use 'unit-allowed-list'.`, + ); + expect(result.deprecations[0].reference).toEqual( + `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + ); + }); +}); + +testRule({ + ruleName, + + config: ['px', 'em'], + + accept: [ + { + code: 'a { line-height: 1; }', + }, + { + code: 'a { color: #000; }', + }, + { + code: 'a { font-size: 14px; }', + }, + { + code: 'a { font-size: 14pX; }', + }, + { + code: 'a { font-size: 14PX; }', + }, + { + code: 'a { font-size: 1.2em; }', + }, + { + code: 'a { font-size: .5em; }', + }, + { + code: 'a { font-size: 0.5em; }', + }, + { + code: 'a { margin: 0 10em 5em 2px; }', + }, + { + code: 'a { background-position: top right, 10px 20px; }', + }, + { + code: 'a { top: calc(10em - 3em); }', + }, + { + code: 'a { top: calc(10em*3); }', + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100px - 50em), silver); }', + }, + { + code: 'a { width: /* 100pc */ 1em; }', + description: 'ignore unit within comments', + }, + { + code: 'a::before { content: "10%"}', + description: 'ignore unit within quotes', + }, + { + code: 'a { font-size: $fs10%; }', + description: 'ignore preprocessor variable includes unit', + }, + { + code: 'a { font-size: --some-fs-10rem; }', + description: 'ignore css variable includes unit', + }, + { + code: 'a { background-url: url(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { background-url: uRl(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { background-url: URL(10vmin); }', + description: 'ignore url function', + }, + { + code: 'a { margin10rem: 10em; }', + description: 'ignore property include wrong unit', + }, + { + code: 'a10rem { margin: 10em; }', + description: 'ignore type selector include wrong unit', + }, + { + code: '#a10rem { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: '.a10rem { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: 'input[type=10rem] { margin: 10em; }', + description: 'ignore class selector include wrong unit', + }, + { + code: 'a:hover10rem { margin: 10em; }', + description: 'ignore pseudo-class include wrong unit', + }, + { + code: 'a::before10rem { margin: 10em; }', + description: 'ignore pseudo-class include wrong unit', + }, + { + code: 'a { margin: calc(100px - #{margin * 2}); }', + description: 'work with interpolation', + }, + { + code: '@media (min-width: 10em) {}', + description: '@media', + }, + { + code: '@media (min-width: 10px)\n and (max-width: 20em) {}', + description: 'complex @media', + }, + ], + + reject: [ + { + code: 'a { font-size: 80%; }', + message: messages.rejected('%'), + line: 1, + column: 16, + }, + { + code: 'a { width: 100vmin; }', + message: messages.rejected('vmin'), + line: 1, + column: 12, + }, + { + code: 'a { width: 100vMiN; }', + message: messages.rejected('vMiN'), + line: 1, + column: 12, + }, + { + code: 'a { width: 100VMIN; }', + message: messages.rejected('VMIN'), + line: 1, + column: 12, + }, + { + code: 'a { line-height: .1rem; }', + message: messages.rejected('rem'), + line: 1, + column: 18, + }, + { + code: 'a { line-height: 0.1rem; }', + message: messages.rejected('rem'), + line: 1, + column: 18, + }, + { + code: 'a { border-left: 1rem solid #ccc; }', + message: messages.rejected('rem'), + line: 1, + column: 18, + }, + { + code: 'a { margin: 0 20%; }', + message: messages.rejected('%'), + line: 1, + column: 15, + }, + { + code: 'a { margin: 0 0 0 20rem; }', + message: messages.rejected('rem'), + line: 1, + column: 19, + }, + { + code: 'a { background-position: top right, 1em 5rem; }', + message: messages.rejected('rem'), + line: 1, + column: 41, + }, + { + code: 'a { top: calc(2vh*3); }', + message: messages.rejected('vh'), + line: 1, + column: 15, + }, + { + code: 'a { top: calc(100px - 30vh); }', + message: messages.rejected('vh'), + line: 1, + column: 23, + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100px - 5vmin), silver); }', + message: messages.rejected('vmin'), + line: 1, + column: 68, + }, + { + code: 'a { margin: calc(100px - #{$margin * 2rem}); }', + message: messages.rejected('rem'), + line: 1, + column: 38, + }, + { + code: '@media (min-width: 13rem) {}', + message: messages.rejected('rem'), + description: '@media', + line: 1, + column: 20, + }, + { + code: '@media (min-width: 10em)\n and (max-width: 20rem) {}', + message: messages.rejected('rem'), + description: 'complex @media', + line: 2, + column: 19, + }, + { + code: '@media (width < 10.01REM) {}', + message: messages.rejected('REM'), + description: 'media feature range', + line: 1, + column: 17, + }, + ], +}); + +testRule({ + ruleName, + + config: ['px'], + + accept: [ + { + code: 'a { line-height: 1px; }', + }, + ], + + reject: [ + { + code: 'a { line-height: 1em; }', + message: messages.rejected('em'), + line: 1, + column: 18, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'em'], + { + ignoreProperties: { + rem: ['line-height', 'margin', '/^border/'], + '%': ['width', 'height'], + }, + }, + ], + + accept: [ + { + code: 'a { line-height: 0.1rem; }', + }, + { + code: 'a { line-height: 0.1rEm; }', + }, + { + code: 'a { margin: 0 20rem; }', + }, + { + code: 'a { margin: 0 0 0 20reM; }', + }, + { + code: 'a { width: 100%; }', + }, + { + code: 'a { height: 50%; }', + }, + { + code: 'a { border: 1rem solid purple; }', + }, + { + code: 'a { border-bottom-width: 6rem; }', + }, + ], + + reject: [ + { + code: 'a { font-size: 80%; }', + message: messages.rejected('%'), + line: 1, + column: 16, + }, + { + code: 'a { background-image: linear-gradient(to right, white calc(100px - 5rem), silver); }', + message: messages.rejected('rem'), + line: 1, + column: 68, + }, + { + code: 'a { -moz-border-radius-topright: 40rem; }', + message: messages.rejected('rem'), + line: 1, + column: 34, + }, + ], +}); + +testRule({ + ruleName, + + config: [ + ['px', 'em'], + { + ignoreProperties: { + rem: ['line-height', 'margin', /^border/], + '%': ['width', 'height'], + }, + }, + ], + + accept: [ + { + code: 'a { border: 1rem solid purple; }', + }, + { + code: 'a { border-bottom-width: 6rem; }', + }, + ], + + reject: [ + { + code: 'a { font-size: 80%; }', + message: messages.rejected('%'), + line: 1, + column: 16, + }, + ], +}); diff --git a/lib/rules/unit-whitelist/index.js b/lib/rules/unit-whitelist/index.js new file mode 100644 index 0000000000..b9f6b18b9f --- /dev/null +++ b/lib/rules/unit-whitelist/index.js @@ -0,0 +1,90 @@ +// @ts-nocheck + +'use strict'; + +const _ = require('lodash'); +const atRuleParamIndex = require('../../utils/atRuleParamIndex'); +const declarationValueIndex = require('../../utils/declarationValueIndex'); +const getUnitFromValueNode = require('../../utils/getUnitFromValueNode'); +const optionsMatches = require('../../utils/optionsMatches'); +const report = require('../../utils/report'); +const ruleMessages = require('../../utils/ruleMessages'); +const validateObjectWithArrayProps = require('../../utils/validateObjectWithArrayProps'); +const validateOptions = require('../../utils/validateOptions'); +const valueParser = require('postcss-value-parser'); + +const ruleName = 'unit-whitelist'; + +const messages = ruleMessages(ruleName, { + rejected: (unit) => `Unexpected unit "${unit}"`, +}); + +function rule(listInput, options) { + const list = [].concat(listInput); + + return (root, result) => { + const validOptions = validateOptions( + result, + ruleName, + { + actual: list, + possible: [_.isString], + }, + { + optional: true, + actual: options, + possible: { + ignoreProperties: validateObjectWithArrayProps([_.isString, _.isRegExp]), + }, + }, + ); + + if (!validOptions) { + return; + } + + result.warn(`'${ruleName}' has been deprecated. Instead use 'unit-allowed-list'.`, { + stylelintType: 'deprecation', + stylelintReference: `https://github.com/stylelint/stylelint/blob/13.7.0/lib/rules/${ruleName}/README.md`, + }); + + function check(node, value, getIndex) { + // make sure multiplication operations (*) are divided - not handled + // by postcss-value-parser + value = value.replace(/\*/g, ','); + valueParser(value).walk((valueNode) => { + // Ignore wrong units within `url` function + if (valueNode.type === 'function' && valueNode.value.toLowerCase() === 'url') { + return false; + } + + const unit = getUnitFromValueNode(valueNode); + + if (!unit || (unit && list.includes(unit.toLowerCase()))) { + return; + } + + if (options && optionsMatches(options.ignoreProperties, unit.toLowerCase(), node.prop)) { + return; + } + + report({ + index: getIndex(node) + valueNode.sourceIndex, + message: messages.rejected(unit), + node, + result, + ruleName, + }); + }); + } + + root.walkAtRules(/^media$/i, (atRule) => check(atRule, atRule.params, atRuleParamIndex)); + root.walkDecls((decl) => check(decl, decl.value, declarationValueIndex)); + }; +} + +rule.primaryOptionArray = true; + +rule.ruleName = ruleName; +rule.messages = messages; +module.exports = rule; diff --git a/lib/utils/__tests__/checkAgainstRule.test.js b/lib/utils/__tests__/checkAgainstRule.test.js index df353eb45f..13a2ee22a6 100644 --- a/lib/utils/__tests__/checkAgainstRule.test.js +++ b/lib/utils/__tests__/checkAgainstRule.test.js @@ -60,24 +60,4 @@ describe('checkAgainstRule', () => { expect(warnings[0].line).toBe(3); expect(warnings[0].column).toBe(1); }); - - it('warns against a renamed rule when an aliased rule is used', () => { - const root = postcss.parse('a { top: 10px; }'); - - const warnings = []; - - checkAgainstRule( - { - ruleName: 'unit-whitelist', - ruleSettings: ['em'], - root, - }, - (warning) => warnings.push(warning), - ); - - expect(warnings).toHaveLength(1); - expect(warnings[0].rule).toBe('unit-allowed-list'); - expect(warnings[0].line).toBe(1); - expect(warnings[0].column).toBe(10); - }); }); From 9401f568a82df407eb2f356b6f0d28447985d3f7 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Mon, 31 Aug 2020 12:11:34 +0100 Subject: [PATCH 27/34] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cca0776ed7..6055cf26cb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project are documented in this file. - Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). - Fixed: inconsistent trailing newlines in CLI error output ([#4876](https://github.com/stylelint/stylelint/pull/4876)). - Fixed: support for multi-line disable descriptions ([#4895](https://github.com/stylelint/stylelint/pull/4895)). +- Fixed: support for paths with parentheses ([#4867](https://github.com/stylelint/stylelint/pull/4867)). - Fixed: `selector-max-*` (except `selector-max-type`) false negatives for `where`, `is`, `nth-child` and `nth-last-child` ([#4842](https://github.com/stylelint/stylelint/pull/4842)). - Fixed: `length-zero-no-unit` TypeError for custom properties fallback ([#4860](https://github.com/stylelint/stylelint/pull/4860)). - Fixed: `selector-combinator-space-after` false positives for trailing combinator ([#4878](https://github.com/stylelint/stylelint/pull/4878)). From d725b88ecc6a5c5fb3c032a970655a7de2f4a0d3 Mon Sep 17 00:00:00 2001 From: jeddy3 Date: Mon, 31 Aug 2020 12:45:06 +0100 Subject: [PATCH 28/34] Update dependencies --- .github/workflows/code-scanning.yml | 1 + lib/rules/custom-media-pattern/README.md | 4 +- lib/rules/custom-property-pattern/README.md | 4 +- lib/rules/keyframes-name-pattern/README.md | 4 +- lib/rules/selector-class-pattern/README.md | 5 +- lib/rules/selector-id-pattern/README.md | 4 +- lib/rules/selector-nested-pattern/README.md | 4 +- package-lock.json | 4323 ++++++------------- package.json | 28 +- 9 files changed, 1231 insertions(+), 3146 deletions(-) diff --git a/.github/workflows/code-scanning.yml b/.github/workflows/code-scanning.yml index ff827220a1..3f811bc964 100644 --- a/.github/workflows/code-scanning.yml +++ b/.github/workflows/code-scanning.yml @@ -27,6 +27,7 @@ jobs: - name: Initialize CodeQL uses: github/codeql-action/init@v1 + # Override language selection by uncommenting this and choosing your languages # with: # languages: go, javascript, csharp, python, cpp, java diff --git a/lib/rules/custom-media-pattern/README.md b/lib/rules/custom-media-pattern/README.md index d95abf8bbd..d9dc628f56 100644 --- a/lib/rules/custom-media-pattern/README.md +++ b/lib/rules/custom-media-pattern/README.md @@ -17,8 +17,8 @@ A string will be translated into a RegExp like so `new RegExp(yourString)` —  Given the string: -```js -"foo-.+"; +``` +"foo-.+" ``` The following patterns are considered violations: diff --git a/lib/rules/custom-property-pattern/README.md b/lib/rules/custom-property-pattern/README.md index 9b4eeabe17..1382b9fc0b 100644 --- a/lib/rules/custom-property-pattern/README.md +++ b/lib/rules/custom-property-pattern/README.md @@ -17,8 +17,8 @@ A string will be translated into a RegExp like so `new RegExp(yourString)` —  Given the string: -```js -"foo-.+"; +``` +"foo-.+" ``` The following patterns are considered violations: diff --git a/lib/rules/keyframes-name-pattern/README.md b/lib/rules/keyframes-name-pattern/README.md index 703fa684b3..cda65c13c1 100644 --- a/lib/rules/keyframes-name-pattern/README.md +++ b/lib/rules/keyframes-name-pattern/README.md @@ -17,8 +17,8 @@ A string will be translated into a RegExp like so `new RegExp(yourString)` —  Given the string: -```js -"foo-.+"; +``` +"foo-.+" ``` The following patterns are considered violations: diff --git a/lib/rules/selector-class-pattern/README.md b/lib/rules/selector-class-pattern/README.md index b6961ad1e6..e7da1ed34e 100644 --- a/lib/rules/selector-class-pattern/README.md +++ b/lib/rules/selector-class-pattern/README.md @@ -25,6 +25,7 @@ Given the string: ```js "foo-[a-z]+"; + ``` The following patterns are considered violations: @@ -76,8 +77,8 @@ For example, with `true`. Given the string: -```js -"^[A-Z]+$"; +``` +"^[A-Z]+$" ``` The following patterns are considered violations: diff --git a/lib/rules/selector-id-pattern/README.md b/lib/rules/selector-id-pattern/README.md index 489b89ae2d..cab22b7d18 100644 --- a/lib/rules/selector-id-pattern/README.md +++ b/lib/rules/selector-id-pattern/README.md @@ -19,8 +19,8 @@ The selector value _after `#`_ will be checked. No need to include `#` in your p Given the string: -```js -"foo-[a-z]+"; +``` +"foo-[a-z]+" ``` The following patterns are considered violations: diff --git a/lib/rules/selector-nested-pattern/README.md b/lib/rules/selector-nested-pattern/README.md index 49415d8c7b..fc223497cd 100644 --- a/lib/rules/selector-nested-pattern/README.md +++ b/lib/rules/selector-nested-pattern/README.md @@ -24,8 +24,8 @@ The selector value will be checked in its entirety. If you'd like to allow for c Given the string: -```js -"^&:(?:hover|focus)$"; +``` +"^&:(?:hover|focus)$" ``` The following patterns are considered violations: diff --git a/package-lock.json b/package-lock.json index 62be53202e..2e67869903 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,158 +5,157 @@ "requires": true, "dependencies": { "@babel/code-frame": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.1.tgz", - "integrity": "sha512-IGhtTmpjGbYzcEDOw7DcQtbQSXcG9ftmAXtWTu9V936vDye4xjjekktFAtgZsWpzTj/X01jocB46mTywm/4SZw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", "requires": { - "@babel/highlight": "^7.10.1" + "@babel/highlight": "^7.10.4" } }, "@babel/core": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.10.2.tgz", - "integrity": "sha512-KQmV9yguEjQsXqyOUGKjS4+3K8/DlOCE2pZcq4augdQmtTy5iv5EHtmMSJ7V4c1BIPjuwtZYqYLCq9Ga+hGBRQ==", - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.2", - "@babel/helper-module-transforms": "^7.10.1", - "@babel/helpers": "^7.10.1", - "@babel/parser": "^7.10.2", - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.2", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz", + "integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.4", + "@babel/helper-module-transforms": "^7.11.0", + "@babel/helpers": "^7.10.4", + "@babel/parser": "^7.11.4", + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.11.0", + "@babel/types": "^7.11.0", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.1", "json5": "^2.1.2", - "lodash": "^4.17.13", + "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", "source-map": "^0.5.0" } }, "@babel/generator": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.10.2.tgz", - "integrity": "sha512-AxfBNHNu99DTMvlUPlt1h2+Hn7knPpH5ayJ8OqDWSeLld+Fi2AYBTC/IejWDM9Edcii4UzZRCsbUt0WlSDsDsA==", + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz", + "integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==", "requires": { - "@babel/types": "^7.10.2", + "@babel/types": "^7.11.0", "jsesc": "^2.5.1", - "lodash": "^4.17.13", "source-map": "^0.5.0" } }, "@babel/helper-function-name": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.1.tgz", - "integrity": "sha512-fcpumwhs3YyZ/ttd5Rz0xn0TpIwVkN7X0V38B9TWNfVF42KEkhkAAuPCQ3oXmtTRtiPJrmZ0TrfS0GKF0eMaRQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", + "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", "requires": { - "@babel/helper-get-function-arity": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-get-function-arity": "^7.10.4", + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-get-function-arity": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.1.tgz", - "integrity": "sha512-F5qdXkYGOQUb0hpRaPoetF9AnsXknKjWMZ+wmsIRsp5ge5sFh4c3h1eH2pRTTuy9KKAA2+TTYomGXAtEL2fQEw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", + "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.10.4" } }, "@babel/helper-member-expression-to-functions": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.10.1.tgz", - "integrity": "sha512-u7XLXeM2n50gb6PWJ9hoO5oO7JFPaZtrh35t8RqKLT1jFKj9IWeD1zrcrYp1q1qiZTdEarfDWfTIP8nGsu0h5g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", + "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.11.0" } }, "@babel/helper-module-imports": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.1.tgz", - "integrity": "sha512-SFxgwYmZ3HZPyZwJRiVNLRHWuW2OgE5k2nrVs6D9Iv4PPnXVffuEHy83Sfx/l4SqF+5kyJXjAyUmrG7tNm+qVg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", + "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.10.4" } }, "@babel/helper-module-transforms": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.10.1.tgz", - "integrity": "sha512-RLHRCAzyJe7Q7sF4oy2cB+kRnU4wDZY/H2xJFGof+M+SJEGhZsb+GFj5j1AD8NiSaVBJ+Pf0/WObiXu/zxWpFg==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", + "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", "requires": { - "@babel/helper-module-imports": "^7.10.1", - "@babel/helper-replace-supers": "^7.10.1", - "@babel/helper-simple-access": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1", - "lodash": "^4.17.13" + "@babel/helper-module-imports": "^7.10.4", + "@babel/helper-replace-supers": "^7.10.4", + "@babel/helper-simple-access": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/template": "^7.10.4", + "@babel/types": "^7.11.0", + "lodash": "^4.17.19" } }, "@babel/helper-optimise-call-expression": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.1.tgz", - "integrity": "sha512-a0DjNS1prnBsoKx83dP2falChcs7p3i8VMzdrSbfLhuQra/2ENC4sbri34dz/rWmDADsmF1q5GbfaXydh0Jbjg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", + "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.10.4" } }, "@babel/helper-plugin-utils": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.1.tgz", - "integrity": "sha512-fvoGeXt0bJc7VMWZGCAEBEMo/HAjW2mP8apF5eXK0wSqwLAVHAISCWRoLMBMUs2kqeaG77jltVqu4Hn8Egl3nA==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", + "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", "dev": true }, "@babel/helper-replace-supers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.1.tgz", - "integrity": "sha512-SOwJzEfpuQwInzzQJGjGaiG578UYmyi2Xw668klPWV5n07B73S0a9btjLk/52Mlcxa+5AdIYqws1KyXRfMoB7A==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", + "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.1", - "@babel/helper-optimise-call-expression": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/helper-member-expression-to-functions": "^7.10.4", + "@babel/helper-optimise-call-expression": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-simple-access": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.1.tgz", - "integrity": "sha512-VSWpWzRzn9VtgMJBIWTZ+GP107kZdQ4YplJlCmIrjoLVSi/0upixezHCDG8kpPVTBJpKfxTH01wDhh+jS2zKbw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", + "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", "requires": { - "@babel/template": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/template": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/helper-split-export-declaration": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.10.1.tgz", - "integrity": "sha512-UQ1LVBPrYdbchNhLwj6fetj46BcFwfS4NllJo/1aJsT+1dLTEnXJL0qHqtY7gPzF8S2fXBJamf1biAXV3X077g==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", + "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", "requires": { - "@babel/types": "^7.10.1" + "@babel/types": "^7.11.0" } }, "@babel/helper-validator-identifier": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.1.tgz", - "integrity": "sha512-5vW/JXLALhczRCWP0PnFDMCJAchlBvM7f4uk/jXritBnIa6E1KmqmtrS3yn1LAnxFBypQ3eneLuXjsnfQsgILw==" + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==" }, "@babel/helpers": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.1.tgz", - "integrity": "sha512-muQNHF+IdU6wGgkaJyhhEmI54MOZBKsFfsXFhboz1ybwJ1Kl7IHlbm2a++4jwrmY5UYsgitt5lfqo1wMFcHmyw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", + "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", "requires": { - "@babel/template": "^7.10.1", - "@babel/traverse": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/template": "^7.10.4", + "@babel/traverse": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/highlight": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.1.tgz", - "integrity": "sha512-8rMof+gVP8mxYZApLF/JgNDAkdKa+aJt3ZYxF8z6+j/hpeXL7iMsKCPHa2jNMHu/qqBwzQF4OHNoYi8dMA/rYg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", "requires": { - "@babel/helper-validator-identifier": "^7.10.1", + "@babel/helper-validator-identifier": "^7.10.4", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -174,9 +173,9 @@ } }, "@babel/parser": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.10.2.tgz", - "integrity": "sha512-PApSXlNMJyB4JiGVhCOlzKIif+TKFTvu0aQAhnTvfP/z3vVSN6ZypH5bfUNwFXXjRQtUEBNFd2PtmCmG2Py3qQ==" + "version": "7.11.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz", + "integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==" }, "@babel/plugin-syntax-async-generators": { "version": "7.8.4", @@ -197,21 +196,21 @@ } }, "@babel/plugin-syntax-class-properties": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.1.tgz", - "integrity": "sha512-Gf2Yx/iRs1JREDtVZ56OrjjgFHCaldpTnuy9BHla10qyVT3YkIIGEtoDWhyop0ksu1GvNjHIoYRBqm3zoR1jyQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", + "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-import-meta": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.1.tgz", - "integrity": "sha512-ypC4jwfIVF72og0dgvEcFRdOM2V9Qm1tu7RGmdZOlhsccyK0wisXmMObGuWEOd5jQ+K9wcIgSNftCpk2vkjUfQ==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-json-strings": { @@ -224,12 +223,12 @@ } }, "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.1.tgz", - "integrity": "sha512-XyHIFa9kdrgJS91CUH+ccPVTnJShr8nLGc5bG2IhGXv5p1Rd+8BleGE5yzIg2Nc1QZAdHDa0Qp4m6066OL96Iw==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-nullish-coalescing-operator": { @@ -242,12 +241,12 @@ } }, "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.1.tgz", - "integrity": "sha512-uTd0OsHrpe3tH5gRPTxG8Voh99/WCU78vIm5NMRYPAqC8lR4vajt6KkCAknCHrx24vkPdd/05yfdGSB4EIY2mg==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.10.1" + "@babel/helper-plugin-utils": "^7.10.4" } }, "@babel/plugin-syntax-object-rest-spread": { @@ -278,38 +277,38 @@ } }, "@babel/template": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.1.tgz", - "integrity": "sha512-OQDg6SqvFSsc9A0ej6SKINWrpJiNonRIniYondK2ViKhB06i3c0s+76XUft71iqBEe9S1OKsHwPAjfHnuvnCig==", + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", + "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1" + "@babel/code-frame": "^7.10.4", + "@babel/parser": "^7.10.4", + "@babel/types": "^7.10.4" } }, "@babel/traverse": { - "version": "7.10.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.10.1.tgz", - "integrity": "sha512-C/cTuXeKt85K+p08jN6vMDz8vSV0vZcI0wmQ36o6mjbuo++kPMdpOYw23W2XH04dbRt9/nMEfA4W3eR21CD+TQ==", - "requires": { - "@babel/code-frame": "^7.10.1", - "@babel/generator": "^7.10.1", - "@babel/helper-function-name": "^7.10.1", - "@babel/helper-split-export-declaration": "^7.10.1", - "@babel/parser": "^7.10.1", - "@babel/types": "^7.10.1", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.0.tgz", + "integrity": "sha512-ZB2V+LskoWKNpMq6E5UUCrjtDUh5IOTAyIl0dTjIEoXum/iKWkoIEKIRDnUucO6f+2FzNkE0oD4RLKoPIufDtg==", + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/generator": "^7.11.0", + "@babel/helper-function-name": "^7.10.4", + "@babel/helper-split-export-declaration": "^7.11.0", + "@babel/parser": "^7.11.0", + "@babel/types": "^7.11.0", "debug": "^4.1.0", "globals": "^11.1.0", - "lodash": "^4.17.13" + "lodash": "^4.17.19" } }, "@babel/types": { - "version": "7.10.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.10.2.tgz", - "integrity": "sha512-AD3AwWBSz0AWF0AkCN9VPiWrvldXq+/e3cHa4J89vo4ymjz1XwrBFFVZmkJTsQIPNk+ZVomPSXUJqq8yyjZsng==", + "version": "7.11.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.0.tgz", + "integrity": "sha512-O53yME4ZZI0jO1EVGtF1ePGl0LHirG4P1ibcD80XyzZcKhcMFeCXmh4Xb1ifGBIV233Qg12x4rBfQgA+tmOukA==", "requires": { - "@babel/helper-validator-identifier": "^7.10.1", - "lodash": "^4.17.13", + "@babel/helper-validator-identifier": "^7.10.4", + "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } }, @@ -340,63 +339,6 @@ "get-package-type": "^0.1.0", "js-yaml": "^3.13.1", "resolve-from": "^5.0.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } } }, "@istanbuljs/schema": { @@ -406,46 +348,48 @@ "dev": true }, "@jest/console": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.0.1.tgz", - "integrity": "sha512-9t1KUe/93coV1rBSxMmBAOIK3/HVpwxArCA1CxskKyRiv6o8J70V8C/V3OJminVCTa2M0hQI9AWRd5wxu2dAHw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.3.0.tgz", + "integrity": "sha512-/5Pn6sJev0nPUcAdpJHMVIsA8sKizL2ZkcKPE5+dJrCccks7tcM7c9wbgHudBJbxXLoTbqsHkG1Dofoem4F09w==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^26.0.1", - "jest-util": "^26.0.1", + "jest-message-util": "^26.3.0", + "jest-util": "^26.3.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.1.0.tgz", - "integrity": "sha512-zyizYmDJOOVke4OO/De//aiv8b07OwZzL2cfsvWF3q9YssfpcKfcnZAwDY8f+A76xXSMMYe8i/f/LPocLlByfw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-26.4.2.tgz", + "integrity": "sha512-sDva7YkeNprxJfepOctzS8cAk9TOekldh+5FhVuXS40+94SHbiicRO1VV2tSoRtgIo+POs/Cdyf8p76vPTd6dg==", "dev": true, "requires": { - "@jest/console": "^26.1.0", - "@jest/reporters": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", + "@jest/console": "^26.3.0", + "@jest/reporters": "^26.4.1", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-changed-files": "^26.1.0", - "jest-config": "^26.1.0", - "jest-haste-map": "^26.1.0", - "jest-message-util": "^26.1.0", + "jest-changed-files": "^26.3.0", + "jest-config": "^26.4.2", + "jest-haste-map": "^26.3.0", + "jest-message-util": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.1.0", - "jest-resolve-dependencies": "^26.1.0", - "jest-runner": "^26.1.0", - "jest-runtime": "^26.1.0", - "jest-snapshot": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "jest-watcher": "^26.1.0", + "jest-resolve": "^26.4.0", + "jest-resolve-dependencies": "^26.4.2", + "jest-runner": "^26.4.2", + "jest-runtime": "^26.4.2", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", + "jest-watcher": "^26.3.0", "micromatch": "^4.0.2", "p-each-series": "^2.1.0", "rimraf": "^3.0.0", @@ -453,557 +397,6 @@ "strip-ansi": "^6.0.0" }, "dependencies": { - "@jest/console": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", - "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "jest-message-util": "^26.1.0", - "jest-util": "^26.1.0", - "slash": "^3.0.0" - } - }, - "@jest/environment": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.1.0.tgz", - "integrity": "sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0" - } - }, - "@jest/fake-timers": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.1.0.tgz", - "integrity": "sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@sinonjs/fake-timers": "^6.0.1", - "jest-message-util": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0" - } - }, - "@jest/globals": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.1.0.tgz", - "integrity": "sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/types": "^26.1.0", - "expect": "^26.1.0" - } - }, - "@jest/source-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.1.0.tgz", - "integrity": "sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", - "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz", - "integrity": "sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q==", - "dev": true, - "requires": { - "@jest/test-result": "^26.1.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.1.0", - "jest-runner": "^26.1.0", - "jest-runtime": "^26.1.0" - } - }, - "@jest/transform": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", - "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.1.0", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.1.0", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", - "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "babel-jest": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.1.0.tgz", - "integrity": "sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg==", - "dev": true, - "requires": { - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/babel__core": "^7.1.7", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz", - "integrity": "sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-jest": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz", - "integrity": "sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^26.1.0", - "babel-preset-current-node-syntax": "^0.1.2" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "expect": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", - "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-regex-util": "^26.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-config": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.1.0.tgz", - "integrity": "sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.1.0", - "@jest/types": "^26.1.0", - "babel-jest": "^26.1.0", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.1.0", - "jest-environment-node": "^26.1.0", - "jest-get-type": "^26.0.0", - "jest-jasmine2": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "micromatch": "^4.0.2", - "pretty-format": "^26.1.0" - } - }, - "jest-diff": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", - "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-each": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.1.0.tgz", - "integrity": "sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-util": "^26.1.0", - "pretty-format": "^26.1.0" - } - }, - "jest-environment-jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz", - "integrity": "sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0", - "jsdom": "^16.2.2" - } - }, - "jest-environment-node": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.1.0.tgz", - "integrity": "sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0" - } - }, - "jest-haste-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", - "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@types/graceful-fs": "^4.1.2", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.4", - "jest-serializer": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - } - }, - "jest-jasmine2": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz", - "integrity": "sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.1.0", - "@jest/source-map": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^26.1.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^26.1.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-runtime": "^26.1.0", - "jest-snapshot": "^26.1.0", - "jest-util": "^26.1.0", - "pretty-format": "^26.1.0", - "throat": "^5.0.0" - } - }, - "jest-leak-detector": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz", - "integrity": "sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw==", - "dev": true, - "requires": { - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-matcher-utils": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", - "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-message-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", - "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - } - }, - "jest-mock": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.1.0.tgz", - "integrity": "sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0" - } - }, - "jest-resolve": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", - "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.1.0", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" - } - }, - "jest-runner": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.1.0.tgz", - "integrity": "sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/environment": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-config": "^26.1.0", - "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.1.0", - "jest-jasmine2": "^26.1.0", - "jest-leak-detector": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-resolve": "^26.1.0", - "jest-runtime": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "source-map-support": "^0.5.6", - "throat": "^5.0.0" - } - }, - "jest-runtime": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.1.0.tgz", - "integrity": "sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/globals": "^26.1.0", - "@jest/source-map": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-config": "^26.1.0", - "jest-haste-map": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.1.0", - "jest-snapshot": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^15.3.1" - } - }, - "jest-serializer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", - "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4" - } - }, - "jest-snapshot": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", - "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/prettier": "^2.0.0", - "chalk": "^4.0.0", - "expect": "^26.1.0", - "graceful-fs": "^4.2.4", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "jest-haste-map": "^26.1.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-resolve": "^26.1.0", - "natural-compare": "^1.4.0", - "pretty-format": "^26.1.0", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", - "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - } - }, - "jest-validate": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.1.0.tgz", - "integrity": "sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "camelcase": "^6.0.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "leven": "^3.1.0", - "pretty-format": "^26.1.0" - } - }, - "jest-watcher": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.1.0.tgz", - "integrity": "sha512-ffEOhJl2EvAIki613oPsSG11usqnGUzIiK7MMX6hE4422aXOcVEG3ySCTDFLn1+LZNXGPE8tuJxhp8OBJ1pgzQ==", - "dev": true, - "requires": { - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "jest-util": "^26.1.0", - "string-length": "^4.0.1" - } - }, - "jest-worker": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", - "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "pretty-format": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", - "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - }, "rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", @@ -1012,85 +405,57 @@ "requires": { "glob": "^7.1.3" } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, "@jest/environment": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.0.1.tgz", - "integrity": "sha512-xBDxPe8/nx251u0VJ2dFAFz2H23Y98qdIaNwnMK6dFQr05jc+Ne/2np73lOAx+5mSBO/yuQldRrQOf6hP1h92g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.3.0.tgz", + "integrity": "sha512-EW+MFEo0DGHahf83RAaiqQx688qpXgl99wdb8Fy67ybyzHwR1a58LHcO376xQJHfmoXTu89M09dH3J509cx2AA==", "dev": true, "requires": { - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1" + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0" } }, "@jest/fake-timers": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.0.1.tgz", - "integrity": "sha512-Oj/kCBnTKhm7CR+OJSjZty6N1bRDr9pgiYQr4wY221azLz5PHi08x/U+9+QpceAYOWheauLP8MhtSVFrqXQfhg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.3.0.tgz", + "integrity": "sha512-ZL9ytUiRwVP8ujfRepffokBvD2KbxbqMhrXSBhSdAhISCw3gOkuntisiSFv+A6HN0n0fF4cxzICEKZENLmW+1A==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@sinonjs/fake-timers": "^6.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@types/node": "*", + "jest-message-util": "^26.3.0", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0" } }, "@jest/globals": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.0.1.tgz", - "integrity": "sha512-iuucxOYB7BRCvT+TYBzUqUNuxFX1hqaR6G6IcGgEqkJ5x4htNKo1r7jk1ji9Zj8ZMiMw0oB5NaA7k5Tx6MVssA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.4.2.tgz", + "integrity": "sha512-Ot5ouAlehhHLRhc+sDz2/9bmNv9p5ZWZ9LE1pXGGTCXBasmi5jnYjlgYcYt03FBwLmZXCZ7GrL29c33/XRQiow==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/types": "^26.0.1", - "expect": "^26.0.1" + "@jest/environment": "^26.3.0", + "@jest/types": "^26.3.0", + "expect": "^26.4.2" } }, "@jest/reporters": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.1.0.tgz", - "integrity": "sha512-SVAysur9FOIojJbF4wLP0TybmqwDkdnFxHSPzHMMIYyBtldCW9gG+Q5xWjpMFyErDiwlRuPyMSJSU64A67Pazg==", + "version": "26.4.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-26.4.1.tgz", + "integrity": "sha512-aROTkCLU8++yiRGVxLsuDmZsQEKO6LprlrxtAuzvtpbIFl3eIjgIf3EUxDKgomkS25R9ZzwGEdB5weCcBZlrpQ==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", + "@jest/console": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", @@ -1101,199 +466,30 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.0.2", - "jest-haste-map": "^26.1.0", - "jest-resolve": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "node-notifier": "^7.0.0", + "jest-haste-map": "^26.3.0", + "jest-resolve": "^26.4.0", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", + "node-notifier": "^8.0.0", "slash": "^3.0.0", "source-map": "^0.6.0", "string-length": "^4.0.1", "terminal-link": "^2.0.0", - "v8-to-istanbul": "^4.1.3" + "v8-to-istanbul": "^5.0.1" }, "dependencies": { - "@jest/console": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", - "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "jest-message-util": "^26.1.0", - "jest-util": "^26.1.0", - "slash": "^3.0.0" - } - }, - "@jest/test-result": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", - "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/transform": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", - "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.1.0", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.1.0", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", - "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-haste-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", - "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@types/graceful-fs": "^4.1.2", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.4", - "jest-serializer": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - } - }, - "jest-message-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", - "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - } - }, - "jest-resolve": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", - "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.1.0", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" - } - }, - "jest-serializer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", - "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4" - } - }, - "jest-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", - "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - } - }, - "jest-worker": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", - "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } } } }, "@jest/source-map": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.0.0.tgz", - "integrity": "sha512-S2Z+Aj/7KOSU2TfW0dyzBze7xr95bkm5YXNUqqCek+HE0VbNNSNzrRwfIi5lf7wvzDTSS0/ib8XQ1krFNyYgbQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.3.0.tgz", + "integrity": "sha512-hWX5IHmMDWe1kyrKl7IhFwqOuAreIwHhbe44+XH2ZRHjrKIh0LO5eLQ/vxHFeAfRwJapmxuqlGAEYLadDq6ZGQ==", "dev": true, "requires": { "callsites": "^3.0.0", @@ -1310,46 +506,46 @@ } }, "@jest/test-result": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.0.1.tgz", - "integrity": "sha512-oKwHvOI73ICSYRPe8WwyYPTtiuOAkLSbY8/MfWF3qDEd/sa8EDyZzin3BaXTqufir/O/Gzea4E8Zl14XU4Mlyg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.3.0.tgz", + "integrity": "sha512-a8rbLqzW/q7HWheFVMtghXV79Xk+GWwOK1FrtimpI5n1la2SY0qHri3/b0/1F0Ve0/yJmV8pEhxDfVwiUBGtgg==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/types": "^26.3.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.0.1.tgz", - "integrity": "sha512-ssga8XlwfP8YjbDcmVhwNlrmblddMfgUeAkWIXts1V22equp2GMIHxm7cyeD5Q/B0ZgKPK/tngt45sH99yLLGg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.4.2.tgz", + "integrity": "sha512-83DRD8N3M0tOhz9h0bn6Kl6dSp+US6DazuVF8J9m21WAp5x7CqSMaNycMP0aemC/SH/pDQQddbsfHRTBXVUgog==", "dev": true, "requires": { - "@jest/test-result": "^26.0.1", + "@jest/test-result": "^26.3.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", - "jest-runner": "^26.0.1", - "jest-runtime": "^26.0.1" + "jest-haste-map": "^26.3.0", + "jest-runner": "^26.4.2", + "jest-runtime": "^26.4.2" } }, "@jest/transform": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.0.1.tgz", - "integrity": "sha512-pPRkVkAQ91drKGbzCfDOoHN838+FSbYaEAvBXvKuWeeRRUD8FjwXkqfUNUZL6Ke48aA/1cqq/Ni7kVMCoqagWA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.3.0.tgz", + "integrity": "sha512-Isj6NB68QorGoFWvcOjlUhpkT56PqNIsXKR7XfvoDlCANn/IANlh8DrKAA2l2JKC3yWSMH5wS0GwuQM20w3b2A==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "babel-plugin-istanbul": "^6.0.0", "chalk": "^4.0.0", "convert-source-map": "^1.4.0", "fast-json-stable-stringify": "^2.0.0", "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.0.1", + "jest-haste-map": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-util": "^26.0.1", + "jest-util": "^26.3.0", "micromatch": "^4.0.2", "pirates": "^4.0.1", "slash": "^3.0.0", @@ -1366,13 +562,14 @@ } }, "@jest/types": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.0.1.tgz", - "integrity": "sha512-IbtjvqI9+eS1qFnOIEL7ggWmT+iK/U+Vde9cGWtYb/b6XgKb3X44ZAe/z9YZzoAAZ/E92m0DqrilF934IGNnQA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.3.0.tgz", + "integrity": "sha512-BDPG23U0qDeAvU4f99haztXwdAg3hz4El95LkAM+tHAqqhiVzRpEGHHU8EDxT/AnxOrA65YjLBwDahdJ9pTLJQ==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", "@types/yargs": "^15.0.0", "chalk": "^4.0.0" } @@ -1401,9 +598,9 @@ } }, "@samverschueren/stream-to-observable": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz", - "integrity": "sha512-MI4Xx6LHs4Webyvi6EbspgyAb4D2Q2VtnCQ1blOJcoLS6mVa8lNN2rkIy1CVxfTUpoyIbCTkXES1rLXztFD1lg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.1.tgz", + "integrity": "sha512-c/qwwcHyafOQuVQJj0IlBjf5yYgBI7YPJ77k4fOJYesb41jio65eaJODRUmfYKhTOFBrIZ66kgvGPlNbjuoRdQ==", "dev": true, "requires": { "any-observable": "^0.3.0" @@ -1418,15 +615,15 @@ } }, "@sindresorhus/is": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", - "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz", + "integrity": "sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==", "dev": true }, "@sinonjs/commons": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.0.tgz", - "integrity": "sha512-wEj54PfsZ5jGSwMX68G8ZXFawcSglQSXqCftWX3ec8MDUzQdHgcKvw97awHbY0efQEL5iKUOAmmVtoYgmrSG4Q==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", + "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", "dev": true, "requires": { "type-detect": "4.0.8" @@ -1489,9 +686,9 @@ } }, "@types/babel__core": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.8.tgz", - "integrity": "sha512-KXBiQG2OXvaPWFPDS1rD8yV9vO0OuWIqAEqLsbfX0oU2REN5KuoMnZ1gClWcBhO5I3n6oTVAmrMufOvRqdmFTQ==", + "version": "7.1.9", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.9.tgz", + "integrity": "sha512-sY2RsIJ5rpER1u3/aQ8OFSI7qGIy8o1NEEbgb2UaJcvOtXOMpd39ko723NBpjQFg9SIX7TXtjejZVGeIMLhoOw==", "dev": true, "requires": { "@babel/parser": "^7.1.0", @@ -1521,9 +718,9 @@ } }, "@types/babel__traverse": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.12.tgz", - "integrity": "sha512-t4CoEokHTfcyfb4hUaF9oOHu9RmmNWnm1CP0YmMqOOfClKascOmvlEM736vlqeScuGvBDsHkf8R2INd4DWreQA==", + "version": "7.0.13", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.0.13.tgz", + "integrity": "sha512-i+zS7t6/s9cdQvbqKDARrcbrPvtJGlbYsMkazo03nTAK3RX9FNrLllXys22uiTGJapPOTZTQ35nHh4ISph4SLQ==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -1580,9 +777,9 @@ } }, "@types/glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-VgNIkxK+j7Nz5P7jvUZlRvhuPSmsEfS03b0alKcq5V/STUKAa3Plemsn5mrQUO7am6OErJ4rhGEGJbACclrtRA==", + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", "dev": true, "requires": { "@types/minimatch": "*", @@ -1638,12 +835,11 @@ } }, "@types/istanbul-reports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-1.1.2.tgz", - "integrity": "sha512-P/W9yOX/3oPZSpaYOCQzGqgCQRXn0FFO/V8bWrCQs+wLmvVVxk6CRBXALEvNs9OHIatlnlFokfhuDo2ug01ciw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.0.tgz", + "integrity": "sha512-nwKNbvnwJ2/mndE9ItP/zc2TCzw6uuodnF4EHYWD+gCQDVBuRQL5UzbZD0/ezy1iKsFU2ZQiDqg4M9dN4+wZgA==", "dev": true, "requires": { - "@types/istanbul-lib-coverage": "*", "@types/istanbul-lib-report": "*" } }, @@ -1663,9 +859,9 @@ } }, "@types/lodash": { - "version": "4.14.157", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.157.tgz", - "integrity": "sha512-Ft5BNFmv2pHDgxV5JDsndOWTRJ+56zte0ZpYLowp03tW+K+t8u8YMOzAnpuqPgzX6WO1XpDIUm7u04M8vdDiVQ==", + "version": "4.14.161", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.161.tgz", + "integrity": "sha512-EP6O3Jkr7bXvZZSZYlsgt5DIjiGr0dXP1/jVEwVLTFgg0d+3lWVQkRavYVQszV7dYUwvg0B8R0MBDpcmXg7XIA==", "dev": true }, "@types/micromatch": { @@ -1689,9 +885,9 @@ "integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=" }, "@types/node": { - "version": "14.0.13", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.13.tgz", - "integrity": "sha512-rouEWBImiRaSJsVA+ITTFM6ZxibuAlTuNOCyxVbwreu6k6+ujs7DfnU9o+PShFhET78pMBl3eH+AGSI5eOTkPA==", + "version": "14.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz", + "integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==", "dev": true }, "@types/normalize-package-data": { @@ -1714,9 +910,9 @@ } }, "@types/prettier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.0.1.tgz", - "integrity": "sha512-boy4xPNEtiw6N3abRhBi/e7hNvy3Tt8E9ZRAQrwAGzoCGZS/1wjo9KY7JHhnfnEsG5wSjDbymCozUM9a3ea7OQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.0.tgz", + "integrity": "sha512-hiYA88aHiEIgDmeKlsyVsuQdcFn3Z2VuFd/Xm/HCnGnPD8UFU5BM128uzzRVVGEzKDKYUrRsRH9S2o+NUy/3IA==", "dev": true }, "@types/responselike": { @@ -1817,15 +1013,15 @@ } }, "abab": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.3.tgz", - "integrity": "sha512-tsFzPpcttalNjFBCFMqsKYQcWxxen1pgJR56by//QwvJc4/OUS3kPOOttx2tSIfjsylB0pYu7f5D3K1RCxUnUg==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", + "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==", "dev": true }, "acorn": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.3.1.tgz", - "integrity": "sha512-tLc0wSnatxAQHVHUapaHdz72pi9KUyHjq5KyHjGg9Y8Ifdc79pTh2XvI6I1/chZbnM7QtNKzh66ooDogPZSleA==", + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", "dev": true }, "acorn-globals": { @@ -1851,9 +1047,9 @@ "dev": true }, "aggregate-error": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", - "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "requires": { "clean-stack": "^2.0.0", @@ -1861,9 +1057,9 @@ } }, "ajv": { - "version": "6.12.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", - "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", "requires": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1921,9 +1117,9 @@ } }, "ansi-colors": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", - "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", "dev": true }, "ansi-escapes": { @@ -2017,9 +1213,9 @@ "dev": true }, "arrify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", - "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" }, "asn1": { "version": "0.2.4", @@ -2043,9 +1239,9 @@ "dev": true }, "astral-regex": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", - "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" }, "async-exit-hook": { "version": "2.0.1", @@ -2066,24 +1262,17 @@ "dev": true }, "autoprefixer": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.2.tgz", - "integrity": "sha512-9UwMMU8Rg7Fj0c55mbOpXrr/2WrRqoOwOlLNTyyYt+nhiyQdIBWipp5XWzt+Lge8r3DK5y+EHMc1OBf8VpZA6Q==", + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", "requires": { "browserslist": "^4.12.0", - "caniuse-lite": "^1.0.30001084", - "kleur": "^4.0.1", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", "postcss": "^7.0.32", "postcss-value-parser": "^4.1.0" - }, - "dependencies": { - "kleur": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.0.1.tgz", - "integrity": "sha512-Qs6SqCLm63rd0kNVh+wO4XsWLU6kgfwwaPYsLiClWf0Tewkzsa6MvB21bespb8cz+ANS+2t3So1ge3gintzhlw==" - } } }, "aws-sign2": { @@ -2093,22 +1282,22 @@ "dev": true }, "aws4": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.0.tgz", - "integrity": "sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.10.1.tgz", + "integrity": "sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA==", "dev": true }, "babel-jest": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.0.1.tgz", - "integrity": "sha512-Z4GGmSNQ8pX3WS1O+6v3fo41YItJJZsVxG5gIQ+HuB/iuAQBJxMTHTwz292vuYws1LnHfwSRgoqI+nxdy/pcvw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.3.0.tgz", + "integrity": "sha512-sxPnQGEyHAOPF8NcUsD0g7hDCnvLL2XyblRBcgrzTWBB/mAIpWow3n1bEL+VghnnZfreLhFSBsFluRoK2tRK4g==", "dev": true, "requires": { - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "@types/babel__core": "^7.1.7", "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.0.0", + "babel-preset-jest": "^26.3.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "slash": "^3.0.0" @@ -2128,13 +1317,14 @@ } }, "babel-plugin-jest-hoist": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.0.0.tgz", - "integrity": "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==", + "version": "26.2.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.2.0.tgz", + "integrity": "sha512-B/hVMRv8Nh1sQ1a3EY8I0n4Y1Wty3NrR5ebOyVT302op+DOAau+xNEImGMsUWOC3++ZlMooCytKz+NgN8aKGbA==", "dev": true, "requires": { "@babel/template": "^7.3.3", "@babel/types": "^7.3.3", + "@types/babel__core": "^7.0.0", "@types/babel__traverse": "^7.0.6" } }, @@ -2158,13 +1348,13 @@ } }, "babel-preset-jest": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.0.0.tgz", - "integrity": "sha512-9ce+DatAa31DpR4Uir8g4Ahxs5K4W4L8refzt+qHWQANb6LhGcAEfIFgLUwk67oya2cCUd6t4eUMtO/z64ocNw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.3.0.tgz", + "integrity": "sha512-5WPdf7nyYi2/eRxCbVrE1kKCWxgWY4RsPEbdJWFm7QsesFGqjdkyLeu1zRkwM1cxK6EPIlNd6d2AxLk7J+t4pw==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^26.0.0", - "babel-preset-current-node-syntax": "^0.1.2" + "babel-plugin-jest-hoist": "^26.2.0", + "babel-preset-current-node-syntax": "^0.1.3" } }, "bail": { @@ -2252,9 +1442,9 @@ } }, "binary-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", - "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", + "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", "dev": true }, "boxen": { @@ -2283,12 +1473,6 @@ "color-convert": "^2.0.1" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -2321,9 +1505,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -2361,14 +1545,14 @@ "dev": true }, "browserslist": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.12.0.tgz", - "integrity": "sha512-UH2GkcEDSI0k/lRkuDSzFl9ZZ87skSy9w2XAn1MsZnL+4c4rqbBd3e82UWHbYDpztABrPBhZsTEeuxVfHppqDg==", + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.0.tgz", + "integrity": "sha512-pUsXKAF2lVwhmtpeA3LJrZ76jXuusrNyhduuQs7CDFf9foT4Y38aQOserd2lMe5DSSrjf3fx34oHwryuvxAUgQ==", "requires": { - "caniuse-lite": "^1.0.30001043", - "electron-to-chromium": "^1.3.413", - "node-releases": "^1.1.53", - "pkg-up": "^2.0.0" + "caniuse-lite": "^1.0.30001111", + "electron-to-chromium": "^1.3.523", + "escalade": "^3.0.2", + "node-releases": "^1.1.60" } }, "bser": { @@ -2436,9 +1620,9 @@ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==" }, "camelcase": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", - "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==" + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" }, "camelcase-keys": { "version": "6.2.2", @@ -2448,19 +1632,12 @@ "camelcase": "^5.3.1", "map-obj": "^4.0.0", "quick-lru": "^4.0.1" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - } } }, "caniuse-lite": { - "version": "1.0.30001085", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001085.tgz", - "integrity": "sha512-x0YRFRE0pmOD90z+9Xk7jwO58p4feVNXP+U8kWV+Uo/HADyrgESlepzIkUqPgaXkpyceZU6siM1gsK7sHgplqA==" + "version": "1.0.30001120", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001120.tgz", + "integrity": "sha512-JBP68okZs1X8D7MQTY602jxMYBmXEKOFkzTBaNSkubooMPFOAv2TXWaKle7qgHpjLDhUzA/TMT0qsNleVyXGUQ==" }, "capture-exit": { "version": "2.0.0", @@ -2519,9 +1696,9 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "requires": { "has-flag": "^4.0.0" } @@ -2561,9 +1738,9 @@ "dev": true }, "chokidar": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", - "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.2.tgz", + "integrity": "sha512-IZHaDeBeI+sZJRX7lGcXsdzgvZqKv6sECqsbErJA4mHWfpRrD8B97kSFN4cQz6nGBGiuFia1MKR4d6c1o8Cv7A==", "dev": true, "requires": { "anymatch": "~3.1.1", @@ -2612,9 +1789,9 @@ "dev": true }, "cli-boxes": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", - "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", "dev": true }, "cli-cursor": { @@ -2646,12 +1823,6 @@ "color-convert": "^2.0.1" } }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2681,9 +1852,9 @@ } }, "cli-width": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", - "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true }, "cliui": { @@ -2760,6 +1931,11 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" }, + "colorette": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz", + "integrity": "sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw==" + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2770,9 +1946,9 @@ } }, "commander": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.1.0.tgz", + "integrity": "sha512-wl7PNrYWd2y5mp1OK/LhTlv8Ff4kQJQRXXAvF+uU/TPNiVJUxZLRYGj/B0y/lPGAVcSbJqH2Za/cvHmrPMC8mA==", "dev": true }, "common-tags": { @@ -3138,9 +2314,9 @@ "dev": true }, "diff-sequences": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.0.0.tgz", - "integrity": "sha512-JC/eHYEC3aSS0vZGjuoc4vHA0yAQTzhQQldXMeMF+JlxLGJlCO38Gma82NV9gk1jGFz8mDzUMeaKXvjRRdJ2dg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-26.3.0.tgz", + "integrity": "sha512-5j5vdRcw3CNctePNYN0Wy2e/JbWT6cAYnXv5OuqPhDpyCGc0uLu2TK0zOCJWNB9kOIfYMSpIulRaDgIi4HJ6Ig==", "dev": true }, "dir-glob": { @@ -3254,9 +2430,9 @@ } }, "electron-to-chromium": { - "version": "1.3.480", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.480.tgz", - "integrity": "sha512-wnuUfQCBMAdzu5Xe+F4FjaRK+6ToG6WvwG72s8k/3E6b+hoGVYGiQE7JD1NhiCMcqF3+wV+c2vAnaLGRSSWVqA==" + "version": "1.3.555", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.555.tgz", + "integrity": "sha512-/55x3nF2feXFZ5tdGUOr00TxnUjUgdxhrn+eCJ1FAcoAt+cKQTjQkUC5XF4frMWE1R5sjHk+JueuBalimfe5Pg==" }, "elegant-spinner": { "version": "1.0.1", @@ -3264,6 +2440,12 @@ "integrity": "sha1-2wQ1IcldfjA/2PNFvtwzSc+wcp4=", "dev": true }, + "emittery": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.7.1.tgz", + "integrity": "sha512-d34LN4L6h18Bzz9xpoku2nPwKxCPlPMr3EEKTkoEBi+1/+b0lcRkRJ1UVyyZaKNeqGR3swcGl6s390DNO4YVgQ==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", @@ -3279,12 +2461,12 @@ } }, "enquirer": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.5.tgz", - "integrity": "sha512-BNT1C08P9XD0vNg3J475yIUG+mVdp9T6towYFHUv897X0KoHBjB1shyrNmhmtHWKP17iSWgo7Gqh7BBuzLZMSA==", + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", "dev": true, "requires": { - "ansi-colors": "^3.2.1" + "ansi-colors": "^4.1.1" } }, "entities": { @@ -3330,6 +2512,11 @@ "is-symbol": "^1.0.2" } }, + "escalade": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.0.2.tgz", + "integrity": "sha512-gPYAU37hYCUhW5euPeR+Y74F7BL+IBsV93j5cvGriSaD1aG6MGsqsV1yamRdrWrb2j3aiZvb0X+UBOWpx3JWtQ==" + }, "escape-goat": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz", @@ -3342,9 +2529,9 @@ "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, "escodegen": { - "version": "1.14.2", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.2.tgz", - "integrity": "sha512-InuOIiKk8wwuOFg6x9BQXbzjrQhtyXh46K9bqVTPzSo2FnyMBaYGBMC6PhQy7yxxil9vIedFBweQBMK74/7o8A==", + "version": "1.14.3", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz", + "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==", "dev": true, "requires": { "esprima": "^4.0.1", @@ -3403,9 +2590,9 @@ } }, "eslint": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.2.0.tgz", - "integrity": "sha512-B3BtEyaDKC5MlfDa2Ha8/D6DsS4fju95zs0hjS3HdGazw+LNayai38A25qMppK37wWGWNYSPOR6oYzlz5MHsRQ==", + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz", + "integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", @@ -3414,10 +2601,11 @@ "cross-spawn": "^7.0.2", "debug": "^4.0.1", "doctrine": "^3.0.0", + "enquirer": "^2.3.5", "eslint-scope": "^5.1.0", - "eslint-utils": "^2.0.0", - "eslint-visitor-keys": "^1.2.0", - "espree": "^7.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", "esquery": "^1.2.0", "esutils": "^2.0.2", "file-entry-cache": "^5.0.1", @@ -3427,12 +2615,11 @@ "ignore": "^4.0.6", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", - "inquirer": "^7.0.0", "is-glob": "^4.0.0", "js-yaml": "^3.13.1", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", - "lodash": "^4.17.14", + "lodash": "^4.17.19", "minimatch": "^3.0.4", "natural-compare": "^1.4.0", "optionator": "^0.9.1", @@ -3446,6 +2633,24 @@ "v8-compile-cache": "^2.0.3" }, "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, "globals": { "version": "12.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", @@ -3461,12 +2666,63 @@ "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", "dev": true }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, "semver": { "version": "7.3.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", "dev": true }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -3526,9 +2782,9 @@ } }, "eslint-plugin-jest": { - "version": "23.13.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.13.2.tgz", - "integrity": "sha512-qZit+moTXTyZFNDqSIR88/L3rdBlTU7CuW6XmyErD2FfHEkdoLgThkRbiQjzgYnX6rfgLx3Ci4eJmF4Ui5v1Cw==", + "version": "23.20.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-23.20.0.tgz", + "integrity": "sha512-+6BGQt85OREevBDWCvhqj1yYA4+BFK4XnRZSGJionuEYmcglMZYLNNBBemwzbqUAckURaHdJSBcjHPyrtypZOw==", "dev": true, "requires": { "@typescript-eslint/experimental-utils": "^2.5.0" @@ -3582,20 +2838,20 @@ } }, "eslint-visitor-keys": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.2.0.tgz", - "integrity": "sha512-WFb4ihckKil6hu3Dp798xdzSfddwKKU3+nGniKF6HfeW6OLd2OUDEPP7TcHtB5+QXOKg2s6B2DaMPE1Nn/kxKQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, "espree": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.1.0.tgz", - "integrity": "sha512-dcorZSyfmm4WTuTnE5Y7MEN1DyoPYy1ZR783QW1FJoenn7RailyWFsq/UL6ZAAA7uXurN9FIpYyUs3OfiIW+Qw==", + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.0.tgz", + "integrity": "sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw==", "dev": true, "requires": { - "acorn": "^7.2.0", + "acorn": "^7.4.0", "acorn-jsx": "^5.2.0", - "eslint-visitor-keys": "^1.2.0" + "eslint-visitor-keys": "^1.3.0" } }, "esprima": { @@ -3614,9 +2870,9 @@ }, "dependencies": { "estraverse": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.1.0.tgz", - "integrity": "sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", "dev": true } } @@ -3773,16 +3029,16 @@ } }, "expect": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.0.1.tgz", - "integrity": "sha512-QcCy4nygHeqmbw564YxNbHTJlXh47dVID2BUP52cZFpLU9zHViMFK6h07cC1wf7GYCTIigTdAXhVua8Yl1FkKg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/expect/-/expect-26.4.2.tgz", + "integrity": "sha512-IlJ3X52Z0lDHm7gjEp+m76uX46ldH5VpqmU0006vqDju/285twh7zaWMRhs67VpQhBwjjMchk+p5aA0VkERCAA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", + "jest-get-type": "^26.3.0", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", "jest-regex-util": "^26.0.0" }, "dependencies": { @@ -3951,9 +3207,9 @@ "dev": true }, "fastest-levenshtein": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.9.tgz", - "integrity": "sha512-8DIQrqkmGTMfjcwiebj28Y1l6eCoLCU+TppdZa5zp5ZyNO12oUhtEEeCZjojZZarD8+peRg3CxL4Zm5BrKr9Fw==" + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz", + "integrity": "sha512-On2N+BpYJ15xIC974QNVuYGMOlEVt4s0EOI3wwMqOmK1fdDY+FN/zltPV8vosq4ad4c/gJ1KHScUn/6AWIgiow==" }, "fastq": { "version": "1.8.0", @@ -4013,11 +3269,12 @@ } }, "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "requires": { - "locate-path": "^2.0.0" + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" } }, "find-versions": { @@ -4135,9 +3392,9 @@ "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==" }, "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -4267,20 +3524,19 @@ } }, "got": { - "version": "11.3.0", - "resolved": "https://registry.npmjs.org/got/-/got-11.3.0.tgz", - "integrity": "sha512-yi/kiZY2tNMtt5IfbfX8UL3hAZWb2gZruxYZ72AY28pU5p0TZjZdl0uRsuaFbnC0JopdUi3I+Mh1F3dPQ9Dh0Q==", + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/got/-/got-11.5.2.tgz", + "integrity": "sha512-yUhpEDLeuGiGJjRSzEq3kvt4zJtAcjKmhIiwNp/eUs75tRlXfWcHo5tcBaMQtnjHWC7nQYT5HkY/l0QOQTkVww==", "dev": true, "requires": { - "@sindresorhus/is": "^2.1.1", + "@sindresorhus/is": "^3.0.0", "@szmarczak/http-timer": "^4.0.5", "@types/cacheable-request": "^6.0.1", "@types/responselike": "^1.0.0", "cacheable-lookup": "^5.0.3", "cacheable-request": "^7.0.1", "decompress-response": "^6.0.0", - "get-stream": "^5.1.0", - "http2-wrapper": "^1.0.0-beta.4.5", + "http2-wrapper": "^1.0.0-beta.5.0", "lowercase-keys": "^2.0.0", "p-cancelable": "^2.0.0", "responselike": "^2.0.0" @@ -4306,12 +3562,12 @@ "dev": true }, "har-validator": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", - "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", "dev": true, "requires": { - "ajv": "^6.5.5", + "ajv": "^6.12.3", "har-schema": "^2.0.0" } }, @@ -4477,12 +3733,12 @@ } }, "http2-wrapper": { - "version": "1.0.0-beta.4.6", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.4.6.tgz", - "integrity": "sha512-9oB4BiGDTI1FmIBlOF9OJ5hwJvcBEmPCqk/hy314Uhy2uq5TjekUZM8w8SPLLlUEM+mxNhXdPAXfrJN2Zbb/GQ==", + "version": "1.0.0-beta.5.2", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.0-beta.5.2.tgz", + "integrity": "sha512-xYz9goEyBnC8XwXDTuC/MZ6t+MrKVQZOk4s7+PaDkwIsQd8IwqvM+0M6bA/2lvG8GHXcPdf+MejTUeO2LCPCeQ==", "dev": true, "requires": { - "quick-lru": "^5.0.0", + "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" }, "dependencies": { @@ -4613,105 +3869,53 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" }, "inquirer": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.2.0.tgz", - "integrity": "sha512-E0c4rPwr9ByePfNlTIB8z51kK1s2n6jrHuJeEHENl/sbq2G/S1auvibgEwNR4uSyiU+PiYHqSwsgGiXjG8p5ZQ==", + "version": "7.3.3", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz", + "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==", "dev": true, "requires": { "ansi-escapes": "^4.2.1", - "chalk": "^3.0.0", + "chalk": "^4.1.0", "cli-cursor": "^3.1.0", - "cli-width": "^2.0.0", + "cli-width": "^3.0.0", "external-editor": "^3.0.3", "figures": "^3.0.0", - "lodash": "^4.17.15", + "lodash": "^4.17.19", "mute-stream": "0.0.8", "run-async": "^2.4.0", - "rxjs": "^6.5.3", + "rxjs": "^6.6.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6" + } + }, + "inquirer-autosubmit-prompt": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/inquirer-autosubmit-prompt/-/inquirer-autosubmit-prompt-0.2.0.tgz", + "integrity": "sha512-mzNrusCk5L6kSzlN0Ioddn8yzrhYNLli+Sn2ZxMuLechMYAzakiFCIULxsxlQb5YKzthLGfrFACcWoAvM7p04Q==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "inquirer": "^6.2.1", + "rxjs": "^6.3.3" }, "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true }, - "chalk": { + "ansi-regex": { "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "inquirer-autosubmit-prompt": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/inquirer-autosubmit-prompt/-/inquirer-autosubmit-prompt-0.2.0.tgz", - "integrity": "sha512-mzNrusCk5L6kSzlN0Ioddn8yzrhYNLli+Sn2ZxMuLechMYAzakiFCIULxsxlQb5YKzthLGfrFACcWoAvM7p04Q==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "inquirer": "^6.2.1", - "rxjs": "^6.3.3" - }, - "dependencies": { - "ansi-escapes": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", - "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "requires": { "ansi-styles": "^3.2.1", @@ -4728,6 +3932,12 @@ "restore-cursor": "^2.0.0" } }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, "figures": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", @@ -4977,9 +4187,9 @@ } }, "is-docker": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", - "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.1.1.tgz", + "integrity": "sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw==", "dev": true }, "is-empty": { @@ -5118,9 +4328,9 @@ "dev": true }, "is-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", - "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", + "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", "dev": true, "requires": { "has-symbols": "^1.0.1" @@ -5161,13 +4371,10 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, "is-url-superb": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-3.0.0.tgz", - "integrity": "sha512-3faQP+wHCGDQT1qReM5zCPx2mxoal6DzbzquFlCYJLWyy4WPTved33ea2xFbX37z4NoriEwZGIYhFtx8RUB5wQ==", - "dev": true, - "requires": { - "url-regex": "^5.0.0" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz", + "integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==", + "dev": true }, "is-whitespace-character": { "version": "1.0.4", @@ -5242,700 +4449,121 @@ "dev": true, "requires": { "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-26.1.0.tgz", - "integrity": "sha512-LIti8jppw5BcQvmNJe4w2g1N/3V68HUfAv9zDVm7v+VAtQulGhH0LnmmiVkbNE4M4I43Bj2fXPiBGKt26k9tHw==", - "dev": true, - "requires": { - "@jest/core": "^26.1.0", - "import-local": "^3.0.2", - "jest-cli": "^26.1.0" - }, - "dependencies": { - "@jest/console": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-26.1.0.tgz", - "integrity": "sha512-+0lpTHMd/8pJp+Nd4lyip+/Iyf2dZJvcCqrlkeZQoQid+JlThA4M9vxHtheyrQ99jJTMQam+es4BcvZ5W5cC3A==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "jest-message-util": "^26.1.0", - "jest-util": "^26.1.0", - "slash": "^3.0.0" - } - }, - "@jest/environment": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-26.1.0.tgz", - "integrity": "sha512-86+DNcGongbX7ai/KE/S3/NcUVZfrwvFzOOWX/W+OOTvTds7j07LtC+MgGydH5c8Ri3uIrvdmVgd1xFD5zt/xA==", - "dev": true, - "requires": { - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0" - } - }, - "@jest/fake-timers": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-26.1.0.tgz", - "integrity": "sha512-Y5F3kBVWxhau3TJ825iuWy++BAuQzK/xEa+wD9vDH3RytW9f2DbMVodfUQC54rZDX3POqdxCgcKdgcOL0rYUpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@sinonjs/fake-timers": "^6.0.1", - "jest-message-util": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0" - } - }, - "@jest/globals": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-26.1.0.tgz", - "integrity": "sha512-MKiHPNaT+ZoG85oMaYUmGHEqu98y3WO2yeIDJrs2sJqHhYOy3Z6F7F/luzFomRQ8SQ1wEkmahFAz2291Iv8EAw==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/types": "^26.1.0", - "expect": "^26.1.0" - } - }, - "@jest/source-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-26.1.0.tgz", - "integrity": "sha512-XYRPYx4eEVX15cMT9mstnO7hkHP3krNtKfxUYd8L7gbtia8JvZZ6bMzSwa6IQJENbudTwKMw5R1BePRD+bkEmA==", - "dev": true, - "requires": { - "callsites": "^3.0.0", - "graceful-fs": "^4.2.4", - "source-map": "^0.6.0" - } - }, - "@jest/test-result": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-26.1.0.tgz", - "integrity": "sha512-Xz44mhXph93EYMA8aYDz+75mFbarTV/d/x0yMdI3tfSRs/vh4CqSxgzVmCps1fPkHDCtn0tU8IH9iCKgGeGpfw==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/istanbul-lib-coverage": "^2.0.0", - "collect-v8-coverage": "^1.0.0" - } - }, - "@jest/test-sequencer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-26.1.0.tgz", - "integrity": "sha512-Z/hcK+rTq56E6sBwMoQhSRDVjqrGtj1y14e2bIgcowARaIE1SgOanwx6gvY4Q9gTKMoZQXbXvptji+q5GYxa6Q==", - "dev": true, - "requires": { - "@jest/test-result": "^26.1.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.1.0", - "jest-runner": "^26.1.0", - "jest-runtime": "^26.1.0" - } - }, - "@jest/transform": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-26.1.0.tgz", - "integrity": "sha512-ICPm6sUXmZJieq45ix28k0s+d/z2E8CHDsq+WwtWI6kW8m7I8kPqarSEcUN86entHQ570ZBRci5OWaKL0wlAWw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/types": "^26.1.0", - "babel-plugin-istanbul": "^6.0.0", - "chalk": "^4.0.0", - "convert-source-map": "^1.4.0", - "fast-json-stable-stringify": "^2.0.0", - "graceful-fs": "^4.2.4", - "jest-haste-map": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-util": "^26.1.0", - "micromatch": "^4.0.2", - "pirates": "^4.0.1", - "slash": "^3.0.0", - "source-map": "^0.6.1", - "write-file-atomic": "^3.0.0" - } - }, - "@jest/types": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", - "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "babel-jest": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.1.0.tgz", - "integrity": "sha512-Nkqgtfe7j6PxLO6TnCQQlkMm8wdTdnIF8xrdpooHCuD5hXRzVEPbPneTJKknH5Dsv3L8ip9unHDAp48YQ54Dkg==", - "dev": true, - "requires": { - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/babel__core": "^7.1.7", - "babel-plugin-istanbul": "^6.0.0", - "babel-preset-jest": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "slash": "^3.0.0" - } - }, - "babel-plugin-jest-hoist": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-26.1.0.tgz", - "integrity": "sha512-qhqLVkkSlqmC83bdMhM8WW4Z9tB+JkjqAqlbbohS9sJLT5Ha2vfzuKqg5yenXrAjOPG2YC0WiXdH3a9PvB+YYw==", - "dev": true, - "requires": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.0.0", - "@types/babel__traverse": "^7.0.6" - } - }, - "babel-preset-jest": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-26.1.0.tgz", - "integrity": "sha512-na9qCqFksknlEj5iSdw1ehMVR06LCCTkZLGKeEtxDDdhg8xpUF09m29Kvh1pRbZ07h7AQ5ttLYUwpXL4tO6w7w==", - "dev": true, - "requires": { - "babel-plugin-jest-hoist": "^26.1.0", - "babel-preset-current-node-syntax": "^0.1.2" - } - }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "expect": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", - "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-regex-util": "^26.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-cli": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.1.0.tgz", - "integrity": "sha512-Imumvjgi3rU7stq6SJ1JUEMaV5aAgJYXIs0jPqdUnF47N/Tk83EXfmtvNKQ+SnFVI6t6mDOvfM3aA9Sg6kQPSw==", - "dev": true, - "requires": { - "@jest/core": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "import-local": "^3.0.2", - "is-ci": "^2.0.0", - "jest-config": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "prompts": "^2.0.1", - "yargs": "^15.3.1" - } - }, - "jest-config": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.1.0.tgz", - "integrity": "sha512-ONTGeoMbAwGCdq4WuKkMcdMoyfs5CLzHEkzFOlVvcDXufZSaIWh/OXMLa2fwKXiOaFcqEw8qFr4VOKJQfn4CVw==", - "dev": true, - "requires": { - "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.1.0", - "@jest/types": "^26.1.0", - "babel-jest": "^26.1.0", - "chalk": "^4.0.0", - "deepmerge": "^4.2.2", - "glob": "^7.1.1", - "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.1.0", - "jest-environment-node": "^26.1.0", - "jest-get-type": "^26.0.0", - "jest-jasmine2": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "micromatch": "^4.0.2", - "pretty-format": "^26.1.0" - } - }, - "jest-diff": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", - "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-each": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.1.0.tgz", - "integrity": "sha512-lYiSo4Igr81q6QRsVQq9LIkJW0hZcKxkIkHzNeTMPENYYDw/W/Raq28iJ0sLlNFYz2qxxeLnc5K2gQoFYlu2bA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-util": "^26.1.0", - "pretty-format": "^26.1.0" - } - }, - "jest-environment-jsdom": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.1.0.tgz", - "integrity": "sha512-dWfiJ+spunVAwzXbdVqPH1LbuJW/kDL+FyqgA5YzquisHqTi0g9hquKif9xKm7c1bKBj6wbmJuDkeMCnxZEpUw==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0", - "jsdom": "^16.2.2" - } - }, - "jest-environment-node": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.1.0.tgz", - "integrity": "sha512-DNm5x1aQH0iRAe9UYAkZenuzuJ69VKzDCAYISFHQ5i9e+2Tbeu2ONGY7YStubCLH8a1wdKBgqScYw85+ySxqxg==", - "dev": true, - "requires": { - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/types": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-util": "^26.1.0" - } - }, - "jest-haste-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", - "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@types/graceful-fs": "^4.1.2", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.4", - "jest-serializer": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - } - }, - "jest-jasmine2": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.1.0.tgz", - "integrity": "sha512-1IPtoDKOAG+MeBrKvvuxxGPJb35MTTRSDglNdWWCndCB3TIVzbLThRBkwH9P081vXLgiJHZY8Bz3yzFS803xqQ==", - "dev": true, - "requires": { - "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.1.0", - "@jest/source-map": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "co": "^4.6.0", - "expect": "^26.1.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^26.1.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-runtime": "^26.1.0", - "jest-snapshot": "^26.1.0", - "jest-util": "^26.1.0", - "pretty-format": "^26.1.0", - "throat": "^5.0.0" - } - }, - "jest-leak-detector": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.1.0.tgz", - "integrity": "sha512-dsMnKF+4BVOZwvQDlgn3MG+Ns4JuLv8jNvXH56bgqrrboyCbI1rQg6EI5rs+8IYagVcfVP2yZFKfWNZy0rK0Hw==", - "dev": true, - "requires": { - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-matcher-utils": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", - "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-message-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", - "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - } - }, - "jest-mock": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.1.0.tgz", - "integrity": "sha512-1Rm8EIJ3ZFA8yCIie92UbxZWj9SuVmUGcyhLHyAhY6WI3NIct38nVcfOPWhJteqSn8V8e3xOMha9Ojfazfpovw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0" - } - }, - "jest-resolve": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", - "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.1.0", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" - } - }, - "jest-runner": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.1.0.tgz", - "integrity": "sha512-elvP7y0fVDREnfqit0zAxiXkDRSw6dgCkzPCf1XvIMnSDZ8yogmSKJf192dpOgnUVykmQXwYYJnCx641uLTgcw==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/environment": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.4", - "jest-config": "^26.1.0", - "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.1.0", - "jest-jasmine2": "^26.1.0", - "jest-leak-detector": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-resolve": "^26.1.0", - "jest-runtime": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "source-map-support": "^0.5.6", - "throat": "^5.0.0" - } - }, - "jest-runtime": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.1.0.tgz", - "integrity": "sha512-1qiYN+EZLmG1QV2wdEBRf+Ci8i3VSfIYLF02U18PiUDrMbhfpN/EAMMkJtT02jgJUoaEOpHAIXG6zS3QRMzRmA==", - "dev": true, - "requires": { - "@jest/console": "^26.1.0", - "@jest/environment": "^26.1.0", - "@jest/fake-timers": "^26.1.0", - "@jest/globals": "^26.1.0", - "@jest/source-map": "^26.1.0", - "@jest/test-result": "^26.1.0", - "@jest/transform": "^26.1.0", - "@jest/types": "^26.1.0", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.4", - "jest-config": "^26.1.0", - "jest-haste-map": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-mock": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.1.0", - "jest-snapshot": "^26.1.0", - "jest-util": "^26.1.0", - "jest-validate": "^26.1.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0", - "yargs": "^15.3.1" - } - }, - "jest-serializer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", - "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4" - } - }, - "jest-snapshot": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", - "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/prettier": "^2.0.0", - "chalk": "^4.0.0", - "expect": "^26.1.0", - "graceful-fs": "^4.2.4", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "jest-haste-map": "^26.1.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-resolve": "^26.1.0", - "natural-compare": "^1.4.0", - "pretty-format": "^26.1.0", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", - "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - } - }, - "jest-validate": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.1.0.tgz", - "integrity": "sha512-WPApOOnXsiwhZtmkDsxnpye+XLb/tUISP+H6cHjfUIXvlG+eKwP+isnivsxlHCPaO9Q5wvbhloIBkdF3qUn+Nw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "camelcase": "^6.0.0", - "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "leven": "^3.1.0", - "pretty-format": "^26.1.0" - } - }, - "jest-worker": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", - "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "pretty-format": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", - "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - }, + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.0.0", + "semver": "^6.3.0" + }, + "dependencies": { "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + } + } + }, + "istanbul-lib-report": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", + "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^3.0.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + } + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", + "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "istanbul-reports": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", + "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, + "jest": { + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest/-/jest-26.4.2.tgz", + "integrity": "sha512-LLCjPrUh98Ik8CzW8LLVnSCfLaiY+wbK53U7VxnFSX7Q+kWC4noVeDvGWIFw0Amfq1lq2VfGm7YHWSLBV62MJw==", + "dev": true, + "requires": { + "@jest/core": "^26.4.2", + "import-local": "^3.0.2", + "jest-cli": "^26.4.2" + }, + "dependencies": { + "jest-cli": { + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-26.4.2.tgz", + "integrity": "sha512-zb+lGd/SfrPvoRSC/0LWdaWCnscXc1mGYW//NP4/tmBvRPT3VntZ2jtKUONsRi59zc5JqmsSajA9ewJKFYp8Cw==", "dev": true, "requires": { - "isexe": "^2.0.0" + "@jest/core": "^26.4.2", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.4", + "import-local": "^3.0.2", + "is-ci": "^2.0.0", + "jest-config": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", + "prompts": "^2.0.1", + "yargs": "^15.3.1" } } } }, "jest-changed-files": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.1.0.tgz", - "integrity": "sha512-HS5MIJp3B8t0NRKGMCZkcDUZo36mVRvrDETl81aqljT1S9tqiHRSpyoOvWg9ZilzZG9TDisDNaN1IXm54fLRZw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-26.3.0.tgz", + "integrity": "sha512-1C4R4nijgPltX6fugKxM4oQ18zimS7LqQ+zTTY8lMCMFPrxqBFb7KJH0Z2fRQJvw2Slbaipsqq7s1mgX5Iot+g==", "dev": true, "requires": { - "@jest/types": "^26.1.0", + "@jest/types": "^26.3.0", "execa": "^4.0.0", "throat": "^5.0.0" }, "dependencies": { - "@jest/types": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", - "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, "execa": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", @@ -5971,27 +4599,29 @@ } }, "jest-circus": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-26.0.1.tgz", - "integrity": "sha512-dp20V0Pi1N92Y7+ULPa3tNR9KCG0Sy19NiopyPmo5rNoQ4OGWmuzp1P0q1je2HV3fRD0BYE7wqh8aReGGENfUA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-26.4.2.tgz", + "integrity": "sha512-gzxoteivskdUTNxT7Jx6hrANsEm+x1wh8jaXmQCtzC7zoNWirk9chYdSosHFC4tJlfDZa0EsPreVAxLicLsV0w==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/environment": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", - "expect": "^26.0.1", + "expect": "^26.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^26.0.1", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1", + "jest-each": "^26.4.2", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-runner": "^26.4.2", + "jest-runtime": "^26.4.2", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "pretty-format": "^26.4.2", "stack-utils": "^2.0.2", "throat": "^5.0.0" }, @@ -6005,41 +4635,41 @@ } }, "jest-config": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.0.1.tgz", - "integrity": "sha512-9mWKx2L1LFgOXlDsC4YSeavnblN6A4CPfXFiobq+YYLaBMymA/SczN7xYTSmLaEYHZOcB98UdoN4m5uNt6tztg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-26.4.2.tgz", + "integrity": "sha512-QBf7YGLuToiM8PmTnJEdRxyYy3mHWLh24LJZKVdXZ2PNdizSe1B/E8bVm+HYcjbEzGuVXDv/di+EzdO/6Gq80A==", "dev": true, "requires": { "@babel/core": "^7.1.0", - "@jest/test-sequencer": "^26.0.1", - "@jest/types": "^26.0.1", - "babel-jest": "^26.0.1", + "@jest/test-sequencer": "^26.4.2", + "@jest/types": "^26.3.0", + "babel-jest": "^26.3.0", "chalk": "^4.0.0", "deepmerge": "^4.2.2", "glob": "^7.1.1", "graceful-fs": "^4.2.4", - "jest-environment-jsdom": "^26.0.1", - "jest-environment-node": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-jasmine2": "^26.0.1", + "jest-environment-jsdom": "^26.3.0", + "jest-environment-node": "^26.3.0", + "jest-get-type": "^26.3.0", + "jest-jasmine2": "^26.4.2", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-resolve": "^26.4.0", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", "micromatch": "^4.0.2", - "pretty-format": "^26.0.1" + "pretty-format": "^26.4.2" } }, "jest-diff": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.0.1.tgz", - "integrity": "sha512-odTcHyl5X+U+QsczJmOjWw5tPvww+y9Yim5xzqxVl/R1j4z71+fHW4g8qu1ugMmKdFdxw+AtQgs5mupPnzcIBQ==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.4.2.tgz", + "integrity": "sha512-6T1XQY8U28WH0Z5rGpQ+VqZSZz8EN8rZcBtfvXaOkbwxIEeRre6qnuZQlbY1AJ4MKDxQF8EkrCvK+hL/VkyYLQ==", "dev": true, "requires": { "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "diff-sequences": "^26.3.0", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" } }, "jest-docblock": { @@ -6052,105 +4682,98 @@ } }, "jest-each": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.0.1.tgz", - "integrity": "sha512-OTgJlwXCAR8NIWaXFL5DBbeS4QIYPuNASkzSwMCJO+ywo9BEa6TqkaSWsfR7VdbMLdgYJqSfQcIyjJCNwl5n4Q==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-26.4.2.tgz", + "integrity": "sha512-p15rt8r8cUcRY0Mvo1fpkOGYm7iI8S6ySxgIdfh3oOIv+gHwrHTy5VWCGOecWUhDsit4Nz8avJWdT07WLpbwDA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1" + "jest-get-type": "^26.3.0", + "jest-util": "^26.3.0", + "pretty-format": "^26.4.2" } }, "jest-environment-jsdom": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.0.1.tgz", - "integrity": "sha512-u88NJa3aptz2Xix2pFhihRBAatwZHWwSiRLBDBQE1cdJvDjPvv7ZGA0NQBxWwDDn7D0g1uHqxM8aGgfA9Bx49g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-jsdom/-/jest-environment-jsdom-26.3.0.tgz", + "integrity": "sha512-zra8He2btIMJkAzvLaiZ9QwEPGEetbxqmjEBQwhH3CA+Hhhu0jSiEJxnJMbX28TGUvPLxBt/zyaTLrOPF4yMJA==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1", + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0", "jsdom": "^16.2.2" } }, "jest-environment-node": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.0.1.tgz", - "integrity": "sha512-4FRBWcSn5yVo0KtNav7+5NH5Z/tEgDLp7VRQVS5tCouWORxj+nI+1tOLutM07Zb2Qi7ja+HEDoOUkjBSWZg/IQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-26.3.0.tgz", + "integrity": "sha512-c9BvYoo+FGcMj5FunbBgtBnbR5qk3uky8PKyRVpSfe2/8+LrNQMiXX53z6q2kY+j15SkjQCOSL/6LHnCPLVHNw==", "dev": true, "requires": { - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/types": "^26.0.1", - "jest-mock": "^26.0.1", - "jest-util": "^26.0.1" + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", + "jest-mock": "^26.3.0", + "jest-util": "^26.3.0" } }, "jest-get-type": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.0.0.tgz", - "integrity": "sha512-zRc1OAPnnws1EVfykXOj19zo2EMw5Hi6HLbFCSjpuJiXtOWAYIjNsHVSbpQ8bDX7L5BGYGI8m+HmKdjHYFF0kg==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-26.3.0.tgz", + "integrity": "sha512-TpfaviN1R2pQWkIihlfEanwOXK0zcxrKEE4MlU6Tn7keoXdN6/3gK/xl0yEh8DOunn5pOVGKf8hB4R9gVh04ig==", "dev": true }, "jest-haste-map": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.0.1.tgz", - "integrity": "sha512-J9kBl/EdjmDsvyv7CiyKY5+DsTvVOScenprz/fGqfLg/pm1gdjbwwQ98nW0t+OIt+f+5nAVaElvn/6wP5KO7KA==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.3.0.tgz", + "integrity": "sha512-DHWBpTJgJhLLGwE5Z1ZaqLTYqeODQIZpby0zMBsCU9iRFHYyhklYqP4EiG73j5dkbaAdSZhgB938mL51Q5LeZA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/graceful-fs": "^4.1.2", + "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.1.2", "graceful-fs": "^4.2.4", - "jest-serializer": "^26.0.0", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", + "jest-regex-util": "^26.0.0", + "jest-serializer": "^26.3.0", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", "micromatch": "^4.0.2", "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "walker": "^1.0.7" } }, "jest-jasmine2": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.0.1.tgz", - "integrity": "sha512-ILaRyiWxiXOJ+RWTKupzQWwnPaeXPIoLS5uW41h18varJzd9/7I0QJGqg69fhTT1ev9JpSSo9QtalriUN0oqOg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-jasmine2/-/jest-jasmine2-26.4.2.tgz", + "integrity": "sha512-z7H4EpCldHN1J8fNgsja58QftxBSL+JcwZmaXIvV9WKIM+x49F4GLHu/+BQh2kzRKHAgaN/E82od+8rTOBPyPA==", "dev": true, "requires": { "@babel/traverse": "^7.1.0", - "@jest/environment": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/environment": "^26.3.0", + "@jest/source-map": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", - "expect": "^26.0.1", + "expect": "^26.4.2", "is-generator-fn": "^2.0.0", - "jest-each": "^26.0.1", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "pretty-format": "^26.0.1", + "jest-each": "^26.4.2", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-runtime": "^26.4.2", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "pretty-format": "^26.4.2", "throat": "^5.0.0" }, "dependencies": { @@ -6163,35 +4786,35 @@ } }, "jest-leak-detector": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.0.1.tgz", - "integrity": "sha512-93FR8tJhaYIWrWsbmVN1pQ9ZNlbgRpfvrnw5LmgLRX0ckOJ8ut/I35CL7awi2ecq6Ca4lL59bEK9hr7nqoHWPA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-26.4.2.tgz", + "integrity": "sha512-akzGcxwxtE+9ZJZRW+M2o+nTNnmQZxrHJxX/HjgDaU5+PLmY1qnQPnMjgADPGCRPhB+Yawe1iij0REe+k/aHoA==", "dev": true, "requires": { - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" } }, "jest-matcher-utils": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.0.1.tgz", - "integrity": "sha512-PUMlsLth0Azen8Q2WFTwnSkGh2JZ8FYuwijC8NR47vXKpsrKmA1wWvgcj1CquuVfcYiDEdj985u5Wmg7COEARw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.4.2.tgz", + "integrity": "sha512-KcbNqWfWUG24R7tu9WcAOKKdiXiXCbMvQYT6iodZ9k1f7065k0keUOW6XpJMMvah+hTfqkhJhRXmA3r3zMAg0Q==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.0.1" + "jest-diff": "^26.4.2", + "jest-get-type": "^26.3.0", + "pretty-format": "^26.4.2" } }, "jest-message-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.0.1.tgz", - "integrity": "sha512-CbK8uQREZ8umUfo8+zgIfEt+W7HAHjQCoRaNs4WxKGhAYBGwEyvxuK81FXa7VeB9pwDEXeeKOB2qcsNVCAvB7Q==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.3.0.tgz", + "integrity": "sha512-xIavRYqr4/otGOiLxLZGj3ieMmjcNE73Ui+LdSW/Y790j5acqCsAdDiLIbzHCZMpN07JOENRWX5DcU+OQ+TjTA==", "dev": true, "requires": { "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/stack-utils": "^1.0.1", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", @@ -6201,376 +4824,152 @@ } }, "jest-mock": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.0.1.tgz", - "integrity": "sha512-MpYTBqycuPYSY6xKJognV7Ja46/TeRbAZept987Zp+tuJvMN0YBWyyhG9mXyYQaU3SBI0TUlSaO5L3p49agw7Q==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-26.3.0.tgz", + "integrity": "sha512-PeaRrg8Dc6mnS35gOo/CbZovoDPKAeB1FICZiuagAgGvbWdNNyjQjkOaGUa/3N3JtpQ/Mh9P4A2D4Fv51NnP8Q==", "dev": true, "requires": { - "@jest/types": "^26.0.1" + "@jest/types": "^26.3.0", + "@types/node": "*" } }, "jest-pnp-resolver": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.1.tgz", - "integrity": "sha512-pgFw2tm54fzgYvc/OHrnysABEObZCUNFnhjoRjaVOCN8NYc032/gVjPaHD4Aq6ApkSieWtfKAFQtmDKAmhupnQ==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.2.tgz", + "integrity": "sha512-olV41bKSMm8BdnuMsewT4jqlZ8+3TCARAXjZGT9jcoSnrfUnRCqnMoF9XEeoWjbzObpqF9dRhHQj0Xb9QdF6/w==", "dev": true }, "jest-preset-stylelint": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/jest-preset-stylelint/-/jest-preset-stylelint-3.0.0.tgz", - "integrity": "sha512-D1OVhoyshWE5i7upXpXuBMkMInnTFCia/uP5Dv+fwRjJz/hvJkJJvMXEa5I9EuHxa4/vmmG5busoMUyUCsKzAg==", - "dev": true - }, - "jest-regex-util": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", - "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", - "dev": true - }, - "jest-resolve": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.0.1.tgz", - "integrity": "sha512-6jWxk0IKZkPIVTvq6s72RH735P8f9eCJW3IM5CX/SJFeKq1p2cZx0U49wf/SdMlhaB/anann5J2nCJj6HrbezQ==", - "dev": true, - "requires": { - "@jest/types": "^26.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.0.1", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" - } - }, - "jest-resolve-dependencies": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.1.0.tgz", - "integrity": "sha512-fQVEPHHQ1JjHRDxzlLU/buuQ9om+hqW6Vo928aa4b4yvq4ZHBtRSDsLdKQLuCqn5CkTVpYZ7ARh2fbA8WkRE6g==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "jest-regex-util": "^26.0.0", - "jest-snapshot": "^26.1.0" - }, - "dependencies": { - "@jest/types": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.1.0.tgz", - "integrity": "sha512-GXigDDsp6ZlNMhXQDeuy/iYCDsRIHJabWtDzvnn36+aqFfG14JmFV0e/iXxY4SP9vbXSiPNOWdehU5MeqrYHBQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^1.1.1", - "@types/yargs": "^15.0.0", - "chalk": "^4.0.0" - } - }, - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "expect": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-26.1.0.tgz", - "integrity": "sha512-QbH4LZXDsno9AACrN9eM0zfnby9G+OsdNgZUohjg/P0mLy1O+/bzTAJGT6VSIjVCe8yKM6SzEl/ckEOFBT7Vnw==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-styles": "^4.0.0", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-regex-util": "^26.0.0" - } - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "jest-diff": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-26.1.0.tgz", - "integrity": "sha512-GZpIcom339y0OXznsEKjtkfKxNdg7bVbEofK8Q6MnevTIiR1jNhDWKhRX6X0SDXJlwn3dy59nZ1z55fLkAqPWg==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "diff-sequences": "^26.0.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-haste-map": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-26.1.0.tgz", - "integrity": "sha512-WeBS54xCIz9twzkEdm6+vJBXgRBQfdbbXD0dk8lJh7gLihopABlJmIQFdWSDDtuDe4PRiObsjZSUjbJ1uhWEpA==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "@types/graceful-fs": "^4.1.2", - "anymatch": "^3.0.3", - "fb-watchman": "^2.0.0", - "fsevents": "^2.1.2", - "graceful-fs": "^4.2.4", - "jest-serializer": "^26.1.0", - "jest-util": "^26.1.0", - "jest-worker": "^26.1.0", - "micromatch": "^4.0.2", - "sane": "^4.0.3", - "walker": "^1.0.7", - "which": "^2.0.2" - } - }, - "jest-matcher-utils": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-26.1.0.tgz", - "integrity": "sha512-PW9JtItbYvES/xLn5mYxjMd+Rk+/kIt88EfH3N7w9KeOrHWaHrdYPnVHndGbsFGRJ2d5gKtwggCvkqbFDoouQA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "pretty-format": "^26.1.0" - } - }, - "jest-message-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-26.1.0.tgz", - "integrity": "sha512-dY0+UlldiAJwNDJ08SF0HdF32g9PkbF2NRK/+2iMPU40O6q+iSn1lgog/u0UH8ksWoPv0+gNq8cjhYO2MFtT0g==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/stack-utils": "^1.0.1", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "micromatch": "^4.0.2", - "slash": "^3.0.0", - "stack-utils": "^2.0.2" - } - }, - "jest-resolve": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.1.0.tgz", - "integrity": "sha512-KsY1JV9FeVgEmwIISbZZN83RNGJ1CC+XUCikf/ZWJBX/tO4a4NvA21YixokhdR9UnmPKKAC4LafVixJBrwlmfg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "jest-pnp-resolver": "^1.2.1", - "jest-util": "^26.1.0", - "read-pkg-up": "^7.0.1", - "resolve": "^1.17.0", - "slash": "^3.0.0" - } - }, - "jest-serializer": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.1.0.tgz", - "integrity": "sha512-eqZOQG/0+MHmr25b2Z86g7+Kzd5dG9dhCiUoyUNJPgiqi38DqbDEOlHcNijyfZoj74soGBohKBZuJFS18YTJ5w==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4" - } - }, - "jest-snapshot": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.1.0.tgz", - "integrity": "sha512-YhSbU7eMTVQO/iRbNs8j0mKRxGp4plo7sJ3GzOQ0IYjvsBiwg0T1o0zGQAYepza7lYHuPTrG5J2yDd0CE2YxSw==", - "dev": true, - "requires": { - "@babel/types": "^7.0.0", - "@jest/types": "^26.1.0", - "@types/prettier": "^2.0.0", - "chalk": "^4.0.0", - "expect": "^26.1.0", - "graceful-fs": "^4.2.4", - "jest-diff": "^26.1.0", - "jest-get-type": "^26.0.0", - "jest-haste-map": "^26.1.0", - "jest-matcher-utils": "^26.1.0", - "jest-message-util": "^26.1.0", - "jest-resolve": "^26.1.0", - "natural-compare": "^1.4.0", - "pretty-format": "^26.1.0", - "semver": "^7.3.2" - } - }, - "jest-util": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.1.0.tgz", - "integrity": "sha512-rNMOwFQevljfNGvbzNQAxdmXQ+NawW/J72dmddsK0E8vgxXCMtwQ/EH0BiWEIxh0hhMcTsxwAxINt7Lh46Uzbg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.4", - "is-ci": "^2.0.0", - "micromatch": "^4.0.2" - } - }, - "jest-worker": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.1.0.tgz", - "integrity": "sha512-Z9P5pZ6UC+kakMbNJn+tA2RdVdNX5WH1x+5UCBZ9MxIK24pjYtFt96fK+UwBTrjLYm232g1xz0L3eTh51OW+yQ==", - "dev": true, - "requires": { - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - } - }, - "pretty-format": { - "version": "26.1.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.1.0.tgz", - "integrity": "sha512-GmeO1PEYdM+non4BKCj+XsPJjFOJIPnsLewqhDVoqY1xo0yNmDas7tC2XwpMrRAHR3MaE2hPo37deX5OisJ2Wg==", - "dev": true, - "requires": { - "@jest/types": "^26.1.0", - "ansi-regex": "^5.0.0", - "ansi-styles": "^4.0.0", - "react-is": "^16.12.0" - } - }, - "semver": { - "version": "7.3.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", - "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", - "dev": true - }, - "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/jest-preset-stylelint/-/jest-preset-stylelint-3.0.0.tgz", + "integrity": "sha512-D1OVhoyshWE5i7upXpXuBMkMInnTFCia/uP5Dv+fwRjJz/hvJkJJvMXEa5I9EuHxa4/vmmG5busoMUyUCsKzAg==", + "dev": true + }, + "jest-regex-util": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-26.0.0.tgz", + "integrity": "sha512-Gv3ZIs/nA48/Zvjrl34bf+oD76JHiGDUxNOVgUjh3j890sblXryjY4rss71fPtD/njchl6PSE2hIhvyWa1eT0A==", + "dev": true + }, + "jest-resolve": { + "version": "26.4.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-26.4.0.tgz", + "integrity": "sha512-bn/JoZTEXRSlEx3+SfgZcJAVuTMOksYq9xe9O6s4Ekg84aKBObEaVXKOEilULRqviSLAYJldnoWV9c07kwtiCg==", + "dev": true, + "requires": { + "@jest/types": "^26.3.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.4", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^26.3.0", + "read-pkg-up": "^7.0.1", + "resolve": "^1.17.0", + "slash": "^3.0.0" + } + }, + "jest-resolve-dependencies": { + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-26.4.2.tgz", + "integrity": "sha512-ADHaOwqEcVc71uTfySzSowA/RdxUpCxhxa2FNLiin9vWLB1uLPad3we+JSSROq5+SrL9iYPdZZF8bdKM7XABTQ==", + "dev": true, + "requires": { + "@jest/types": "^26.3.0", + "jest-regex-util": "^26.0.0", + "jest-snapshot": "^26.4.2" } }, "jest-runner": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.0.1.tgz", - "integrity": "sha512-CApm0g81b49Znm4cZekYQK67zY7kkB4umOlI2Dx5CwKAzdgw75EN+ozBHRvxBzwo1ZLYZ07TFxkaPm+1t4d8jA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-26.4.2.tgz", + "integrity": "sha512-FgjDHeVknDjw1gRAYaoUoShe1K3XUuFMkIaXbdhEys+1O4bEJS8Avmn4lBwoMfL8O5oFTdWYKcf3tEJyyYyk8g==", "dev": true, "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/console": "^26.3.0", + "@jest/environment": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", + "emittery": "^0.7.1", "exit": "^0.1.2", "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", + "jest-config": "^26.4.2", "jest-docblock": "^26.0.0", - "jest-haste-map": "^26.0.1", - "jest-jasmine2": "^26.0.1", - "jest-leak-detector": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "jest-runtime": "^26.0.1", - "jest-util": "^26.0.1", - "jest-worker": "^26.0.0", + "jest-haste-map": "^26.3.0", + "jest-leak-detector": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-resolve": "^26.4.0", + "jest-runtime": "^26.4.2", + "jest-util": "^26.3.0", + "jest-worker": "^26.3.0", "source-map-support": "^0.5.6", "throat": "^5.0.0" } }, "jest-runtime": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.0.1.tgz", - "integrity": "sha512-Ci2QhYFmANg5qaXWf78T2Pfo6GtmIBn2rRaLnklRyEucmPccmCKvS9JPljcmtVamsdMmkyNkVFb9pBTD6si9Lw==", - "dev": true, - "requires": { - "@jest/console": "^26.0.1", - "@jest/environment": "^26.0.1", - "@jest/fake-timers": "^26.0.1", - "@jest/globals": "^26.0.1", - "@jest/source-map": "^26.0.0", - "@jest/test-result": "^26.0.1", - "@jest/transform": "^26.0.1", - "@jest/types": "^26.0.1", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-26.4.2.tgz", + "integrity": "sha512-4Pe7Uk5a80FnbHwSOk7ojNCJvz3Ks2CNQWT5Z7MJo4tX0jb3V/LThKvD9tKPNVNyeMH98J/nzGlcwc00R2dSHQ==", + "dev": true, + "requires": { + "@jest/console": "^26.3.0", + "@jest/environment": "^26.3.0", + "@jest/fake-timers": "^26.3.0", + "@jest/globals": "^26.4.2", + "@jest/source-map": "^26.3.0", + "@jest/test-result": "^26.3.0", + "@jest/transform": "^26.3.0", + "@jest/types": "^26.3.0", "@types/yargs": "^15.0.0", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", "exit": "^0.1.2", "glob": "^7.1.3", "graceful-fs": "^4.2.4", - "jest-config": "^26.0.1", - "jest-haste-map": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-mock": "^26.0.1", + "jest-config": "^26.4.2", + "jest-haste-map": "^26.3.0", + "jest-message-util": "^26.3.0", + "jest-mock": "^26.3.0", "jest-regex-util": "^26.0.0", - "jest-resolve": "^26.0.1", - "jest-snapshot": "^26.0.1", - "jest-util": "^26.0.1", - "jest-validate": "^26.0.1", + "jest-resolve": "^26.4.0", + "jest-snapshot": "^26.4.2", + "jest-util": "^26.3.0", + "jest-validate": "^26.4.2", "slash": "^3.0.0", "strip-bom": "^4.0.0", "yargs": "^15.3.1" } }, "jest-serializer": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.0.0.tgz", - "integrity": "sha512-sQGXLdEGWFAE4wIJ2ZaIDb+ikETlUirEOBsLXdoBbeLhTHkZUJwgk3+M8eyFizhM6le43PDCCKPA1hzkSDo4cQ==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-serializer/-/jest-serializer-26.3.0.tgz", + "integrity": "sha512-IDRBQBLPlKa4flg77fqg0n/pH87tcRKwe8zxOVTWISxGpPHYkRZ1dXKyh04JOja7gppc60+soKVZ791mruVdow==", "dev": true, "requires": { + "@types/node": "*", "graceful-fs": "^4.2.4" } }, "jest-snapshot": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.0.1.tgz", - "integrity": "sha512-jxd+cF7+LL+a80qh6TAnTLUZHyQoWwEHSUFJjkw35u3Gx+BZUNuXhYvDqHXr62UQPnWo2P6fvQlLjsU93UKyxA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-26.4.2.tgz", + "integrity": "sha512-N6Uub8FccKlf5SBFnL2Ri/xofbaA68Cc3MGjP/NuwgnsvWh+9hLIR/DhrxbSiKXMY9vUW5dI6EW1eHaDHqe9sg==", "dev": true, "requires": { "@babel/types": "^7.0.0", - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "@types/prettier": "^2.0.0", "chalk": "^4.0.0", - "expect": "^26.0.1", + "expect": "^26.4.2", "graceful-fs": "^4.2.4", - "jest-diff": "^26.0.1", - "jest-get-type": "^26.0.0", - "jest-matcher-utils": "^26.0.1", - "jest-message-util": "^26.0.1", - "jest-resolve": "^26.0.1", - "make-dir": "^3.0.0", + "jest-diff": "^26.4.2", + "jest-get-type": "^26.3.0", + "jest-haste-map": "^26.3.0", + "jest-matcher-utils": "^26.4.2", + "jest-message-util": "^26.3.0", + "jest-resolve": "^26.4.0", "natural-compare": "^1.4.0", - "pretty-format": "^26.0.1", + "pretty-format": "^26.4.2", "semver": "^7.3.2" }, "dependencies": { @@ -6583,30 +4982,39 @@ } }, "jest-util": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.0.1.tgz", - "integrity": "sha512-byQ3n7ad1BO/WyFkYvlWQHTsomB6GIewBh8tlGtusiylAlaxQ1UpS0XYH0ngOyhZuHVLN79Qvl6/pMiDMSSG1g==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-26.3.0.tgz", + "integrity": "sha512-4zpn6bwV0+AMFN0IYhH/wnzIQzRaYVrz1A8sYnRnj4UXDXbOVtWmlaZkO9mipFqZ13okIfN87aDoJWB7VH6hcw==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", + "@types/node": "*", "chalk": "^4.0.0", "graceful-fs": "^4.2.4", "is-ci": "^2.0.0", - "make-dir": "^3.0.0" + "micromatch": "^4.0.2" } }, "jest-validate": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.0.1.tgz", - "integrity": "sha512-u0xRc+rbmov/VqXnX3DlkxD74rHI/CfS5xaV2VpeaVySjbb1JioNVOyly5b56q2l9ZKe7bVG5qWmjfctkQb0bA==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-26.4.2.tgz", + "integrity": "sha512-blft+xDX7XXghfhY0mrsBCYhX365n8K5wNDC4XAcNKqqjEzsRUSXP44m6PL0QJEW2crxQFLLztVnJ4j7oPlQrQ==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "camelcase": "^6.0.0", "chalk": "^4.0.0", - "jest-get-type": "^26.0.0", + "jest-get-type": "^26.3.0", "leven": "^3.1.0", - "pretty-format": "^26.0.1" + "pretty-format": "^26.4.2" + }, + "dependencies": { + "camelcase": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.0.0.tgz", + "integrity": "sha512-8KMDF1Vz2gzOq54ONPJS65IvTUaB1cHJ2DMM7MbPmLZljDH1qpzzLsWdiN9pHh6qvkRVDTi/07+eNGch/oLU4w==", + "dev": true + } } }, "jest-watch-typeahead": { @@ -6625,25 +5033,27 @@ } }, "jest-watcher": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.0.1.tgz", - "integrity": "sha512-pdZPydsS8475f89kGswaNsN3rhP6lnC3/QDCppP7bg1L9JQz7oU9Mb/5xPETk1RHDCWeqmVC47M4K5RR7ejxFw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-26.3.0.tgz", + "integrity": "sha512-XnLdKmyCGJ3VoF6G/p5ohbJ04q/vv5aH9ENI+i6BL0uu9WWB6Z7Z2lhQQk0d2AVZcRGp1yW+/TsoToMhBFPRdQ==", "dev": true, "requires": { - "@jest/test-result": "^26.0.1", - "@jest/types": "^26.0.1", + "@jest/test-result": "^26.3.0", + "@jest/types": "^26.3.0", + "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", - "jest-util": "^26.0.1", + "jest-util": "^26.3.0", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "26.0.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz", - "integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==", + "version": "26.3.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.3.0.tgz", + "integrity": "sha512-Vmpn2F6IASefL+DVBhPzI2J9/GJUsqzomdeN+P+dK8/jKxbh8R3BtFnx3FIta7wYlPU62cpJMJQo4kuOowcMnw==", "dev": true, "requires": { + "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^7.0.0" }, @@ -6655,9 +5065,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -6687,9 +5097,9 @@ "dev": true }, "jsdom": { - "version": "16.2.2", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.2.2.tgz", - "integrity": "sha512-pDFQbcYtKBHxRaP55zGXCJWgFHkDAYbKcsXEK/3Icu9nKYZkutUXfLBwbD+09XDutkYSHcgfQLZ0qvpAAm9mvg==", + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-16.4.0.tgz", + "integrity": "sha512-lYMm3wYdgPhrl7pDcRmvzPhhrGVBeVhPIqeHjzeiHN3DFmD1RBpbExbi8vU7BJdH8VAZYovR8DMt0PNNDM7k8w==", "dev": true, "requires": { "abab": "^2.0.3", @@ -6712,7 +5122,7 @@ "tough-cookie": "^3.0.1", "w3c-hr-time": "^1.0.2", "w3c-xmlserializer": "^2.0.0", - "webidl-conversions": "^6.0.0", + "webidl-conversions": "^6.1.0", "whatwg-encoding": "^1.0.5", "whatwg-mimetype": "^2.3.0", "whatwg-url": "^8.0.0", @@ -6734,7 +5144,13 @@ "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", - "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==" + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.0.tgz", + "integrity": "sha512-o3aP+RsWDJZayj1SbHNQAI8x0v3T3SKiGoZlNYfbUP1S3omJQ6i9CnqADqkSPaOAxwua4/1YWx5CM7oiChJt2Q==" }, "json-schema": { "version": "0.2.3", @@ -6865,15 +5281,6 @@ "path-exists": "^3.0.0" } }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, "p-locate": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", @@ -6883,10 +5290,10 @@ "p-limit": "^2.0.0" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", "dev": true } } @@ -6897,20 +5304,20 @@ "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=" }, "lint-staged": { - "version": "10.2.11", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.11.tgz", - "integrity": "sha512-LRRrSogzbixYaZItE2APaS4l2eJMjjf5MbclRZpLJtcQJShcvUzKXsNeZgsLIZ0H0+fg2tL4B59fU9wHIHtFIA==", + "version": "10.2.13", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-10.2.13.tgz", + "integrity": "sha512-conwlukNV6aL9SiMWjFtDp5exeDnTMekdNPDZsKGnpfQuHcO0E3L3Bbf58lcR+M7vk6LpCilxDAVks/DDVBYlA==", "dev": true, "requires": { - "chalk": "^4.0.0", - "cli-truncate": "2.1.0", - "commander": "^5.1.0", - "cosmiconfig": "^6.0.0", + "chalk": "^4.1.0", + "cli-truncate": "^2.1.0", + "commander": "^6.0.0", + "cosmiconfig": "^7.0.0", "debug": "^4.1.1", "dedent": "^0.7.0", - "enquirer": "^2.3.5", - "execa": "^4.0.1", - "listr2": "^2.1.0", + "enquirer": "^2.3.6", + "execa": "^4.0.3", + "listr2": "^2.6.0", "log-symbols": "^4.0.0", "micromatch": "^4.0.2", "normalize-path": "^3.0.0", @@ -6919,23 +5326,10 @@ "stringify-object": "^3.3.0" }, "dependencies": { - "cosmiconfig": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", - "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", - "dev": true, - "requires": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.1.0", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.7.2" - } - }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -7291,18 +5685,18 @@ } }, "listr2": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.1.8.tgz", - "integrity": "sha512-Op+hheiChfAphkJ5qUxZtHgyjlX9iNnAeFS/S134xw7mVSg0YVrQo1IY4/K+ElY6XgOPg2Ij4z07urUXR+YEew==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-2.6.2.tgz", + "integrity": "sha512-6x6pKEMs8DSIpA/tixiYY2m/GcbgMplMVmhQAaLFxEtNSKLeWTGjtmU57xvv6QCm2XcqzyNXL/cTSVf4IChCRA==", "dev": true, "requires": { - "chalk": "^4.0.0", + "chalk": "^4.1.0", "cli-truncate": "^2.1.0", "figures": "^3.2.0", "indent-string": "^4.0.0", "log-update": "^4.0.0", "p-map": "^4.0.0", - "rxjs": "^6.5.5", + "rxjs": "^6.6.2", "through": "^2.3.8" }, "dependencies": { @@ -7364,18 +5758,17 @@ } }, "locate-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", - "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "requires": { - "p-locate": "^2.0.0", - "path-exists": "^3.0.0" + "p-locate": "^4.1.0" } }, "lodash": { - "version": "4.17.19", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", - "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==" }, "lodash.sortby": { "version": "4.7.0", @@ -7407,50 +5800,6 @@ "cli-cursor": "^3.1.0", "slice-ansi": "^4.0.0", "wrap-ansi": "^6.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", - "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", - "dev": true, - "requires": { - "@types/color-name": "^1.1.1", - "color-convert": "^2.0.1" - } - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - } } }, "longest-streak": { @@ -7465,12 +5814,12 @@ "dev": true }, "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" } }, "make-dir": { @@ -7596,17 +5945,15 @@ "dev": true }, "meow": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-7.0.1.tgz", - "integrity": "sha512-tBKIQqVrAHqwit0vfuFPY3LlzJYkEOFyKa3bPgxzNl6q/RtN8KQ+ALYEASYuFayzSAsjlhXj/JZ10rH85Q6TUw==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-7.1.1.tgz", + "integrity": "sha512-GWHvA5QOcS412WCo8vwKDlTelGLsCGBVevQB5Kva961rmNfun0PCbv5+xta2kUMFJyR8/oWnn7ddeKdosbAPbA==", "requires": { "@types/minimist": "^1.2.0", - "arrify": "^2.0.1", - "camelcase": "^6.0.0", "camelcase-keys": "^6.2.2", "decamelize-keys": "^1.1.0", "hard-rejection": "^2.1.0", - "minimist-options": "^4.0.2", + "minimist-options": "4.1.0", "normalize-package-data": "^2.5.0", "read-pkg-up": "^7.0.1", "redent": "^3.0.0", @@ -7690,11 +6037,6 @@ "kind-of": "^6.0.3" }, "dependencies": { - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=" - }, "is-plain-obj": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", @@ -7803,9 +6145,9 @@ "dev": true }, "node-notifier": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-7.0.2.tgz", - "integrity": "sha512-ux+n4hPVETuTL8+daJXTOC6uKLgMsl1RYfFv7DKRzyvzBapqco0rZZ9g72ZN8VS6V+gvNYHYa/ofcCY8fkJWsA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/node-notifier/-/node-notifier-8.0.0.tgz", + "integrity": "sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==", "dev": true, "optional": true, "requires": { @@ -7813,7 +6155,7 @@ "is-wsl": "^2.2.0", "semver": "^7.3.2", "shellwords": "^0.1.1", - "uuid": "^8.2.0", + "uuid": "^8.3.0", "which": "^2.0.2" }, "dependencies": { @@ -7837,9 +6179,9 @@ } }, "node-releases": { - "version": "1.1.58", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.58.tgz", - "integrity": "sha512-NxBudgVKiRh/2aPWMgPR7bPTX0VPmGx5QBwCtdHitnqFE5/O8DeBXuIMH1nwNnw/aMo6AjOrpsHzfY3UbUJ7yg==" + "version": "1.1.60", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.60.tgz", + "integrity": "sha512-gsO4vjEdQaTusZAEebUWp2a5d7dF5DYoIpDG7WySnk7BuZDW+GPpHXoXXuYawRBr/9t5q54tirPz79kFIWg4dA==" }, "normalize-package-data": { "version": "2.5.0", @@ -7875,9 +6217,9 @@ "dev": true }, "np": { - "version": "6.2.4", - "resolved": "https://registry.npmjs.org/np/-/np-6.2.4.tgz", - "integrity": "sha512-3ChpSEnrQQGSH5kU8qei/vfmQRI8mggPjDvrIvGUBkAjCO0u3b3xTuraefJADZps0dGsblzcSXc5ZrAWcQAbaQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/np/-/np-6.5.0.tgz", + "integrity": "sha512-Xm1kUUlEqOZsu0qBA3A9wB44EBDRXubrLvfdCodG1TOllW0aymVI0qeFWKGN+kH74/XjO1B5how07fm3g+c72w==", "dev": true, "requires": { "@samverschueren/stream-to-observable": "^0.3.0", @@ -7901,7 +6243,7 @@ "log-symbols": "^3.0.0", "meow": "^6.0.0", "new-github-release-url": "^1.0.0", - "npm-name": "^5.4.0", + "npm-name": "^6.0.0", "onetime": "^5.1.0", "open": "^7.0.0", "ow": "^0.15.0", @@ -7996,9 +6338,9 @@ "dev": true }, "execa": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.2.tgz", - "integrity": "sha512-QI2zLa6CjGWdiQsmSkZoGtDx2N+cQIGb3yNolGTdjSQzydzLgYYf8LRuagp7S7fPimjcrzUDSUFd/MgzELMi4Q==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/execa/-/execa-4.0.3.tgz", + "integrity": "sha512-WFDXGHckXPWZX19t1kCsXzOpqX9LWYNqn4C+HqZlk/V0imTkzJZqf87ZBhvpHaftERYknpk0fjSylnXVlVgI0A==", "dev": true, "requires": { "cross-spawn": "^7.0.0", @@ -8040,12 +6382,12 @@ "dev": true }, "hosted-git-info": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz", - "integrity": "sha512-4oT62d2jwSDBbLLFLZE+1vPuQ1h8p9wjrJ8Mqx5TjsyWmBMV5B13eJqn8pvluqubLf3cJPTfiYCIwNwDNmzScQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", + "integrity": "sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==", "dev": true, "requires": { - "lru-cache": "^5.1.1" + "lru-cache": "^6.0.0" } }, "is-stream": { @@ -8162,9 +6504,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -8173,145 +6515,81 @@ } }, "npm-name": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/npm-name/-/npm-name-5.5.0.tgz", - "integrity": "sha512-l7/uyVfEi2e3ho+ovaJZC0xlbwzXNUz3RxkxpfcnLuoGKAuYoo9YoJ/uy18PsTD8IziugGHks4t/mGmBJEZ4Qg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/npm-name/-/npm-name-6.0.1.tgz", + "integrity": "sha512-fhKRvUAxaYzMEUZim4mXWyfFbVS+M1CbrCLdAo3txWzrctxKka/h+KaBW0O9Cz5uOM00Nldn2JLWhuwnyW3SUw==", "dev": true, "requires": { - "got": "^9.6.0", + "got": "^10.6.0", "is-scoped": "^2.1.0", - "is-url-superb": "^3.0.0", + "is-url-superb": "^4.0.0", "lodash.zip": "^4.2.0", + "org-regex": "^1.0.0", + "p-map": "^3.0.0", "registry-auth-token": "^4.0.0", "registry-url": "^5.1.0", "validate-npm-package-name": "^3.0.0" }, "dependencies": { "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-2.1.1.tgz", + "integrity": "sha512-/aPsuoj/1Dw/kzhkgz+ES6TxG0zfTMGLwuK2ZG00k/iJzYHTLCE8mVU8EPqEOp/lmxPoq1C1C9RYToRKb2KEfg==", "dev": true }, - "@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "defer-to-connect": "^1.0.1" - } - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "cacheable-lookup": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-2.0.1.tgz", + "integrity": "sha512-EMMbsiOTcdngM/K6gV/OxF2x0t07+vMOWxZNSCRQMjO2MY2nhZQ6OYhOOpyQrbhqsgtvKGI7hcq6xjnA92USjg==", "dev": true, "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } + "@types/keyv": "^3.1.1", + "keyv": "^4.0.0" } }, "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-5.0.0.tgz", + "integrity": "sha512-TLZWWybuxWgoW7Lykv+gq9xvzOsUjQ9tF09Tj6NSTYGMTCHNXzrPnD6Hi+TgZq19PyTAGH4Ll/NIM/eTGglnMw==", "dev": true, "requires": { - "pump": "^3.0.0" + "mimic-response": "^2.0.0" } }, "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "version": "10.7.0", + "resolved": "https://registry.npmjs.org/got/-/got-10.7.0.tgz", + "integrity": "sha512-aWTDeNw9g+XqEZNcTjMMZSy7B7yE9toWOFYip7ofFTLleJhvZwUxxTxkTpKvF+p1SAA4VHmuEy7PiHTHyq8tJg==", "dev": true, "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", + "@sindresorhus/is": "^2.0.0", + "@szmarczak/http-timer": "^4.0.0", + "@types/cacheable-request": "^6.0.1", + "cacheable-lookup": "^2.0.0", + "cacheable-request": "^7.0.1", + "decompress-response": "^5.0.0", "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" + "get-stream": "^5.0.0", + "lowercase-keys": "^2.0.0", + "mimic-response": "^2.1.0", + "p-cancelable": "^2.0.0", + "p-event": "^4.0.0", + "responselike": "^2.0.0", + "to-readable-stream": "^2.0.0", + "type-fest": "^0.10.0" } }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", "dev": true }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "type-fest": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.10.0.tgz", + "integrity": "sha512-EUV9jo4sffrwlg8s0zDhP0T2WD3pru5Xi0+HTE3zTUmBaZNhfkite9PdSJwdXLwPVW0jnAHT56pZHIOYckPEiw==", "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } } } }, @@ -8489,9 +6767,9 @@ } }, "object-inspect": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", "dev": true }, "object-keys": { @@ -8539,18 +6817,18 @@ } }, "onetime": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", - "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "requires": { "mimic-fn": "^2.1.0" } }, "open": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/open/-/open-7.0.4.tgz", - "integrity": "sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/open/-/open-7.2.1.tgz", + "integrity": "sha512-xbYCJib4spUdmcs0g/2mK1nKo/jO2T7INClWd/beL7PFkXRWgr8B23ssDHX/USPn2M2IjDR5UdpYs6I67SnTSA==", "dev": true, "requires": { "is-docker": "^2.0.0", @@ -8577,6 +6855,12 @@ "word-wrap": "^1.2.3" } }, + "org-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/org-regex/-/org-regex-1.0.0.tgz", + "integrity": "sha512-7bqkxkEJwzJQUAlyYniqEZ3Ilzjh0yoa62c7gL6Ijxj5bEpPL+8IE1Z0PFj0ywjjXQcdrwR51g9MIcLezR0hKQ==", + "dev": true + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", @@ -8618,6 +6902,15 @@ "integrity": "sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ==", "dev": true }, + "p-event": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz", + "integrity": "sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ==", + "dev": true, + "requires": { + "p-timeout": "^3.1.0" + } + }, "p-finally": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", @@ -8631,19 +6924,19 @@ "dev": true }, "p-limit": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", - "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "requires": { - "p-try": "^1.0.0" + "p-try": "^2.0.0" } }, "p-locate": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", - "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "requires": { - "p-limit": "^1.1.0" + "p-limit": "^2.2.0" } }, "p-map": { @@ -8675,9 +6968,9 @@ } }, "p-try": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", - "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" }, "package-json": { "version": "6.5.0", @@ -8722,9 +7015,9 @@ }, "dependencies": { "get-stream": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", - "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", "dev": true, "requires": { "pump": "^3.0.0" @@ -8822,6 +7115,12 @@ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true } } }, @@ -8847,13 +7146,13 @@ } }, "parse-json": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", - "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.1.0.tgz", + "integrity": "sha512-+mi/lmVVNKFNVyLXV31ERiy2CY5E1/F6QtJFEzoChPRwwngMNXRDQ9GJ5WdE2Z2P4AujsOi0/+2qHID68KwfIQ==", "requires": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", - "json-parse-better-errors": "^1.0.1", + "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" } }, @@ -8870,9 +7169,9 @@ "dev": true }, "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" }, "path-is-absolute": { "version": "1.0.1", @@ -8955,71 +7254,12 @@ "dev": true, "requires": { "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-2.0.0.tgz", - "integrity": "sha1-yBmscoBZpGHKscOImivjxJoATX8=", - "requires": { - "find-up": "^2.1.0" } }, "platform": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", - "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==", + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.6.tgz", + "integrity": "sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==", "dev": true }, "please-upgrade-node": { @@ -9192,9 +7432,9 @@ "dev": true }, "prettier": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", - "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.1.1.tgz", + "integrity": "sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw==", "dev": true }, "prettier-plugin-packagejson": { @@ -9207,12 +7447,12 @@ } }, "pretty-format": { - "version": "26.0.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.0.1.tgz", - "integrity": "sha512-SWxz6MbupT3ZSlL0Po4WF/KujhQaVehijR2blyRDCzk9e45EaYMVhMBn49fnRuHxtkSpXTes1GxNpVmH86Bxfw==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.4.2.tgz", + "integrity": "sha512-zK6Gd8zDsEiVydOCGLkoBoZuqv8VTiHyAbKznXe/gaph/DAeZOmit9yMfgIz5adIgAMMs5XfoYSwAX3jcCO1tA==", "dev": true, "requires": { - "@jest/types": "^26.0.1", + "@jest/types": "^26.3.0", "ansi-regex": "^5.0.0", "ansi-styles": "^4.0.0", "react-is": "^16.12.0" @@ -9390,49 +7630,6 @@ "type-fest": "^0.8.1" }, "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, "type-fest": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", @@ -9485,9 +7682,9 @@ "dev": true }, "registry-auth-token": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", - "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.0.tgz", + "integrity": "sha512-P+lWzPrsgfN+UEpDS3U8AQKg/UjZX6mQSJueZj3EK+vNESoqBSpBUD3gmu4sF9lOsjXWjF11dQKUqemf3veq1w==", "dev": true, "requires": { "rc": "^1.2.8" @@ -9503,9 +7700,9 @@ } }, "remark": { - "version": "12.0.0", - "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.0.tgz", - "integrity": "sha512-oX4lMIS0csgk8AEbzY0h2jdR0ngiCHOpwwpxjmRa5TqAkeknY+tkhjRJGZqnCmvyuWh55/0SW5WY3R3nn3PH9A==", + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/remark/-/remark-12.0.1.tgz", + "integrity": "sha512-gS7HDonkdIaHmmP/+shCPejCEEW+liMp/t/QwmF0Xt47Rpuhl32lLtDV1uKWvGoq+kxr5jSgg5oAIpGuyULjUw==", "requires": { "remark-parse": "^8.0.0", "remark-stringify": "^8.0.0", @@ -9513,9 +7710,9 @@ } }, "remark-cli": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-8.0.0.tgz", - "integrity": "sha512-5iRrk8ad+dU4espDl60H7ANhXqoaEXYsIyL8Mau0lDN6pP7QMAZsZTCX2XdoCfKfKEpiOggA7CHv43HkyVEppA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/remark-cli/-/remark-cli-8.0.1.tgz", + "integrity": "sha512-UaYeFI5qUAzkthUd8/MLBQD5OKM6jLN8GRvF6v+KF7xO/i1jQ+X2VqUSQAxWFYxZ8R25gM56GVjeoKOZ0EIr8A==", "dev": true, "requires": { "markdown-extensions": "^1.1.0", @@ -9534,27 +7731,27 @@ } }, "remark-lint": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-7.0.0.tgz", - "integrity": "sha512-OLrWPYy0MUcGLa/2rjuy1kQILTRRK+JiRtyUzqe4XRoHboGuvFDcy/W2e7sq5hu/0xmD+Eh7cEa1Coiqp7LeaA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/remark-lint/-/remark-lint-7.0.1.tgz", + "integrity": "sha512-caZXo3qhuBxzvq9JSJFVQ/ERDq/6TJVgWn0KDwKOIJCGOuLXfQhby5XttUq+Rn7kLbNMtvwfWHJlte14LpaeXQ==", "dev": true, "requires": { "remark-message-control": "^6.0.0" } }, "remark-lint-final-newline": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.4.tgz", - "integrity": "sha512-pUwqX8TVTTfqX5arMnu9Dr2ufg6wZ6Pk1VeqlnWfK92PBXLG8Zc3yrLpYXOJy1fHdWpqUECRRowG0H/OkZIEbw==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/remark-lint-final-newline/-/remark-lint-final-newline-1.0.5.tgz", + "integrity": "sha512-rfLlW8+Fz2dqnaEgU4JwLA55CQF1T4mfSs/GwkkeUCGPenvEYwSkCN2KO2Gr1dy8qPoOdTFE1rSufLjmeTW5HA==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0" } }, "remark-lint-hard-break-spaces": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-2.0.0.tgz", - "integrity": "sha512-dmB8GucOSDtEctwa+Y8JlSAWF4q8HcquvLr+OpFOSE1QCrpFoZdb2mcSY+rZuTtfeg4S60orhhzArd2aiHvUPQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-hard-break-spaces/-/remark-lint-hard-break-spaces-2.0.1.tgz", + "integrity": "sha512-Qfn/BMQFamHhtbfLrL8Co/dbYJFLRL4PGVXZ5wumkUO5f9FkZC2RsV+MD9lisvGTkJK0ZEJrVVeaPbUIFM0OAw==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9564,9 +7761,9 @@ } }, "remark-lint-list-item-bullet-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-2.0.0.tgz", - "integrity": "sha512-8iK+ht771UBf/Iuj4YBgdLnFFOyEgfXY62jBoywtMuiOLVWXDfPe+jUY7pCrnFjsnxXGEnMaxHJqENgrHd0J/w==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-bullet-indent/-/remark-lint-list-item-bullet-indent-2.0.1.tgz", + "integrity": "sha512-tozDt9LChG1CvYJnBQH/oh45vNcHYBvg79ogvV0f8MtE/K0CXsM8EpfQ6pImFUdHpBV1op6aF6zPMrB0AkRhcQ==", "dev": true, "requires": { "pluralize": "^8.0.0", @@ -9577,9 +7774,9 @@ } }, "remark-lint-list-item-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-2.0.0.tgz", - "integrity": "sha512-qnKsq2UQpCC8gnI1O23dgoKsd+5RAJrAJuvHXrlkRgzsab7BOMluptxRlyLVXn0P71l4Wo/bfo84Ual7qpOyWw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-list-item-indent/-/remark-lint-list-item-indent-2.0.1.tgz", + "integrity": "sha512-4IKbA9GA14Q9PzKSQI6KEHU/UGO36CSQEjaDIhmb9UOhyhuzz4vWhnSIsxyI73n9nl9GGRAMNUSGzr4pQUFwTA==", "dev": true, "requires": { "pluralize": "^8.0.0", @@ -9590,9 +7787,9 @@ } }, "remark-lint-no-auto-link-without-protocol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-2.0.0.tgz", - "integrity": "sha512-pIntUa+zNiyRxIt2Wvp1soktDbVnk1SEiJXsjcLYYn9GapgXqOQG5ZfFwR6zxTkGV5mZKo9927EvHQkvIV6cLQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-auto-link-without-protocol/-/remark-lint-no-auto-link-without-protocol-2.0.1.tgz", + "integrity": "sha512-TFcXxzucsfBb/5uMqGF1rQA+WJJqm1ZlYQXyvJEXigEZ8EAxsxZGPb/gOQARHl/y0vymAuYxMTaChavPKaBqpQ==", "dev": true, "requires": { "mdast-util-to-string": "^1.0.2", @@ -9603,9 +7800,9 @@ } }, "remark-lint-no-blockquote-without-marker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-3.0.0.tgz", - "integrity": "sha512-auyAxMVDuhvGw29VilqUfUIUnBT7qmByG/kBPqV/GwM1a5rn4fIUJ7p9Je9BlWMRCBMTNQUMsm3ce0dawouVew==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-blockquote-without-marker/-/remark-lint-no-blockquote-without-marker-3.0.1.tgz", + "integrity": "sha512-sM953+u0zN90SGd2V5hWcFbacbpaROUslS5Q5F7/aa66/2rAwh6zVnrXc4pf7fFOpj7I9Xa8Aw+uB+3RJWwdrQ==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9616,9 +7813,9 @@ } }, "remark-lint-no-duplicate-definitions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-2.0.0.tgz", - "integrity": "sha512-Z5DkYKbmS+r4D0ZhaXgK6L72EWzhiklpXNF/TS+KCsffAFgfy5aJfSA3A8GpVNj1wYMP35STXBGBCLW5TckvGw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-duplicate-definitions/-/remark-lint-no-duplicate-definitions-2.0.1.tgz", + "integrity": "sha512-XL22benJZB01m+aOse91nsu1IMFqeWJWme9QvoJuxIcBROO1BG1VoqLOkwNcawE/M/0CkvTo5rfx0eMlcnXOIw==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9629,9 +7826,9 @@ } }, "remark-lint-no-heading-content-indent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-2.0.0.tgz", - "integrity": "sha512-Zqg0WXG60Nan8j7HZtnBXidMxXhlhc7Q5JrB54I3n7H3vSPCyaqhZJ2/obYVLalEVGND8NOJGvfA1rtchaZyYg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-heading-content-indent/-/remark-lint-no-heading-content-indent-2.0.1.tgz", + "integrity": "sha512-Jp0zCykGwg13z7XU4VuoFK7DN8bVZ1u3Oqu3hqECsH6LMASb0tW4zcTIc985kcVo3OQTRyb6KLQXL2ltOvppKA==", "dev": true, "requires": { "mdast-util-heading-style": "^1.0.2", @@ -9643,9 +7840,9 @@ } }, "remark-lint-no-inline-padding": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-2.0.0.tgz", - "integrity": "sha512-0YueQ3SBA8zFQYCN0/afRc6ZuSbM4Azx4sPVeVpAfMT0MrYgmi6msswyhUDXaeN2RwVO6bx/ZW6di8dVqRr7UA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-inline-padding/-/remark-lint-no-inline-padding-2.0.1.tgz", + "integrity": "sha512-a36UlPvRrLCgxjjG3YZA9VCDvLBcoBtGNyM04VeCPz+d9hHe+5Fs1C/jL+DRLCH7nff90jJ5C/9b8/LTwhjaWA==", "dev": true, "requires": { "mdast-util-to-string": "^1.0.2", @@ -9655,9 +7852,9 @@ } }, "remark-lint-no-literal-urls": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-2.0.0.tgz", - "integrity": "sha512-bZAxr65ftz9joszDkSs2LBeJB2cRE8GydUtxYdA1WRHYmVW1AfM5ilcqLnWhiOmu+XMPH7J0eRvUzbtvu+xerw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-literal-urls/-/remark-lint-no-literal-urls-2.0.1.tgz", + "integrity": "sha512-IDdKtWOMuKVQIlb1CnsgBoyoTcXU3LppelDFAIZePbRPySVHklTtuK57kacgU5grc7gPM04bZV96eliGrRU7Iw==", "dev": true, "requires": { "mdast-util-to-string": "^1.0.2", @@ -9668,9 +7865,9 @@ } }, "remark-lint-no-shortcut-reference-image": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-2.0.0.tgz", - "integrity": "sha512-kgGCQBHibJ0IFVhWjnfjbqkKC0VeL5+cvyjjwfMJlgZrHEXNOYb2FJE2nvF/l6PSXQ17goRZpznTBfP4mQieUA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-image/-/remark-lint-no-shortcut-reference-image-2.0.1.tgz", + "integrity": "sha512-2jcZBdnN6ecP7u87gkOVFrvICLXIU5OsdWbo160FvS/2v3qqqwF2e/n/e7D9Jd+KTq1mR1gEVVuTqkWWuh3cig==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9679,9 +7876,9 @@ } }, "remark-lint-no-shortcut-reference-link": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-2.0.0.tgz", - "integrity": "sha512-rSdGLWpEsHa4b2doUch+B7QtUHH9XuC8Hndb4rAYf8U0d48KfGAIoiicxUho8qZJ4VA3RIaDo4kA/iQ15Al+Vg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-shortcut-reference-link/-/remark-lint-no-shortcut-reference-link-2.0.1.tgz", + "integrity": "sha512-pTZbslG412rrwwGQkIboA8wpBvcjmGFmvugIA+UQR+GfFysKtJ5OZMPGJ98/9CYWjw9Z5m0/EktplZ5TjFjqwA==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9690,9 +7887,9 @@ } }, "remark-lint-no-undefined-references": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-2.0.0.tgz", - "integrity": "sha512-K4k05pmlMRqEMUDYewitRUx8zM+ntJWbG61dILmL7to7uy0JoSbzuDtz1cxC+kKBKzkulPnyE3WOgRZG8RX2Jg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-undefined-references/-/remark-lint-no-undefined-references-2.0.1.tgz", + "integrity": "sha512-tXM2ctFnduC3QcskrIePUajcjtNtBmo2dvlj4aoQJtQy09Soav/rYngb8u/SgERc6Irdmm5s55UAwR9CcSrzVg==", "dev": true, "requires": { "collapse-white-space": "^1.0.4", @@ -9702,9 +7899,9 @@ } }, "remark-lint-no-unused-definitions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-2.0.0.tgz", - "integrity": "sha512-Y8zrulwaf7z6WR1ICfEGjW92iq2SPEN7Zhrs0nloNITHOg22tIPf28TurUz9HSQ3sEd52d9bZCfW9RkdfMq1xw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-no-unused-definitions/-/remark-lint-no-unused-definitions-2.0.1.tgz", + "integrity": "sha512-+BMc0BOjc364SvKYLkspmxDch8OaKPbnUGgQBvK0Bmlwy42baR4C9zhwAWBxm0SBy5Z4AyM4G4jKpLXPH40Oxg==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9713,9 +7910,9 @@ } }, "remark-lint-ordered-list-marker-style": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-2.0.0.tgz", - "integrity": "sha512-zYMZA8tQD/slJYKqsstZv0/Q34Hkdlf4DjC8SOr92PSA60R/xr7JdVd/AHHisbMsFvdnHZrxaB8oIOtbAUJCSw==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/remark-lint-ordered-list-marker-style/-/remark-lint-ordered-list-marker-style-2.0.1.tgz", + "integrity": "sha512-Cnpw1Dn9CHn+wBjlyf4qhPciiJroFOEGmyfX008sQ8uGoPZsoBVIJx76usnHklojSONbpjEDcJCjnOvfAcWW1A==", "dev": true, "requires": { "unified-lint-rule": "^1.0.0", @@ -9735,9 +7932,9 @@ } }, "remark-parse": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.2.tgz", - "integrity": "sha512-eMI6kMRjsAGpMXXBAywJwiwAse+KNpmt+BK55Oofy4KvBZEqUDj6mWbGLJZrujoPIPPxDXzn3T9baRlpsm2jnQ==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-8.0.3.tgz", + "integrity": "sha512-E1K9+QLGgggHxCQtLt++uXltxEprmWzNfg+MxpfHsZlrddKzZ/hZyWHDbK3/Ap8HJQqYJRXP+jHczdL6q6i85Q==", "requires": { "ccount": "^1.0.0", "collapse-white-space": "^1.0.2", @@ -9758,9 +7955,9 @@ } }, "remark-preset-lint-recommended": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-4.0.0.tgz", - "integrity": "sha512-Nroe+4Itvk+AHxkMCMu6iRUptE/5pXWgLoEOGdVO/2JIiMk/+15HEogMZ05vMhPct9+Wp4uVt2zqfuvzNzdcww==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/remark-preset-lint-recommended/-/remark-preset-lint-recommended-4.0.1.tgz", + "integrity": "sha512-zn+ImQbOVcAQVWLL0R0rFQ2Wy8JyWnuU3mJ8Zh0EVOckglcxByssvTbKqPih3Lh8ogpE38EfnC3a/vshj4Jx6A==", "dev": true, "requires": { "remark-lint": "^7.0.0", @@ -9788,9 +7985,9 @@ "dev": true }, "remark-stringify": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.0.tgz", - "integrity": "sha512-FSPZv1ds76oAZjurhhuV5qXSUSoz6QRPuwYK38S41sLHwg4oB7ejnmZshj7qwjgYLf93kdz6BOX9j5aidNE7rA==", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-8.1.1.tgz", + "integrity": "sha512-q4EyPZT3PcA3Eq7vPpT6bIdokXzFGp9i85igjmhRyXWmPs0Y6/d2FYwUNotKAWyLch7g0ASZJn/KHHcHZQ163A==", "requires": { "ccount": "^1.0.0", "is-alphanumeric": "^1.0.0", @@ -9825,12 +8022,12 @@ }, "dependencies": { "hosted-git-info": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.4.tgz", - "integrity": "sha512-4oT62d2jwSDBbLLFLZE+1vPuQ1h8p9wjrJ8Mqx5TjsyWmBMV5B13eJqn8pvluqubLf3cJPTfiYCIwNwDNmzScQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-3.0.5.tgz", + "integrity": "sha512-i4dpK6xj9BIpVOTboXIlKG9+8HMKggcrMX7WA24xZtKwX0TPelq/rbaS5rCKeNX8sJXZJGdSxpnEGtta+wismQ==", "dev": true, "requires": { - "lru-cache": "^5.1.1" + "lru-cache": "^6.0.0" } } } @@ -9904,21 +8101,21 @@ } }, "request-promise-core": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz", - "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", + "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", "dev": true, "requires": { - "lodash": "^4.17.15" + "lodash": "^4.17.19" } }, "request-promise-native": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.8.tgz", - "integrity": "sha512-dapwLGqkHtwL5AEbfenuzjTYg35Jd6KPytsC2/TLkVMz8rm+tNt72MGUWT1RP/aYawMpN6HqbNGBQaRcBtjQMQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", + "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", "dev": true, "requires": { - "request-promise-core": "1.1.3", + "request-promise-core": "1.1.4", "stealthy-require": "^1.1.1", "tough-cookie": "^2.3.3" }, @@ -10037,9 +8234,9 @@ "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==" }, "rxjs": { - "version": "6.5.5", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.5.5.tgz", - "integrity": "sha512-WfQI+1gohdf0Dai/Bbmk5L5ItH5tYqm3ki2c5GdWhKjalzjg93N3avFjVStyZZz+A2Em+ZxKH5bNghw9UeylGQ==", + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", + "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -10335,19 +8532,36 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, "slice-ansi": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", - "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "requires": { - "ansi-styles": "^3.2.0", - "astral-regex": "^1.0.0", - "is-fullwidth-code-point": "^2.0.0" + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" }, "dependencies": { - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" } } }, @@ -10825,9 +9039,9 @@ } }, "strip-json-comments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.0.tgz", - "integrity": "sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true }, "style-search": { @@ -10868,9 +9082,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -10896,49 +9110,14 @@ "dev": true }, "table": { - "version": "5.4.6", - "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", - "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/table/-/table-6.0.1.tgz", + "integrity": "sha512-fmr6168splcy/3XIvhSm5w6hYYOqyr3plAsd7OqoerzyoMnIpoxYuwrpdO2Cm22dh6KCnvirvigPrFZp+tdWFA==", "requires": { - "ajv": "^6.10.2", - "lodash": "^4.17.14", - "slice-ansi": "^2.1.0", - "string-width": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "requires": { - "ansi-regex": "^4.1.0" - } - } + "ajv": "^6.12.4", + "lodash": "^4.17.20", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.0" } }, "term-size": { @@ -10986,12 +9165,6 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, - "tlds": { - "version": "1.207.0", - "resolved": "https://registry.npmjs.org/tlds/-/tlds-1.207.0.tgz", - "integrity": "sha512-k7d7Q1LqjtAvhtEOs3yN14EabsNO8ZCoY6RESSJDB9lst3bTx3as/m1UuAeCKzYxiyhR1qq72ZPhpSf+qlqiwg==", - "dev": true - }, "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", @@ -11039,9 +9212,9 @@ } }, "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-2.1.0.tgz", + "integrity": "sha512-o3Qa6DGg1CEXshSdvWNX2sN4QHqg03SPq7U6jPXRahlQdl5dK8oXjkU/2/sGrnOZKeGV1zLSO8qPwyKklPPE7w==", "dev": true }, "to-regex": { @@ -11179,9 +9352,9 @@ } }, "typescript": { - "version": "3.9.6", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.6.tgz", - "integrity": "sha512-Pspx3oKAPJtjNwE92YS05HQoY7z2SFyOpHo9MqJor3BXAGNaPUs83CuVp9VISFkSjyRfiTpmKuAYGJB7S7hOxw==", + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz", + "integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==", "dev": true }, "unherit": { @@ -11194,9 +9367,9 @@ } }, "unified": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/unified/-/unified-9.0.0.tgz", - "integrity": "sha512-ssFo33gljU3PdlWLjNp15Inqb77d6JnJSfyplGJPT/a+fNRNyCBeveBAYJdO5khKdF6WVHa/yYCC7Xl6BDwZUQ==", + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/unified/-/unified-9.2.0.tgz", + "integrity": "sha512-vx2Z0vY+a3YoTj8+pttM3tiJHCwY5UFbYdiWrwBEbHmK8pvsPj2rtAX2BFfgXen8T39CJWblWRDT4L5WGXtDdg==", "requires": { "bail": "^1.0.0", "extend": "^3.0.0", @@ -11232,12 +9405,6 @@ "color-convert": "^2.0.1" } }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, "chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", @@ -11270,9 +9437,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -11306,9 +9473,9 @@ } }, "unified-lint-rule": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.5.tgz", - "integrity": "sha512-jOPr/fx8lTzqszEfh46p99jUMqgPlIZ8rNKllEepumISvgfj9lUq1c7BSpVihr0L1df3lkjVHAThRPS7dIyjYg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/unified-lint-rule/-/unified-lint-rule-1.0.6.tgz", + "integrity": "sha512-YPK15YBFwnsVorDFG/u0cVVQN5G2a3V8zv5/N6KN3TCG+ajKtaALcy7u14DCSrJI+gZeyYquFL9cioJXOGXSvg==", "dev": true, "requires": { "wrapped": "^1.0.1" @@ -11401,9 +9568,9 @@ } }, "unist-util-visit": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.2.tgz", - "integrity": "sha512-HoHNhGnKj6y+Sq+7ASo2zpVdfdRifhTgX2KTU3B/sO/TTlZchp7E3S4vjRzDJ7L60KmrCPsQkVK3lEF3cz36XQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", "requires": { "@types/unist": "^2.0.0", "unist-util-is": "^4.0.0", @@ -11411,9 +9578,9 @@ } }, "unist-util-visit-parents": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.0.2.tgz", - "integrity": "sha512-yJEfuZtzFpQmg1OSCyS9M5NJRrln/9FbYosH3iW0MG402QbdbaB8ZESwUv9RO6nRfLAKvWcMxCwdLWOov36x/g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.0.tgz", + "integrity": "sha512-0g4wbluTF93npyPrp/ymd3tCDTMnP0yo2akFD2FIBAYXq/Sga3lwaU1D8OYKbtpioaI6CkDcQ6fsMnmtzt7htw==", "requires": { "@types/unist": "^2.0.0", "unist-util-is": "^4.0.0" @@ -11460,9 +9627,9 @@ } }, "update-notifier": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", - "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.1.tgz", + "integrity": "sha512-9y+Kds0+LoLG6yN802wVXoIfxYEwh3FlZwzMwpCZp62S2i1/Jzeqb9Eeeju3NSHccGGasfGlK5/vEHbAifYRDg==", "dev": true, "requires": { "boxen": "^4.2.0", @@ -11528,9 +9695,9 @@ "dev": true }, "supports-color": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", - "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "requires": { "has-flag": "^4.0.0" @@ -11539,9 +9706,9 @@ } }, "uri-js": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", - "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.0.tgz", + "integrity": "sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g==", "requires": { "punycode": "^2.1.0" } @@ -11561,24 +9728,6 @@ "prepend-http": "^2.0.0" } }, - "url-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-5.0.0.tgz", - "integrity": "sha512-O08GjTiAFNsSlrUWfqF1jH0H1W3m35ZyadHrGv5krdnmPPoxP27oDTqux/579PtaroiSGm5yma6KT1mHFH6Y/g==", - "dev": true, - "requires": { - "ip-regex": "^4.1.0", - "tlds": "^1.203.0" - }, - "dependencies": { - "ip-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.1.0.tgz", - "integrity": "sha512-pKnZpbgCTfH/1NLIlOduP/V+WRXzC2MOz3Qo8xmxk8C5GudJLgK5QyLVXOSWy3ParAH7Eemurl3xjv/WXYFvMA==", - "dev": true - } - } - }, "use": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", @@ -11591,9 +9740,9 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" }, "uuid": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", - "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.0.tgz", + "integrity": "sha512-fX6Z5o4m6XsXBdli9g7DtWgAx+osMsRRZFKma1mIUsLCz6vRvv+pz5VNbyu9UEDzpMWulZfvpgb/cmDXVulYFQ==", "dev": true, "optional": true }, @@ -11603,9 +9752,9 @@ "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==" }, "v8-to-istanbul": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-4.1.4.tgz", - "integrity": "sha512-Rw6vJHj1mbdK8edjR7+zuJrpDtKIgNdAvTSAcpYfgMIw+u2dPDntD3dgN4XQFLU2/fvFQdzj+EeSGfd/jnY5fQ==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-5.0.1.tgz", + "integrity": "sha512-mbDNjuDajqYe3TXFk5qxcQy8L1msXNE37WTlLoqqpBfRsimbNcrlhQlDPntmECEcUvdC+AQ8CyMMf6EUx1r74Q==", "dev": true, "requires": { "@types/istanbul-lib-coverage": "^2.0.1", @@ -11651,9 +9800,9 @@ } }, "vfile": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.1.1.tgz", - "integrity": "sha512-lRjkpyDGjVlBA7cDQhQ+gNcvB1BGaTHYuSOcY3S7OhDmBtnzX95FhtZZDecSTDm6aajFymyve6S5DN4ZHGezdQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-4.2.0.tgz", + "integrity": "sha512-a/alcwCvtuc8OX92rqqo7PflxiCgXRFjdyoGVuYV+qbgCb0GgZJRvIgCD4+U/Kl1yhaRsaTwksF88xbPyGsgpw==", "requires": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", @@ -11663,9 +9812,9 @@ } }, "vfile-location": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.0.1.tgz", - "integrity": "sha512-yYBO06eeN/Ki6Kh1QAkgzYpWT1d3Qln+ZCtSbJqFExPl1S3y2qqotJQXoh6qEvl/jDlgpUJolBn3PItVnnZRqQ==" + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-3.1.0.tgz", + "integrity": "sha512-FCZ4AN9xMcjFIG1oGmZKo61PjwJHRVA+0/tPUP2ul4uIwjGGndIxavEMRpWn5p4xwm/ZsdXp9YNygf1ZyE4x8g==" }, "vfile-message": { "version": "2.0.4", @@ -11762,22 +9911,14 @@ "dev": true }, "whatwg-url": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.1.0.tgz", - "integrity": "sha512-vEIkwNi9Hqt4TV9RdnaBPNt+E2Sgmo3gePebCRgZ1R7g6d23+53zCTnuB0amKI4AXq6VM8jj2DUAa0S1vjJxkw==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.2.1.tgz", + "integrity": "sha512-ZmVCr6nfBeaMxEHALLEGy0LszYjpJqf6PVNQUQ1qd9Et+q7Jpygd4rGGDXgHjD8e99yLFseD69msHDM4YwPZ4A==", "dev": true, "requires": { "lodash.sortby": "^4.7.0", "tr46": "^2.0.2", - "webidl-conversions": "^5.0.0" - }, - "dependencies": { - "webidl-conversions": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-5.0.0.tgz", - "integrity": "sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==", - "dev": true - } + "webidl-conversions": "^6.1.0" } }, "which": { @@ -11888,9 +10029,9 @@ } }, "ws": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.0.tgz", - "integrity": "sha512-iFtXzngZVXPGgpTlP1rBqsUK82p9tKqsWRPg5L56egiljujJT3vGAYnHANvFxBieXrTFavhzhxW52jnaWV+w2w==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz", + "integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==", "dev": true }, "xdg-basedir": { @@ -11923,9 +10064,9 @@ "dev": true }, "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "yaml": { @@ -11934,9 +10075,9 @@ "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==" }, "yargs": { - "version": "15.3.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", - "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, "requires": { "cliui": "^6.0.0", @@ -11949,58 +10090,7 @@ "string-width": "^4.2.0", "which-module": "^2.0.0", "y18n": "^4.0.0", - "yargs-parser": "^18.1.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } + "yargs-parser": "^18.1.2" } }, "yargs-parser": { @@ -12010,13 +10100,6 @@ "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" - }, - "dependencies": { - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" - } } } } diff --git a/package.json b/package.json index b91ac5aec3..93719b3d76 100644 --- a/package.json +++ b/package.json @@ -112,14 +112,14 @@ "dependencies": { "@stylelint/postcss-css-in-js": "^0.37.2", "@stylelint/postcss-markdown": "^0.36.1", - "autoprefixer": "^9.8.2", + "autoprefixer": "^9.8.6", "balanced-match": "^1.0.0", "chalk": "^4.1.0", "cosmiconfig": "^7.0.0", "debug": "^4.1.1", "execall": "^2.0.0", "fast-glob": "^3.2.4", - "fastest-levenshtein": "^1.0.9", + "fastest-levenshtein": "^1.0.12", "file-entry-cache": "^5.0.1", "get-stdin": "^8.0.0", "global-modules": "^2.0.0", @@ -130,10 +130,10 @@ "import-lazy": "^4.0.0", "imurmurhash": "^0.1.4", "known-css-properties": "^0.19.0", - "lodash": "^4.17.19", + "lodash": "^4.17.20", "log-symbols": "^4.0.0", "mathml-tag-names": "^2.1.3", - "meow": "^7.0.1", + "meow": "^7.1.1", "micromatch": "^4.0.2", "normalize-selector": "^0.2.0", "postcss": "^7.0.32", @@ -155,7 +155,7 @@ "style-search": "^0.1.0", "sugarss": "^2.0.0", "svg-tags": "^1.0.0", - "table": "^5.4.6", + "table": "^6.0.1", "v8-compile-cache": "^2.1.1", "write-file-atomic": "^3.0.3" }, @@ -169,7 +169,7 @@ "@types/global-modules": "^2.0.0", "@types/globjoin": "^0.1.0", "@types/imurmurhash": "^0.1.1", - "@types/lodash": "^4.14.157", + "@types/lodash": "^4.14.161", "@types/micromatch": "^4.0.1", "@types/postcss-safe-parser": "^4.0.0", "@types/style-search": "^0.1.1", @@ -179,20 +179,20 @@ "benchmark": "^2.1.4", "common-tags": "^1.8.0", "del": "^5.1.0", - "eslint": "^7.2.0", + "eslint": "^7.7.0", "eslint-config-stylelint": "^12.0.0", - "got": "^11.3.0", + "got": "^11.5.2", "husky": "^4.2.5", - "jest": "^26.1.0", - "jest-circus": "^26.0.1", + "jest": "^26.4.2", + "jest-circus": "^26.4.2", "jest-preset-stylelint": "^3.0.0", "jest-watch-typeahead": "^0.6.0", - "lint-staged": "^10.2.11", - "np": "^6.2.4", + "lint-staged": "^10.2.13", + "np": "^6.5.0", "npm-run-all": "^4.1.5", "postcss-import": "^12.0.1", - "prettier": "^2.0.5", - "remark-cli": "^8.0.0", + "prettier": "^2.1.1", + "remark-cli": "^8.0.1", "typescript": "^3.9.6" }, "engines": { From fb4287c3c29920d621aa58c86c84eeb0c1f0acf8 Mon Sep 17 00:00:00 2001 From: jeddy3 Date: Mon, 31 Aug 2020 13:18:22 +0100 Subject: [PATCH 29/34] Prepare changelog --- CHANGELOG.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6055cf26cb..76d1585895 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,39 @@ All notable changes to this project are documented in this file. ## Head +- Deprecated: `*-blacklist`, `*-requirelist` and `*-whitelist` rules in favour of the new `*-disallowed-list`, `*-required-list` and `*-disallowed-list` ones ([#4845](https://github.com/stylelint/stylelint/pull/4845)): + - `at-rule-blacklist`. Use `at-rule-disallowed-list` instead. + - `at-rule-property-requirelist`. Use `at-rule-property-required-list` instead. + - `at-rule-whitelist`. Use `at-rule-allowed-list` instead. + - `comment-word-blacklist`. Use `comment-word-disallowed-list` instead. + - `declaration-property-unit-blacklist`. Use `declaration-property-unit-disallowed-list` instead. + - `declaration-property-unit-whitelist`. Use `declaration-property-unit-allowed-list` instead. + - `declaration-property-value-blacklist`. Use `declaration-property-value-disallowed-list` instead. + - `declaration-property-value-whitelist`. Use `declaration-property-value-allowed-list` instead. + - `function-blacklist`. Use `function-disallowed-list` instead. + - `function-url-scheme-blacklist`. Use `function-url-scheme-disallowed-list` instead. + - `function-url-scheme-whitelist`. Use `function-url-scheme-allowed-list` instead. + - `function-whitelist`. Use `function-allowed-list` instead. + - `media-feature-name-blacklist`. Use `media-feature-name-disallowed-list` instead. + - `media-feature-name-value-whitelist`. Use `media-feature-name-value-allowed-list` instead. + - `media-feature-name-whitelist`. Use `media-feature-name-allowed-list` instead. + - `property-blacklist`. Use `property-disallowed-list` instead. + - `property-whitelist`. Use `property-allowed-list` instead. + - `selector-attribute-operator-blacklist`. Use `selector-attribute-operator-disallowed-list` instead. + - `selector-attribute-operator-whitelist`. Use `selector-attribute-operator-allowed-list` instead. + - `selector-combinator-blacklist`. Use `selector-combinator-disallowed-list` instead. + - `selector-combinator-whitelist`. Use `selector-combinator-allowed-list` instead. + - `selector-pseudo-class-blacklist`. Use `selector-pseudo-class-disallowed-list` instead. + - `selector-pseudo-class-whitelist`. Use `selector-pseudo-class-allowed-list` instead. + - `selector-pseudo-element-blacklist`. Use `selector-pseudo-element-disallowed-list` instead. + - `selector-pseudo-element-whitelist`. Use `selector-pseudo-element-allowed-list` instead. + - `unit-blacklist`. Use `unit-disallowed-list` instead. + - `unit-whitelist`. Use `unit-allowed-list` instead. - Added: syntax object acceptance to `customSyntax` option ([#4839](https://github.com/stylelint/stylelint/pull/4839)). - Added: support for `*.cjs` config files ([#4905](https://github.com/stylelint/stylelint/pull/4905)). - Added: support for descriptions in stylelint command comments ([#4848](https://github.com/stylelint/stylelint/pull/4848)). - Added: `reportDescriptionlessDisables` flag ([#4907](https://github.com/stylelint/stylelint/pull/4907)). -- Added: `*-allowed-list`, `*-disallowed-list` and `*-required-list` new names for `*-whitelist`, `*-blacklist` and `*-requirelist` rules, respectively; the rules are aliased as their old names ([#4845](https://github.com/stylelint/stylelint/pull/4845)). +- Added: `reportDisables` secondary option ([#4897](https://github.com/stylelint/stylelint/pull/4897)). - Added: `*-no-vendor-prefix` autofix ([#4859](https://github.com/stylelint/stylelint/pull/4859)). - Added: `ignoreComments[]` to `comment-empty-line-before` ([#4841](https://github.com/stylelint/stylelint/pull/4841)). - Added: `ignoreContextFunctionalPseudoClasses` to `selector-max-id` ([#4835](https://github.com/stylelint/stylelint/pull/4835)). From 797cc842f6a99808778da13bf380cb435f4fce79 Mon Sep 17 00:00:00 2001 From: jeddy3 Date: Mon, 31 Aug 2020 13:23:25 +0100 Subject: [PATCH 30/34] Prepare 13.7.0 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 76d1585895..1b32a0f389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to this project are documented in this file. -## Head +## 13.7.0 - Deprecated: `*-blacklist`, `*-requirelist` and `*-whitelist` rules in favour of the new `*-disallowed-list`, `*-required-list` and `*-disallowed-list` ones ([#4845](https://github.com/stylelint/stylelint/pull/4845)): - `at-rule-blacklist`. Use `at-rule-disallowed-list` instead. From cf2f45fd0e165efdc7e5ab5ae3d5b46025e1baf1 Mon Sep 17 00:00:00 2001 From: jeddy3 Date: Mon, 31 Aug 2020 13:29:16 +0100 Subject: [PATCH 31/34] 13.7.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2e67869903..8faf149993 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "stylelint", - "version": "13.6.1", + "version": "13.7.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 93719b3d76..86c9d87b49 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "stylelint", - "version": "13.6.1", + "version": "13.7.0", "description": "A mighty, modern CSS linter.", "keywords": [ "css-in-js", From 6697b1e6477073cccf15857d9645c4005523d1cd Mon Sep 17 00:00:00 2001 From: Eugene Date: Tue, 1 Sep 2020 15:38:16 +0700 Subject: [PATCH 32/34] Update CHANGELOG.md (#4916) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b32a0f389..6468ace244 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project are documented in this file. ## 13.7.0 -- Deprecated: `*-blacklist`, `*-requirelist` and `*-whitelist` rules in favour of the new `*-disallowed-list`, `*-required-list` and `*-disallowed-list` ones ([#4845](https://github.com/stylelint/stylelint/pull/4845)): +- Deprecated: `*-blacklist`, `*-requirelist` and `*-whitelist` rules in favour of the new `*-disallowed-list`, `*-required-list` and `*-allowed-list` ones ([#4845](https://github.com/stylelint/stylelint/pull/4845)): - `at-rule-blacklist`. Use `at-rule-disallowed-list` instead. - `at-rule-property-requirelist`. Use `at-rule-property-required-list` instead. - `at-rule-whitelist`. Use `at-rule-allowed-list` instead. From c287bd87a3486bd98f7f8bd831b6103f47a3fe91 Mon Sep 17 00:00:00 2001 From: Jennifer Thakar Date: Tue, 1 Sep 2020 12:53:45 -0700 Subject: [PATCH 33/34] Fix double-slash disable comments when followed by another comment (#4913) Fixes #4911. --- lib/__tests__/disableRanges.test.js | 48 +++++++++++++++++++++++++++++ lib/assignDisabledRanges.js | 6 ++++ 2 files changed, 54 insertions(+) diff --git a/lib/__tests__/disableRanges.test.js b/lib/__tests__/disableRanges.test.js index d30a669b82..cef906a581 100644 --- a/lib/__tests__/disableRanges.test.js +++ b/lib/__tests__/disableRanges.test.js @@ -781,6 +781,54 @@ it('SCSS // disable next-line comment (with multi-line description)', () => { }); }); +it('SCSS // disable comment (with // comment after blank line)', () => { + const scssSource = `a { + // stylelint-disable declaration-no-important + + // Unrelated + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + }, + ], + }); + }); +}); + +it('SCSS /* disable comment (with // comment after blank line)', () => { + const scssSource = `a { + /* stylelint-disable declaration-no-important */ + + // Unrelated + color: pink !important; + }`; + + return postcss() + .use(assignDisabledRanges) + .process(scssSource, { syntax: scss, from: undefined }) + .then((result) => { + expect(result.stylelint.disabledRanges).toEqual({ + all: [], + 'declaration-no-important': [ + { + start: 2, + strictStart: true, + }, + ], + }); + }); +}); + it('Less // line-disabling comment (with description)', () => { const lessSource = `a { color: pink !important; // stylelint-disable-line declaration-no-important -- Description diff --git a/lib/assignDisabledRanges.js b/lib/assignDisabledRanges.js index 9405207f00..d57043e059 100644 --- a/lib/assignDisabledRanges.js +++ b/lib/assignDisabledRanges.js @@ -69,6 +69,7 @@ module.exports = function (root, result) { } else if (isInlineComment(comment)) { const fullComment = comment.clone(); let next = comment.next(); + let lastLine = (comment.source && comment.source.end && comment.source.end.line) || 0; while (next && next.type === 'comment') { /** @type {PostcssComment} */ @@ -76,6 +77,10 @@ module.exports = function (root, result) { if (!isInlineComment(current)) break; + const currentLine = (current.source && current.source.end && current.source.end.line) || 0; + + if (lastLine + 1 !== currentLine) break; + fullComment.text += `\n${current.text}`; if (fullComment.source && current.source) { @@ -84,6 +89,7 @@ module.exports = function (root, result) { inlineEnd = current; next = current.next(); + lastLine = currentLine; } checkComment(fullComment); } else { From 0be0e11ba1998dfb01385d76eb3ef896c6020fa6 Mon Sep 17 00:00:00 2001 From: Richard Hallows Date: Tue, 1 Sep 2020 20:56:08 +0100 Subject: [PATCH 34/34] Update CHANGELOG.md --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6468ace244..6be16ab022 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project are documented in this file. +## Head + +- Fixed: double-slash disable comments when followed by another comment ([#4913](https://github.com/stylelint/stylelint/pull/4913)). + ## 13.7.0 - Deprecated: `*-blacklist`, `*-requirelist` and `*-whitelist` rules in favour of the new `*-disallowed-list`, `*-required-list` and `*-allowed-list` ones ([#4845](https://github.com/stylelint/stylelint/pull/4845)):