diff --git a/.gitignore b/.gitignore index 3c3629e..37d7e73 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +.env diff --git a/README.md b/README.md index d5a0100..4ef9b96 100644 --- a/README.md +++ b/README.md @@ -58,18 +58,213 @@ While configuration is not required, it's recommended you enable support for ES2 JavaScript has many problematic and difficult to understand syntax features that have been replaced by newer features. Migrating to new features can drastically improve the readability, safety, and consistency of JavaScript. -- Use ES classes with `class` instead of constructor functions with `function`. -- Use ES modules instead of globals or `"use strict"`. -- Replace `var` with `const` if you don't need to reassign the variable, and `let` if you do. -- Replace `for (const i = 0; i < array.length; i++)` and `for (const value in array)` with `for (const value of array)`. -- Only use `` for string concatenation and + for addition. -- Use spread arguments like `...args` instead of `arguments`. -- Prefer Promises over callbacks when using async errors. -- Prefer `async`/`await` over `.then()` to use Promises. -- Don't give `parseInt()` a radix, it properly defaults to 10 on modern browsers. -- Don't assign `this` to a variable, use arrow functions or `.bind()` to avoid shadowing. -- Use `===` and `!==` instead of `==` and `!=`. -- Use `fetch` or a third party library to make requests in browsers instead of `XMLHTTPRequest`. `undici` is a good alternative for Node. +#### Replace constructor functions with classes + +```js +// ❌ +function Animal() {} +Animal.prototype.speak = function () { + return this +} + +// ✅ +class Animal { + speak() { + return this + } +} +``` + +#### Replace globals and CJS modules with ES modules (`no-implicit-globals`) + +The ES module standard makes it easy to safely reuse JavaScript code across files without leaking into the global scope, and enables useful tooling features like tree shaking and loaders. + +```js +// ❌ globals +window.greeting = "Hello, world!" + +// ❌ CJS +exports.greeting = "Hello, world!" + +// ✅ ES +export const greeting = "Hello, world!" +``` + +#### Replace `var` with `let`/`const` (`no-const-assign`, `no-var`, `prefer-const`) + +Variables created with `var` are hoisted to the nearest function, which can cause confusing behavior with the order of accessing variables and variables overriding each other in nearby scopes. `let` and `const` replace `var` with more predictable block scoping (typical with other programming languages). `const` should be preferred if you don't need to reassign the variable, otherwise use `let`. + +```js +// ❌ +var greeting = "Hello, world!" +var enabled = true +enabled = false + +// ✅ +const greeting = "Hello, world!" +let enabled = true +enabled = false +``` + +#### Use iteration with `for` + +C-style `for` loops are often unnecessarily complicated and error prone for basic iteration. `for...of` can replace it in most cases, and in other cases you should prefer other iteration operators or methods. + +```js +// ❌ +for (const i = 0; i < array.length; i++) { + console.log(array[i]) +} + +// ✅ +for (const value of array) { + console.log(value) +} +``` + +#### Replace `for...in` with `for...of` (`no-restricted-syntax`) + +Unfortunately `for...in` loops include the entire prototype chain, not just iterable items in an object. This can cause confusing behavior, like logging methods of a custom array type when you only want to log array items. `for...of` is similar, but it uses iterators to only loop over iterable items. + +```js +// ❌ +for (const value in array) + +// ✅ +for (const value of array) +``` + +#### Replace string concatenation with template literals (`prefer-template`) + +`+` can have ambiguous behavior if it's used between strings and numbers interchangeably. To avoid bugs and unwanted formatting, it's better to use template literal syntax (which also allows for custom templates) for strings and exclusively use `+` for math. + +```js +// ❌ +const name = "world" +console.log("Hello, " + name + "!") + +// ✅ +const name = "world" +console.log(`Hello, ${name}!`) +``` + +#### Replace the `arguments` keyword with spread arguments (`prefer-rest-params`) + +`arguments` used to be the only way to get a variable number of arguments from a function dynamically, but it isn't supported in arrow functions and confusingly is not an actual Array object. The spread argument (`...`) solves this issue and works with both `function` and arrow functions. + +```js +// ❌ +function joinWords() { + return Array.from(arguments).join(" ") +} + +// ✅ +function joinWords(...args) { + return args.join(" ") +} +``` + +#### Prefer Promises over callbacks when using async errors + +Originally, callbacks were the only basic primitive for asyncronous operations in JavaScript. However, chaining together asyncronous operations with multiple callbacks can often result in messy indentation. Callbacks also don't necessarily have consistent error handling, making error handling logic repetitive and easy to misuse. Promises on the other hand are objects that represent a future value, running listeners when complete. This makes asyncronous data processing and error handling easier and less error-prone. + +```js +// ❌ +function getFirstResult(callback) { + getResults((error, results) { + if (error) { + callback(error) + } else { + callback(null,results[0]) + } + }) +} + +// ✅ +async function getFirstResult() { + const results = await getResults() + return results[0] +} +``` + +#### Prefer `async`/`await` over `.then()` to use Promises (`no-restricted-properties`) + +`async` functions allow for more convenient usage of Promise values without manually nesting or chaining Promises. Instead of using `.then()` to wait for a Promise to resolve and `.catch()` to handle errors, use the Promise in an `async` function with `await` with an ordinary `try`/`catch` clause for error handling (each Promise chain should have at least one handler). + +```js +// ❌ +function getExample() { + return fetch("https://example.com") + .then((response) => response.text()) + .catch((error) => console.error(error)) +} + +// ✅ +async function getExample() { + try { + const response = await fetch("https://example.com") + return response.text() + } catch (error) { + console.error(error) + } +} +``` + +#### Use `parseInt()` without a radix for base 10 + +Modern JavaScript specs require the radix/base of integer parsing to always be 10, so defensively passing `10` as the second argument is no longer necessary. + +```js +// ❌ +const integer = parseInt(string, 10) + +// ✅ +const integer = parseInt(string) +``` + +#### Don't assign `this` to a variable, use arrow functions or `.bind()` to avoid shadowing (`consistent-this`) + +```js +// ❌ +const that = this +const processedItems = items.map(function (item) { + return that.processItem(item) +}) + +// ✅ +const processedItems = items.map((item) => this.processItem(item)) +``` + +#### Use strict mode in all files (`strict`) + +Strict mode is automatically enabled in ES modules, so you only need `"use strict"` at the top of files that don't use `import` or `export`. + +```js +// ❌ +console.log("Hello, world!") + +// ✅ file +import greeting from "./greeting" // or if you don't have imports/exports, use "use-strict" on the first line +console.log(greeting) +``` + +#### Use `===` and `!==` instead of `==` and `!=` (`eqeqeq`) + +JavaScript's default comparison operators (`==` and `!=`) can compare different types of primitives, leading to confusion behavior and bugs from unexpected types and other coercion issues. It's better to explicitly use `===` and `!==`, which check to see if values are equivalent and of the same type. + +```js +// ❌ +nameOrId == 1 + +// ✅ +nameOrId === 1 +``` + +#### Use `fetch` instead of `XMLHTTPRequest` (`no-restricted-globals`) + +`XMLHTTPRequest` is a fairly old API for making HTTP/AJAX requests in browsers. It relies on multiple events and callbacks, making it more difficult to learn and harder to reuse. `fetch` is a more modern alternative that's entirely based on Promises, and therefore has better data management and error handling (see above). + +If you're using Node 18+, you can use `fetch` globally. If not, we recommend `undici` as Node's legacy HTTP client is also fairly complex. ### Improve semantics @@ -87,11 +282,22 @@ Some features have potentially dangerous or confusing usages and can be improved Some features are too dangerous or confusing to be worth using. - Avoid `eval()`, use other techniques to make code dynamic. -- Avoid `continue`, use conditional statements inside blocks instead. -- Avoid typed wrappers (Boolean/Number/String/Object/Array), use literals like `false`, `0`, `''`, `{}`, and `[]` instead. -- Avoid `with`, manually read properties or use destructuring instead. -- Avoid `void`, it's better to use `undefined` or break up multiple statements instead. -- Avoid bitwise operators like `&` and `|`, they're usually confused with the `&&` and `||` (and/or) operators, and bitwise operations are not very performant or useful in JavaScript. +- Avoid `continue`, use conditional statements inside blocks instead. (`no-continue`) +- Avoid typed wrappers (Boolean/Number/String/Object/Array), use literals like `false`, `0`, `''`, `{}`, and `[]` instead. (`no-new-wrappers`) +- Avoid `with`, manually read properties or use destructuring instead. (`no-with`) +- Avoid `void`, it's better to use `undefined` or break up multiple statements instead. (`no-void`) +- Avoid bitwise operators like `&` and `|`, they're usually confused with the `&&` and `||` (and/or) operators, and bitwise operations are not very performant or useful in JavaScript. (`no-bitwise`) +- Avoid labels (`no-labels`) + +### Follow best practices + +- Always define a getter for each setter (`accessor-pairs`) +- Return values in Array methods (`array-callback-return`) +- Always use `this` in class methods (`class-methods-use-this`) +- Consistently return values (`consistent-return`) +- Always provide a `default` in `case` as a fallback (`default-case`) +- Avoid using `[]` unnecessary when indexing (`dot-notation`) +- Use one class per file (`max-classes-per-file`) ## Inspiration diff --git a/package.json b/package.json index 86d11b9..e888308 100644 --- a/package.json +++ b/package.json @@ -10,10 +10,14 @@ ], "repository": "nickmccurdy/eslint-config-modern", "scripts": { - "test": "eslint ." + "test": "eslint .", + "rules": "node rules" }, "devDependencies": { + "@notionhq/client": "^2.1.1", + "dotenv": "^16.0.1", "eslint": "~6.2.0", + "eslint-config-prettier": "^6.11.0", "prettier": "^2.7.1", "prettier-config-nick": "^1.0.2" }, diff --git a/rules.js b/rules.js new file mode 100644 index 0000000..5a1d779 --- /dev/null +++ b/rules.js @@ -0,0 +1,91 @@ +/* eslint camelcase: ["error", { allow: ["_id$"] }] */ +"use strict" +const config = require(".") +const { Linter } = require("eslint") +const prettier = require("eslint-config-prettier") +const { readFile } = require("fs/promises") +const { Client } = require("@notionhq/client") +require("dotenv/config") + +const notion = new Client({ + auth: process.env.NOTION_TOKEN, +}) + +;(async () => { + const markdown = await readFile("README.md", "utf8") + const headingMatches = markdown.matchAll(/\((?`.*`)\)$/gmu) + const documentedRules = Array.from(headingMatches).flatMap( + ({ groups: { rules } }) => { + const ruleMatches = rules.matchAll(/`(?[a-z-]+)`/gu) + return Array.from(ruleMatches).map(({ groups: { rule } }) => rule) + }, + ) + + const rules = Object.fromEntries( + Array.from(new Linter().getRules().entries()).map(([rule, { meta }]) => [ + rule, + { + category: meta.docs.category, + status: + prettier.rules[rule] === "off" + ? "Prettier" + : documentedRules.includes(rule) + ? "Documented" + : rule in config.rules + ? "Implemented" + : "To-do", + docs: `https://eslint.org/docs/latest/rules/${rule}`, + }, + ]), + ) + + console.table(rules) + + const { id } = await notion.databases.create({ + parent: { + page_id: process.env.NOTION_PAGE, + }, + title: [{ text: { content: "ESLint Rules" } }], + properties: { + ID: { title: {} }, + Category: { + select: { + options: [ + { name: "Best Practices" }, + { name: "Stylistic Issues" }, + { name: "ECMAScript 6" }, + { name: "Node.js and CommonJS" }, + { name: "Possible Errors" }, + { name: "Variables" }, + { name: "Strict Mode" }, + ], + }, + }, + Status: { + select: { + options: [ + { name: "To-do" }, + { name: "Implemented" }, + { name: "Documented" }, + { name: "Prettier" }, + ], + }, + }, + Docs: { url: {} }, + }, + }) + + for (const [rule, { category, status, docs }] of Object.entries(rules)) { + notion.pages.create({ + parent: { + database_id: id, + }, + properties: { + ID: { title: [{ text: { content: rule } }] }, + Category: { select: { name: category } }, + Status: { select: { name: status } }, + Docs: { url: docs }, + }, + }) + } +})() diff --git a/yarn.lock b/yarn.lock index 834fd11..d9c9dad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -23,6 +23,27 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@notionhq/client@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@notionhq/client/-/client-2.1.1.tgz#3dfe84054d27fb95144ff26f1fe373adebb0e362" + integrity sha512-2B5riO5pk+M4HrKd2eL8bWTdKvfsTSLU8UU19F+uq0NUq5DPvG2iCTNO+l5l+M3DU2BZLK1SZzLxHa+8NaOkIw== + dependencies: + "@types/node-fetch" "^2.5.10" + node-fetch "^2.6.1" + +"@types/node-fetch@^2.5.10": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + +"@types/node@*": + version "18.6.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.3.tgz#4e4a95b6fe44014563ceb514b2598b3e623d1c98" + integrity sha512-6qKpDtoaYLM+5+AFChLhHermMQxc3TOEFIDzrZLPRGHPrLEwqFkkT5Kx3ju05g6X7uDPazz3jHbKPX0KzCjntg== + acorn-jsx@^5.2.0: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -77,6 +98,11 @@ astral-regex@^1.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -133,6 +159,13 @@ color-name@1.1.3: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -161,6 +194,11 @@ deep-is@~0.1.3: resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + doctrine@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" @@ -168,6 +206,11 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" +dotenv@^16.0.1: + version "16.0.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.0.1.tgz#8f8f9d94876c35dac989876a5d3a82a267fdce1d" + integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== + emoji-regex@^7.0.1: version "7.0.3" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" @@ -178,6 +221,13 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== +eslint-config-prettier@^6.11.0: + version "6.15.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.15.0.tgz#7f93f6cb7d45a92f1537a70ecc06366e1ac6fed9" + integrity sha512-a1+kOYLR8wMGustcgAjdydMsQ2A/2ipRPwRKUmfYaSxc9ZPcrku080Ctl6zrZzZNs/U82MjSv+qKREkoq3bJaw== + dependencies: + get-stdin "^6.0.0" + eslint-scope@^5.0.0: version "5.1.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" @@ -336,6 +386,15 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -346,6 +405,11 @@ functional-red-black-tree@^1.0.1: resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== +get-stdin@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" + integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g== + glob-parent@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" @@ -490,6 +554,18 @@ lodash@^4.17.12, lodash@^4.17.14: resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + mimic-fn@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" @@ -534,6 +610,13 @@ nice-try@^1.0.4: resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== +node-fetch@^2.6.1: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -760,6 +843,11 @@ tmp@^0.0.33: dependencies: os-tmpdir "~1.0.2" +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" @@ -784,6 +872,19 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + which@^1.2.9: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"