diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index c307718..0000000 --- a/.eslintignore +++ /dev/null @@ -1,6 +0,0 @@ -/coverage -/dist -/node_modules -/test/fixtures -/test/output -/types/**/* diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 399d99d..0000000 --- a/.eslintrc.js +++ /dev/null @@ -1,24 +0,0 @@ -module.exports = { - root: true, - extends: [ - '@webpack-contrib/eslint-config-webpack/rules/possible-errors', - '@webpack-contrib/eslint-config-webpack/rules/best-practices', - '@webpack-contrib/eslint-config-webpack/rules/variables', - '@webpack-contrib/eslint-config-webpack/rules/node', - '@webpack-contrib/eslint-config-webpack/rules/stylistic-issues', - '@webpack-contrib/eslint-config-webpack/rules/es2015', - 'prettier', - ], - parserOptions: { - ecmaVersion: 2018, - env: { - es6: true, - jest: true, - }, - sourceType: 'module', - }, - rules: { - strict: 'error', - 'global-require': 'off', - }, -}; diff --git a/.gitignore b/.gitignore index d286487..ec1bd8c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ yarn-debug.log* /local /reports /node_modules -/test/output +/test/outputs .DS_Store Thumbs.db diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index 4f14003..0000000 --- a/.prettierrc.js +++ /dev/null @@ -1 +0,0 @@ -module.exports = { singleQuote: true }; diff --git a/README.md b/README.md index ee109ff..d76fdae 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ pnpm add -D eslint Then add the plugin to your webpack configuration. For example: ```js -const ESLintPlugin = require('eslint-webpack-plugin'); +const ESLintPlugin = require("eslint-webpack-plugin"); module.exports = { // ... @@ -111,7 +111,7 @@ Specify the path to the cache location. Can be a file or a directory. - Type: ```ts -type configType = 'flat' | 'eslintrc'; +type configType = "flat" | "eslintrc"; ``` - Default: `flat` @@ -154,7 +154,7 @@ If the `eslintPath` is a folder like a official ESlint, or specify a `formatter` - Type: ```ts -type extensions = string | Array; +type extensions = string | string[]; ``` - Default: `'js'` @@ -166,7 +166,7 @@ Specify file extensions that should be checked. - Type: ```ts -type exclude = string | Array; +type exclude = string | string[]; ``` - Default: `'node_modules'` @@ -178,7 +178,7 @@ Specify the files/directories to exclude. Must be relative to `options.context`. - Type: ```ts -type resourceQueryExclude = RegExp | Array; +type resourceQueryExclude = RegExp | RegExp[]; ``` - Default: `[]` @@ -190,7 +190,7 @@ Specify the resource query to exclude. - Type: ```ts -type files = string | Array; +type files = string | string[]; ``` - Default: `null` @@ -218,10 +218,12 @@ Will enable [ESLint autofix feature](https://eslint.org/docs/developer-guide/nod - Type: ```ts -type formatter = string| ( - results: Array, - data?: import('eslint').ESLint.LintResultData | undefined -) => string +type formatter = + | string + | (( + results: import("eslint").ESLint.LintResult[], + data?: import("eslint").ESLint.LintResultData | undefined, + ) => string); ``` - Default: `'stylish'` @@ -333,8 +335,8 @@ type outputReport = | ( | string | (( - results: Array, - data?: import('eslint').ESLint.LintResultData | undefined, + results: import("eslint").ESLint.LintResult[], + data?: import("eslint").ESLint.LintResultData | undefined, ) => string) ) | undefined; diff --git a/babel.config.js b/babel.config.js index ac2d184..471d337 100644 --- a/babel.config.js +++ b/babel.config.js @@ -7,10 +7,10 @@ module.exports = (api) => { return { presets: [ [ - '@babel/preset-env', + "@babel/preset-env", { targets: { - node: '14.15.0', + node: "14.15.0", }, }, ], diff --git a/commitlint.config.js b/commitlint.config.js index 0664f00..86a8e2d 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,8 +1,8 @@ module.exports = { - extends: ['@commitlint/config-conventional'], + extends: ["@commitlint/config-conventional"], rules: { - 'header-max-length': [0], - 'body-max-line-length': [0], - 'footer-max-line-length': [0], + "header-max-length": [0], + "body-max-line-length": [0], + "footer-max-line-length": [0], }, }; diff --git a/eslint.config.mjs b/eslint.config.mjs new file mode 100644 index 0000000..c227975 --- /dev/null +++ b/eslint.config.mjs @@ -0,0 +1,8 @@ +import { defineConfig } from "eslint/config"; +import configs from "eslint-config-webpack/configs.js"; + +export default defineConfig([ + { + extends: [configs["recommended-dirty"]], + }, +]); diff --git a/husky.config.js b/husky.config.js index 4c2ec3a..6cf9b3f 100644 --- a/husky.config.js +++ b/husky.config.js @@ -1,6 +1,6 @@ module.exports = { hooks: { - 'pre-commit': 'lint-staged', - 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS', + "pre-commit": "lint-staged", + "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", }, }; diff --git a/jest.config.js b/jest.config.js index df8cb27..97956b8 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,6 +1,7 @@ module.exports = { collectCoverage: true, - testEnvironment: 'node', + collectCoverageFrom: ["src/**/*"], + testEnvironment: "node", testTimeout: 60000, - transformIgnorePatterns: ['node_modules/(?!(arrify)/)'], + transformIgnorePatterns: ["node_modules/(?!(arrify)/)"], }; diff --git a/lint-staged.config.js b/lint-staged.config.js index a234f45..43f9f2a 100644 --- a/lint-staged.config.js +++ b/lint-staged.config.js @@ -1,4 +1,4 @@ module.exports = { - '*.js': ['eslint --fix', 'prettier --write', 'cspell'], - '*.{json,md,yml,css,ts}': ['prettier --write'], + "*.js": ["eslint --fix", "prettier --write", "cspell"], + "*.{json,md,yml,css,ts}": ["prettier --write"], }; diff --git a/package-lock.json b/package-lock.json index 0a5a256..092d6da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,28 +22,36 @@ "@babel/preset-env": "^7.27.2", "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", + "@eslint/js": "^9.33.0", + "@eslint/markdown": "^7.0.0", + "@stylistic/eslint-plugin": "^5.2.3", "@types/fs-extra": "^11.0.4", "@types/micromatch": "^4.0.9", "@types/node": "^22.15.30", "@types/normalize-path": "^3.0.2", - "@types/webpack": "^5.28.5", - "@webpack-contrib/eslint-config-webpack": "^3.0.0", - "babel-jest": "^30.0.0", "chokidar": "^4.0.3", "cross-env": "^7.0.3", "cspell": "^8.19.4", "del": "^8.0.0", "del-cli": "^6.0.0", - "eslint": "^9.28.0", - "eslint-config-prettier": "^10.1.5", + "eslint": "^9.33.0", + "eslint-config-prettier": "^10.1.8", + "eslint-config-webpack": "^4.6.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jsdoc": "^54.0.0", + "eslint-plugin-n": "^17.21.0", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-unicorn": "^60.0.0", "fs-extra": "^11.3.0", "husky": "^9.1.7", "jest": "^30.0.0", "lint-staged": "^15.5.2", "npm-run-all": "^4.1.5", - "prettier": "^3.5.3", + "prettier": "^3.6.2", "standard-version": "^9.5.0", - "typescript": "^5.8.3", + "typescript": "^5.5.3", + "typescript-eslint": "^8.39.1", "webpack": "^5.99.9" }, "engines": { @@ -1032,6 +1040,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-classes/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/plugin-transform-computed-properties": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", @@ -1863,6 +1881,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/types": { "version": "7.27.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.6.tgz", @@ -2776,6 +2804,23 @@ "tslib": "^2.4.0" } }, + "node_modules/@es-joy/jsdoccomment": { + "version": "0.52.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.52.0.tgz", + "integrity": "sha512-BXuN7BII+8AyNtn57euU2Yxo9yA/KUDNzrpXyi3pfqKmBhhysR6ZWOebFh3vyPoqA3/j1SOvGgucElMGwlXing==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.34.1", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~4.1.0" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", @@ -2819,9 +2864,9 @@ } }, "node_modules/@eslint/config-array": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.20.1.tgz", - "integrity": "sha512-OL0RJzC/CBzli0DrrR31qzj6d6i6Mm3HByuhflhl4LOBiWxN+3i6/t/ZQQNii4tjksXi8r2CRW1wMpWA2ULUEw==", + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2834,9 +2879,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.3.tgz", - "integrity": "sha512-u180qk2Um1le4yf0ruXH3PYFeEZeYC3p/4wCTKrr2U1CmGdzGi3KtY0nuPDH48UJxlKCC5RDzbcbh4X0XlqgHg==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -2844,9 +2889,9 @@ } }, "node_modules/@eslint/core": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", - "integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -2938,9 +2983,9 @@ "license": "MIT" }, "node_modules/@eslint/js": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.28.0.tgz", - "integrity": "sha512-fnqSjGWd/CoIp4EXIxWVK/sHA6DOHN4+8Ix2cX5ycOY7LG0UY8nHCU5pIp2eaE1Mc7Qd8kHspYNzYXT2ojPLzg==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.33.0.tgz", + "integrity": "sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==", "dev": true, "license": "MIT", "engines": { @@ -2950,6 +2995,29 @@ "url": "https://eslint.org/donate" } }, + "node_modules/@eslint/markdown": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/@eslint/markdown/-/markdown-7.1.0.tgz", + "integrity": "sha512-Y+X1B1j+/zupKDVJfkKc8uYMjQkGzfnd8lt7vK3y8x9Br6H5dBuhAfFrQ6ff7HAMm/1BwgecyEiRFkYCWPRxmA==", + "dev": true, + "license": "MIT", + "workspaces": [ + "examples/*" + ], + "dependencies": { + "@eslint/core": "^0.15.1", + "@eslint/plugin-kit": "^0.3.4", + "github-slugger": "^2.0.0", + "mdast-util-from-markdown": "^2.0.2", + "mdast-util-frontmatter": "^2.0.1", + "mdast-util-gfm": "^3.1.0", + "micromark-extension-frontmatter": "^2.0.0", + "micromark-extension-gfm": "^3.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/object-schema": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", @@ -2961,32 +3029,19 @@ } }, "node_modules/@eslint/plugin-kit": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.2.tgz", - "integrity": "sha512-4SaFZCNfJqvk/kenHpI8xvN42DMaoycy4PzKc5otHxRswww1kAt82OlBuwRVLofCACCTZEcla2Ydxv8scMXaTg==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^0.15.0", + "@eslint/core": "^0.15.2", "levn": "^0.4.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.0.tgz", - "integrity": "sha512-b7ePw78tEWWkpgZCDYkbqDOP8dmM6qe+AOC6iuJqlq1R/0ahMAeH3qynpnqKFGkMltrp44ohV4ubGyvLX28tzw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, "node_modules/@humanfs/core": { "version": "0.19.1", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", @@ -4196,6 +4251,13 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, "node_modules/@sinclair/typebox": { "version": "0.34.33", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.34.33.tgz", @@ -4236,6 +4298,27 @@ "@sinonjs/commons": "^3.0.1" } }, + "node_modules/@stylistic/eslint-plugin": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@stylistic/eslint-plugin/-/eslint-plugin-5.2.3.tgz", + "integrity": "sha512-oY7GVkJGVMI5benlBDCaRrSC1qPasafyv5dOBLLv5MTilMGnErKhO6ziEfodDDIZbo5QxPUNW360VudJOFODMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/types": "^8.38.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "estraverse": "^5.3.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": ">=9.0.0" + } + }, "node_modules/@tybys/wasm-util": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", @@ -4309,6 +4392,16 @@ "@types/node": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/eslint": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", @@ -4377,6 +4470,13 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/jsonfile": { "version": "6.1.4", "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", @@ -4387,6 +4487,16 @@ "@types/node": "*" } }, + "node_modules/@types/mdast": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", + "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "*" + } + }, "node_modules/@types/micromatch": { "version": "4.0.9", "resolved": "https://registry.npmjs.org/@types/micromatch/-/micromatch-4.0.9.tgz", @@ -4404,6 +4514,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.15.31", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.31.tgz", @@ -4434,17 +4551,12 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/webpack": { - "version": "5.28.5", - "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-5.28.5.tgz", - "integrity": "sha512-wR87cgvxj3p6D0Crt1r5avwqffqPXUkNlnQ1mjU93G7gCuFjufZR4I6j8cz5g1F1tTYpfOOFvly+cmIQwL9wvw==", + "node_modules/@types/unist": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", + "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "tapable": "^2.2.0", - "webpack": "^5" - } + "license": "MIT" }, "node_modules/@types/yargs": { "version": "17.0.33", @@ -4461,6 +4573,277 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "license": "MIT" }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.39.1.tgz", + "integrity": "sha512-yYegZ5n3Yr6eOcqgj2nJH8cH/ZZgF+l0YIdKILSDjYFRjgYQMgv/lRjV5Z7Up04b9VYUondt8EPMqg7kTWgJ2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/type-utils": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.39.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.39.1.tgz", + "integrity": "sha512-pUXGCuHnnKw6PyYq93lLRiZm3vjuslIy7tus1lIQTYVK9bL8XBgJnCWm8a0KcTtHC84Yya1Q6rtll+duSMj0dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.39.1.tgz", + "integrity": "sha512-8fZxek3ONTwBu9ptw5nCKqZOSkXshZB7uAxuFF0J/wTMkKydjXCzqqga7MlFMpHi9DoG4BadhmTkITBcg8Aybw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.39.1", + "@typescript-eslint/types": "^8.39.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.39.1.tgz", + "integrity": "sha512-RkBKGBrjgskFGWuyUGz/EtD8AF/GW49S21J8dvMzpJitOF1slLEbbHnNEtAHtnDAnx8qDEdRrULRnWVx27wGBw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.39.1.tgz", + "integrity": "sha512-ePUPGVtTMR8XMU2Hee8kD0Pu4NDE1CN9Q1sxGSGd/mbOtGZDM7pnhXNJnzW63zk/q+Z54zVzj44HtwXln5CvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.39.1.tgz", + "integrity": "sha512-gu9/ahyatyAdQbKeHnhT4R+y3YLtqqHyvkfDxaBYk97EcbfChSJXyaJnIL3ygUv7OuZatePHmQvuH5ru0lnVeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.39.1.tgz", + "integrity": "sha512-7sPDKQQp+S11laqTrhHqeAbsCfMkwJMrV7oTDvtDds4mEofJYir414bYKUEb8YPUm9QL3U+8f6L6YExSoAGdQw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.39.1.tgz", + "integrity": "sha512-EKkpcPuIux48dddVDXyQBlKdeTPMmALqBUbEk38McWv0qVEZwOpVJBi7ugK5qVNgeuYjGNQxrrnoM/5+TI/BPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.39.1", + "@typescript-eslint/tsconfig-utils": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/visitor-keys": "8.39.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.39.1.tgz", + "integrity": "sha512-VF5tZ2XnUSTuiqZFXCZfZs1cgkdd3O/sSYmdo2EpSyDlC86UM/8YytTmKnehOW3TGAlivqTDT6bS87B/GQ/jyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.39.1", + "@typescript-eslint/types": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.39.1.tgz", + "integrity": "sha512-W8FQi6kEh2e8zVhQ0eeRnxdvIoOkAp/CPAahcNio6nO9dsIwb9b34z90KOlheoyuVf6LSOEdjlkxSkapNEc+4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.39.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, "node_modules/@ungap/structured-clone": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", @@ -4898,19 +5281,6 @@ "@xtuc/long": "4.2.2" } }, - "node_modules/@webpack-contrib/eslint-config-webpack": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@webpack-contrib/eslint-config-webpack/-/eslint-config-webpack-3.0.0.tgz", - "integrity": "sha512-3f0dwuTZ1JZpnoGQ6tAKBWluZKZZBXr1ADoaOAbPiW0OvSN7o0wXFLGyfw6J+fW756xIkZLZ8JDYP5zInIRvBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6.9.0 || >= 8.9.0" - }, - "peerDependencies": { - "eslint": ">= 5.0.0" - } - }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", @@ -5066,6 +5436,16 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + } + }, "node_modules/argparse": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", @@ -5100,6 +5480,29 @@ "dev": true, "license": "MIT" }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-timsort": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", @@ -5107,6 +5510,66 @@ "dev": true, "license": "MIT" }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arraybuffer.prototype.slice": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", @@ -5413,9 +5876,9 @@ } }, "node_modules/browserslist": { - "version": "4.25.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.0.tgz", - "integrity": "sha512-PJ8gYKeS5e/whHBh8xrwYK+dAvEj7JXtz6uTucnMRB8OiGTsKccFekoRrjajPBHV8oOY+2tI4uxeceSimKwMFA==", + "version": "4.25.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.1.tgz", + "integrity": "sha512-KGj0KoOMXLpSNkkEI6Z6mShmQy0bc1I+T7K9N81k4WWMrfz+6fQ6es80B/YLAeRoKvjYE1YSHHOW1qe9xIVzHw==", "dev": true, "funding": [ { @@ -5433,8 +5896,8 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001718", - "electron-to-chromium": "^1.5.160", + "caniuse-lite": "^1.0.30001726", + "electron-to-chromium": "^1.5.173", "node-releases": "^2.0.19", "update-browserslist-db": "^1.1.3" }, @@ -5462,6 +5925,19 @@ "dev": true, "license": "MIT" }, + "node_modules/builtin-modules": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/call-bind": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", @@ -5551,9 +6027,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001722", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001722.tgz", - "integrity": "sha512-DCQHBBZtiK6JVkAGw7drvAMK0Q0POD/xZvEmDp6baiMMP6QXXk9HpD6mNYBZWhOPG6LvIDb82ITqtWjhDckHCA==", + "version": "1.0.30001731", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz", + "integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==", "dev": true, "funding": [ { @@ -5571,6 +6047,17 @@ ], "license": "CC-BY-4.0" }, + "node_modules/ccount": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", + "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chalk": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", @@ -5600,6 +6087,13 @@ "url": "https://github.com/chalk/chalk-template?sponsor=1" } }, + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true, + "license": "MIT" + }, "node_modules/char-regex": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", @@ -5610,6 +6104,17 @@ "node": ">=10" } }, + "node_modules/character-entities": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", + "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -5637,9 +6142,9 @@ } }, "node_modules/ci-info": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.2.0.tgz", - "integrity": "sha512-cYY9mypksY8NRqgDB1XD1RiJL338v/551niynFTGkZOO2LHuB2OmOYxDIe/ttN9AHwrqdum1360G3ald0W9kCg==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.0.tgz", + "integrity": "sha512-l+2bNRMiQgcfILUi33labAZYIWlH1kWDp+ecNo5iisRKrbm0xcRyCww71/YU0Fkw0mAFpz9bJayXPjey6vkmaQ==", "dev": true, "funding": [ { @@ -5659,6 +6164,29 @@ "dev": true, "license": "MIT" }, + "node_modules/clean-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clean-regexp/-/clean-regexp-1.0.0.tgz", + "integrity": "sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/clean-regexp/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/clear-module": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/clear-module/-/clear-module-4.1.2.tgz", @@ -5879,6 +6407,16 @@ "node": ">= 6" } }, + "node_modules/comment-parser": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 12.0.0" + } + }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -7165,13 +7703,13 @@ "license": "MIT" }, "node_modules/core-js-compat": { - "version": "3.43.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.43.0.tgz", - "integrity": "sha512-2GML2ZsCc5LR7hZYz4AXmjQw8zuy2T//2QntwdnpuYI7jteT6GVYJL7F6C2C57R7gSYrcqVW3lAALefdbhBLDA==", + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz", + "integrity": "sha512-JepmAj2zfl6ogy34qfWtcE7nHKAJnKsQFRn++scjVS2bZFllwptzw61BZcZFYBPpUznLfAvh0LGhxKppk04ClA==", "dev": true, "license": "MIT", "dependencies": { - "browserslist": "^4.25.0" + "browserslist": "^4.25.1" }, "funding": { "type": "opencollective", @@ -7633,6 +8171,20 @@ "node": ">=0.10.0" } }, + "node_modules/decode-named-character-reference": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", + "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "character-entities": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/dedent": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.6.0.tgz", @@ -7769,6 +8321,16 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/detect-indent": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", @@ -7789,6 +8351,33 @@ "node": ">=8" } }, + "node_modules/devlop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", + "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", + "dev": true, + "license": "MIT", + "dependencies": { + "dequal": "^2.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/dot-prop": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", @@ -7905,9 +8494,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.166", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.166.tgz", - "integrity": "sha512-QPWqHL0BglzPYyJJ1zSSmwFFL6MFXhbACOCcsCdUMCkzPdS9/OIBVxg516X/Ado2qwAq8k0nJJ7phQPCqiaFAw==", + "version": "1.5.192", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.192.tgz", + "integrity": "sha512-rP8Ez0w7UNw/9j5eSXCe10o1g/8B1P5SM90PCCMVkIRQn2R0LEHWz4Eh9RnxkniuDe1W0cTSOB3MLlkTGDcuCg==", "dev": true, "license": "ISC" }, @@ -8103,6 +8692,19 @@ "node": ">= 0.4" } }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-to-primitive": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", @@ -8145,20 +8747,20 @@ } }, "node_modules/eslint": { - "version": "9.28.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.28.0.tgz", - "integrity": "sha512-ocgh41VhRlf9+fVpe7QKzwLj9c92fDiqOj8Y3Sd4/ZmVA4Btx4PlUYPq4pp9JDyupkf1upbEXecxL2mwNV7jPQ==", + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.33.0.tgz", + "integrity": "sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.20.0", - "@eslint/config-helpers": "^0.2.1", - "@eslint/core": "^0.14.0", + "@eslint/config-array": "^0.21.0", + "@eslint/config-helpers": "^0.3.1", + "@eslint/core": "^0.15.2", "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.28.0", - "@eslint/plugin-kit": "^0.3.1", + "@eslint/js": "9.33.0", + "@eslint/plugin-kit": "^0.3.5", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", @@ -8169,9 +8771,9 @@ "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.3.0", - "eslint-visitor-keys": "^4.2.0", - "espree": "^10.3.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -8205,10 +8807,39 @@ } } }, + "node_modules/eslint-compat-utils": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/eslint-compat-utils/-/eslint-compat-utils-0.5.1.tgz", + "integrity": "sha512-3z3vFexKIEnjHE3zCMRo6fn/e44U7T1khUjg+Hp0ZQMCigh28rALD0nPFBcGZuiLC5rLZa2ubQHDRln09JfU2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/eslint-compat-utils/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/eslint-config-prettier": { - "version": "10.1.5", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz", - "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==", + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", "dev": true, "license": "MIT", "bin": { @@ -8221,46 +8852,479 @@ "eslint": ">=7.0.0" } }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "node_modules/eslint-config-webpack": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-config-webpack/-/eslint-config-webpack-4.6.0.tgz", + "integrity": "sha512-EcOVuPRz5WGjZ3XgEpynvUoQbR4WCFosLTnCZjNTqLuISjix+RSrR2c0zp1r0jo3+BOhqcDNgbN5ZwD5ns3IAg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "detect-indent": "^7.0.1", + "jsonc-eslint-parser": "^2.4.0", + "semver": "^7.7.2", + "sort-package-json": "^3.4.0" }, "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": ">= 20.9.0" }, - "funding": { - "url": "https://opencollective.com/eslint" + "peerDependencies": { + "@eslint/js": ">= 9.28.0", + "@eslint/markdown": ">= 7.1.0", + "@stylistic/eslint-plugin": ">= 4.4.1", + "eslint": ">= 9.28.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-import": ">= 2.31.0", + "eslint-plugin-jest": ">= 28.12.0", + "eslint-plugin-jsdoc": ">= 50.7.1", + "eslint-plugin-n": ">= 17.19.0", + "eslint-plugin-prettier": ">= 5.5.3", + "eslint-plugin-react": ">= 7.37.5", + "eslint-plugin-unicorn": ">= 60.0.0", + "globals": ">= 16.2.0", + "prettier": ">= 3.5.3", + "typescript": ">= 5.0.0", + "typescript-eslint": ">= 8.34.0" + }, + "peerDependenciesMeta": { + "@eslint/markdown": { + "optional": true + }, + "eslint-plugin-jest": { + "optional": true + }, + "eslint-plugin-jsdoc": { + "optional": true + }, + "eslint-plugin-n": { + "optional": true + }, + "eslint-plugin-react": { + "optional": true + }, + "typescript": { + "optional": true + }, + "typescript-eslint": { + "optional": true + } } }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/eslint-config-webpack/node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12.20" } }, - "node_modules/eslint/node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/eslint-config-webpack/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "dev": true, - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-es-x": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-es-x/-/eslint-plugin-es-x-7.8.0.tgz", + "integrity": "sha512-7Ds8+wAAoV3T+LAKeu39Y5BzXCrGKrcISfgKEqTS4BDN8SFEDQd0S43jiQ8vIa3wUKD07qitZdfzlenSi8/0qQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/ota-meshi", + "https://opencollective.com/eslint" + ], + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.1.2", + "@eslint-community/regexpp": "^4.11.0", + "eslint-compat-utils": "^0.5.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": ">=8" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "29.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-29.0.1.tgz", + "integrity": "sha512-EE44T0OSMCeXhDrrdsbKAhprobKkPtJTbQz5yEktysNpHeDZTAL1SfDTNKmcFfJkY6yrQLtTKZALrD3j/Gpmiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.0.0" + }, + "engines": { + "node": "^20.12.0 || ^22.0.0 || >=24.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^8.0.0", + "eslint": "^8.57.0 || ^9.0.0", + "jest": "*" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-jsdoc": { + "version": "54.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-54.0.0.tgz", + "integrity": "sha512-8w5c8OmmD5WD5MNQy1AhmYbiyV4IlSscXUyg5MwvN3BI/bLUmRpeEXc+Mj37y2UZsLhzvHyCscQenUzvbLxQ7Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.52.0", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.1", + "debug": "^4.4.1", + "escape-string-regexp": "^4.0.0", + "espree": "^10.4.0", + "esquery": "^1.6.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.2", + "spdx-expression-parse": "^4.0.0" + }, + "engines": { + "node": ">=20.11.0" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-jsdoc/node_modules/spdx-expression-parse": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/eslint-plugin-n": { + "version": "17.21.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-n/-/eslint-plugin-n-17.21.3.tgz", + "integrity": "sha512-MtxYjDZhMQgsWRm/4xYLL0i2EhusWT7itDxlJ80l1NND2AL2Vi5Mvneqv/ikG9+zpran0VsVRXTEHrpLmUZRNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.5.0", + "enhanced-resolve": "^5.17.1", + "eslint-plugin-es-x": "^7.8.0", + "get-tsconfig": "^4.8.1", + "globals": "^15.11.0", + "globrex": "^0.1.2", + "ignore": "^5.3.2", + "semver": "^7.6.3", + "ts-declaration-location": "^1.0.6" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": ">=8.23.0" + } + }, + "node_modules/eslint-plugin-n/node_modules/globals": { + "version": "15.15.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.15.0.tgz", + "integrity": "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-n/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz", + "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.11.7" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-unicorn": { + "version": "60.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-60.0.0.tgz", + "integrity": "sha512-QUzTefvP8stfSXsqKQ+vBQSEsXIlAiCduS/V1Em+FKgL9c21U/IIm20/e3MFy1jyCf14tHAhqC1sX8OTy6VUCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "@eslint-community/eslint-utils": "^4.7.0", + "@eslint/plugin-kit": "^0.3.3", + "change-case": "^5.4.4", + "ci-info": "^4.3.0", + "clean-regexp": "^1.0.0", + "core-js-compat": "^3.44.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.3.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", + "pluralize": "^8.0.0", + "regexp-tree": "^0.1.27", + "regjsparser": "^0.12.0", + "semver": "^7.7.2", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": "^20.10.0 || >=21.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" + }, + "peerDependencies": { + "eslint": ">=9.29.0" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/indent-string": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint-plugin-unicorn/node_modules/strip-indent": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.0.0.tgz", + "integrity": "sha512-mnVSV2l+Zv6BLpSD/8V87CW/y9EmmbYzGCIavsnsI6/nwn26DwffM/yztm30Z/I2DY9wdS3vXVCMnHDgZaVNoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { @@ -8567,9 +9631,16 @@ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "license": "MIT" }, - "node_modules/fast-equals": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-equals": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.2.2.tgz", "integrity": "sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==", "dev": true, "license": "MIT", @@ -8647,6 +9718,20 @@ "reusify": "^1.0.4" } }, + "node_modules/fault": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", + "integrity": "sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "format": "^0.2.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/fb-watchman": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", @@ -8741,6 +9826,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat-cache": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz", @@ -8807,6 +9905,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/format": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", + "integrity": "sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, "node_modules/fs-extra": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", @@ -9245,6 +10352,29 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-tsconfig": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.1.tgz", + "integrity": "sha512-auHyJ4AgMz7vgS8Hp3N6HXSmlMdUyhSUrfBF16w153rxtLIEOE+HGqaBppczZvnHLqQJfiHotCYpNhl0lUROFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/git-hooks-list": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz", + "integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/fisker/git-hooks-list?sponsor=1" + } + }, "node_modules/git-raw-commits": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-4.0.0.tgz", @@ -9582,6 +10712,13 @@ "dev": true, "license": "ISC" }, + "node_modules/github-slugger": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", + "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", + "dev": true, + "license": "ISC" + }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", @@ -9641,13 +10778,16 @@ } }, "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "version": "16.3.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.3.0.tgz", + "integrity": "sha512-bqWEnJ1Nt3neqx2q5SFfGS8r/ahumIakg3HcwtNlrVlwXIeNumWn/c7Pn/wKzGhf6SaW6H6uWXLqC30STCMchQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/globalthis": { @@ -9724,6 +10864,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/globrex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", + "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", + "dev": true, + "license": "MIT" + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -9743,6 +10890,13 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, "node_modules/handlebars": { "version": "4.7.8", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", @@ -10155,6 +11309,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-builtin-module": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-modules": "^5.0.0" + }, + "engines": { + "node": ">=18.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -12425,6 +13595,16 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.1.0.tgz", + "integrity": "sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -12492,6 +13672,69 @@ "node": ">=6" } }, + "node_modules/jsonc-eslint-parser": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonc-eslint-parser/-/jsonc-eslint-parser-2.4.0.tgz", + "integrity": "sha512-WYDyuc/uFcGp6YtM2H0uKmUwieOuzeE/5YocFJLnLfclZ4inf3mRn8ZVy1s7Hxji7Jxm6Ss8gqpexD/GlKoGgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.5.0", + "eslint-visitor-keys": "^3.0.0", + "espree": "^9.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ota-meshi" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/jsonc-eslint-parser/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -13067,6 +14310,17 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/longest-streak": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", + "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -13124,6 +14378,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/markdown-table": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", + "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -13134,43 +14399,896 @@ "node": ">= 0.4" } }, - "node_modules/memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "node_modules/mdast-util-find-and-replace": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", + "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "escape-string-regexp": "^5.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-find-and-replace/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, + "license": "MIT", "engines": { - "node": ">= 0.10.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/meow": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", - "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "node_modules/mdast-util-from-markdown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", + "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark": "^4.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0", + "unist-util-stringify-position": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-frontmatter/-/mdast-util-frontmatter-2.0.1.tgz", + "integrity": "sha512-LRqI9+wdgC25P0URIJY9vwocIzCcksduHQ9OF2joxQoyTNVduwLAFUzjoopuRJbJAReaKrNQKAZKL3uCMugWJA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "escape-string-regexp": "^5.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-extension-frontmatter": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-frontmatter/node_modules/escape-string-regexp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", + "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", "dev": true, "license": "MIT", "engines": { - "node": ">=16.10" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/merge-stream": { + "node_modules/mdast-util-gfm": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", + "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-gfm-autolink-literal": "^2.0.0", + "mdast-util-gfm-footnote": "^2.0.0", + "mdast-util-gfm-strikethrough": "^2.0.0", + "mdast-util-gfm-table": "^2.0.0", + "mdast-util-gfm-task-list-item": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-autolink-literal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", + "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "ccount": "^2.0.0", + "devlop": "^1.0.0", + "mdast-util-find-and-replace": "^3.0.0", + "micromark-util-character": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.1.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-strikethrough": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "license": "MIT" + "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", + "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "node_modules/mdast-util-gfm-table": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", + "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "markdown-table": "^3.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-gfm-task-list-item": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", + "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "devlop": "^1.0.0", + "mdast-util-from-markdown": "^2.0.0", + "mdast-util-to-markdown": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-phrasing": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", + "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-markdown": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", + "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0", + "@types/unist": "^3.0.0", + "longest-streak": "^3.0.0", + "mdast-util-phrasing": "^4.0.0", + "mdast-util-to-string": "^4.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-decode-string": "^2.0.0", + "unist-util-visit": "^5.0.0", + "zwitch": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-to-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", + "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdast": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/meow": { + "version": "12.1.1", + "resolved": "https://registry.npmjs.org/meow/-/meow-12.1.1.tgz", + "integrity": "sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16.10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromark": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", + "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "@types/debug": "^4.0.0", + "debug": "^4.0.0", + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-core-commonmark": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", + "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "devlop": "^1.0.0", + "micromark-factory-destination": "^2.0.0", + "micromark-factory-label": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-factory-title": "^2.0.0", + "micromark-factory-whitespace": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-html-tag-name": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-subtokenize": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-extension-frontmatter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-frontmatter/-/micromark-extension-frontmatter-2.0.0.tgz", + "integrity": "sha512-C4AkuM3dA58cgZha7zVnuVxBhDsbttIMiytjgsM2XbHAB2faRVaHRle40558FBN+DJcrLNCoqG5mlrpdU4cRtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fault": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", + "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-extension-gfm-autolink-literal": "^2.0.0", + "micromark-extension-gfm-footnote": "^2.0.0", + "micromark-extension-gfm-strikethrough": "^2.0.0", + "micromark-extension-gfm-table": "^2.0.0", + "micromark-extension-gfm-tagfilter": "^2.0.0", + "micromark-extension-gfm-task-list-item": "^2.0.0", + "micromark-util-combine-extensions": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-autolink-literal": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", + "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-footnote": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", + "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-core-commonmark": "^2.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-normalize-identifier": "^2.0.0", + "micromark-util-sanitize-uri": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-strikethrough": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", + "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-classify-character": "^2.0.0", + "micromark-util-resolve-all": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-table": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", + "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-tagfilter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", + "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-extension-gfm-task-list-item": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", + "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/micromark-factory-destination": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", + "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-label": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", + "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-space": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", + "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-title": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", + "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-factory-whitespace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", + "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-factory-space": "^2.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-character": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", + "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-chunked": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", + "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-classify-character": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", + "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-combine-extensions": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", + "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-chunked": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-numeric-character-reference": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", + "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-decode-string": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", + "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "decode-named-character-reference": "^1.0.0", + "micromark-util-character": "^2.0.0", + "micromark-util-decode-numeric-character-reference": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-encode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", + "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-html-tag-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", + "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-normalize-identifier": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", + "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-resolve-all": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", + "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-sanitize-uri": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", + "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "micromark-util-character": "^2.0.0", + "micromark-util-encode": "^2.0.0", + "micromark-util-symbol": "^2.0.0" + } + }, + "node_modules/micromark-util-subtokenize": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", + "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT", + "dependencies": { + "devlop": "^1.0.0", + "micromark-util-chunked": "^2.0.0", + "micromark-util-symbol": "^2.0.0", + "micromark-util-types": "^2.0.0" + } + }, + "node_modules/micromark-util-symbol": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", + "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", + "dev": true, + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" + }, + "node_modules/micromark-util-types": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", + "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } + "funding": [ + { + "type": "GitHub Sponsors", + "url": "https://github.com/sponsors/unifiedjs" + }, + { + "type": "OpenCollective", + "url": "https://opencollective.com/unified" + } + ], + "license": "MIT" }, "node_modules/micromatch": { "version": "4.0.8", @@ -13618,6 +15736,59 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -13784,6 +15955,16 @@ "node": ">=8" } }, + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parse-statements": "1.0.11" + } + }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", @@ -13803,6 +15984,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", @@ -13885,9 +16073,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -14009,6 +16197,16 @@ "node": ">=8" } }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -14030,9 +16228,9 @@ } }, "node_modules/prettier": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", - "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", + "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", "dev": true, "license": "MIT", "bin": { @@ -14045,6 +16243,19 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/pretty-format": { "version": "30.0.0", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-30.0.0.tgz", @@ -14378,6 +16589,16 @@ "node": ">=4" } }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmjs.org/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "dev": true, + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -14523,6 +16744,16 @@ "node": ">=8" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", @@ -14934,6 +17165,84 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/sort-object-keys": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", + "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sort-package-json": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.4.0.tgz", + "integrity": "sha512-97oFRRMM2/Js4oEA9LJhjyMlde+2ewpZQf53pgue27UkbEXfHJnDzHlUxQ/DWUkzqmp7DFwJp8D+wi/TYeQhpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^7.0.1", + "detect-newline": "^4.0.1", + "git-hooks-list": "^4.0.0", + "is-plain-obj": "^4.1.0", + "semver": "^7.7.1", + "sort-object-keys": "^1.1.3", + "tinyglobby": "^0.2.12" + }, + "bin": { + "sort-package-json": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/sort-package-json/node_modules/detect-indent": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", + "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, + "node_modules/sort-package-json/node_modules/detect-newline": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", + "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/is-plain-obj": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", + "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sort-package-json/node_modules/semver": { + "version": "7.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", + "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -15875,6 +18184,78 @@ "node": ">=8" } }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-declaration-location": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/ts-declaration-location/-/ts-declaration-location-1.0.7.tgz", + "integrity": "sha512-EDyGAwH1gO0Ausm9gV6T2nUvBgXT5kGoCMJPllOaooZ+4VvJiKBdZE7wK18N1deEowhcUptS+5GXZK8U/fvpwA==", + "dev": true, + "funding": [ + { + "type": "ko-fi", + "url": "https://ko-fi.com/rebeccastevens" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/ts-declaration-location" + } + ], + "license": "BSD-3-Clause", + "dependencies": { + "picomatch": "^4.0.2" + }, + "peerDependencies": { + "typescript": ">=4.0.0" + } + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -16018,6 +18399,30 @@ "node": ">=14.17" } }, + "node_modules/typescript-eslint": { + "version": "8.39.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.39.1.tgz", + "integrity": "sha512-GDUv6/NDYngUlNvwaHM1RamYftxf782IyEDbdj3SeaIHHv8fNQVRC++fITT7kUJV/5rIA/tkoRSSskt6osEfqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.39.1", + "@typescript-eslint/parser": "8.39.1", + "@typescript-eslint/typescript-estree": "8.39.1", + "@typescript-eslint/utils": "8.39.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, "node_modules/uglify-js": { "version": "3.19.3", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", @@ -16114,6 +18519,65 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/unist-util-is": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.0.tgz", + "integrity": "sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-stringify-position": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", + "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", + "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0", + "unist-util-visit-parents": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-visit-parents": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", + "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/unist": "^3.0.0", + "unist-util-is": "^6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/universalify": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", @@ -16782,6 +19246,17 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zwitch": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", + "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } } } } diff --git a/package.json b/package.json index b21e55c..c858a58 100644 --- a/package.json +++ b/package.json @@ -2,20 +2,28 @@ "name": "eslint-webpack-plugin", "version": "5.0.2", "description": "A ESLint plugin for webpack", - "license": "MIT", - "repository": "webpack-contrib/eslint-webpack-plugin", - "author": "Ricardo Gobbo de Souza ", + "keywords": [ + "eslint", + "lint", + "linter", + "plugin", + "webpack" + ], "homepage": "https://github.com/webpack-contrib/eslint-webpack-plugin", "bugs": "https://github.com/webpack-contrib/eslint-webpack-plugin/issues", + "repository": "webpack-contrib/eslint-webpack-plugin", "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, + "license": "MIT", + "author": "Ricardo Gobbo de Souza ", "main": "dist/index.js", "types": "types/index.d.ts", - "engines": { - "node": ">= 18.12.0" - }, + "files": [ + "dist", + "types" + ], "scripts": { "start": "npm run build -- -w", "clean": "del-cli dist types", @@ -26,13 +34,13 @@ "commitlint": "commitlint --from=master", "security": "npm audit", "lint:prettier": "prettier -w --list-different .", - "lint:js": "exit 0; //eslint --cache .", + "lint:code": "eslint --cache .", "lint:spelling": "cspell \"**/*.*\"", "lint:types": "tsc --pretty --noEmit", "lint": "npm-run-all -l -p \"lint:**\"", - "fix:js": "npm run lint:js -- --fix", + "fix:code": "npm run lint:code -- --fix", "fix:prettier": "npm run lint:prettier -- --write", - "fix": "npm-run-all -l fix:js fix:prettier", + "fix": "npm-run-all -l fix:code fix:prettier", "test:only": "cross-env NODE_OPTIONS=--experimental-vm-modules NODE_ENV=test jest --testTimeout=60000", "test:watch": "npm run test:only -- --watch", "test:coverage": "npm run test:only -- --collectCoverageFrom=\"src/**/*.js\" --coverage", @@ -41,14 +49,6 @@ "prepare": "npm run build", "release": "standard-version" }, - "files": [ - "dist", - "types" - ], - "peerDependencies": { - "eslint": "^8.0.0 || ^9.0.0", - "webpack": "^5.0.0" - }, "dependencies": { "@types/eslint": "^9.6.1", "flatted": "^3.3.3", @@ -63,35 +63,43 @@ "@babel/preset-env": "^7.27.2", "@commitlint/cli": "^19.8.1", "@commitlint/config-conventional": "^19.8.1", + "@eslint/js": "^9.33.0", + "@eslint/markdown": "^7.0.0", + "@stylistic/eslint-plugin": "^5.2.3", "@types/fs-extra": "^11.0.4", "@types/micromatch": "^4.0.9", "@types/node": "^22.15.30", "@types/normalize-path": "^3.0.2", - "@types/webpack": "^5.28.5", - "@webpack-contrib/eslint-config-webpack": "^3.0.0", - "babel-jest": "^30.0.0", "chokidar": "^4.0.3", "cross-env": "^7.0.3", "cspell": "^8.19.4", "del": "^8.0.0", "del-cli": "^6.0.0", - "eslint": "^9.28.0", - "eslint-config-prettier": "^10.1.5", + "eslint": "^9.33.0", + "eslint-config-prettier": "^10.1.8", + "eslint-config-webpack": "^4.6.0", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jest": "^29.0.1", + "eslint-plugin-jsdoc": "^54.0.0", + "eslint-plugin-n": "^17.21.0", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-unicorn": "^60.0.0", "fs-extra": "^11.3.0", "husky": "^9.1.7", "jest": "^30.0.0", "lint-staged": "^15.5.2", "npm-run-all": "^4.1.5", - "prettier": "^3.5.3", + "prettier": "^3.6.2", "standard-version": "^9.5.0", - "typescript": "^5.8.3", + "typescript": "^5.5.3", + "typescript-eslint": "^8.39.1", "webpack": "^5.99.9" }, - "keywords": [ - "eslint", - "lint", - "linter", - "plugin", - "webpack" - ] + "peerDependencies": { + "eslint": "^8.0.0 || ^9.0.0", + "webpack": "^5.0.0" + }, + "engines": { + "node": ">= 18.12.0" + } } diff --git a/src/ESLintError.js b/src/ESLintError.js index 37dfb9f..feef37d 100644 --- a/src/ESLintError.js +++ b/src/ESLintError.js @@ -1,11 +1,11 @@ class ESLintError extends Error { /** - * @param {string=} messages + * @param {string=} messages messages */ constructor(messages) { super(`[eslint] ${messages}`); - this.name = 'ESLintError'; - this.stack = ''; + this.name = "ESLintError"; + this.stack = ""; } } diff --git a/src/getESLint.js b/src/getESLint.js index 6c852ff..fae43eb 100644 --- a/src/getESLint.js +++ b/src/getESLint.js @@ -1,14 +1,13 @@ -const { cpus } = require('os'); +const { cpus } = require("node:os"); -const { Worker: JestWorker } = require('jest-worker'); +const { stringify } = require("flatted"); +const { Worker: JestWorker } = require("jest-worker"); -// @ts-ignore -const { setup, lintFiles } = require('./worker'); -const { getESLintOptions } = require('./options'); -const { jsonStringifyReplacerSortKeys } = require('./utils'); -const { stringify } = require('flatted'); +const { getESLintOptions } = require("./options"); +const { jsonStringifyReplacerSortKeys } = require("./utils"); +const { lintFiles, setup } = require("./worker"); -/** @type {{[key: string]: any}} */ +/** @type {{ [key: string]: Linter }} */ const cache = {}; /** @typedef {import('eslint').ESLint} ESLint */ @@ -20,8 +19,8 @@ const cache = {}; /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */ /** - * @param {Options} options - * @returns {Promise} + * @param {Options} options options + * @returns {Promise} linter */ async function loadESLint(options) { const { eslintPath } = options; @@ -41,15 +40,24 @@ async function loadESLint(options) { } /** - * @param {string|undefined} key - * @param {number} poolSize - * @param {Options} options - * @returns {Promise} + * @param {string | undefined} key a cache key + * @param {Options} options options + * @returns {string} a stringified cache key + */ +function getCacheKey(key, options) { + return stringify({ key, options }, jsonStringifyReplacerSortKeys); +} + +/** + * @param {string | undefined} key a cache key + * @param {number} poolSize number of workers + * @param {Options} options options + * @returns {Promise} linter */ async function loadESLintThreaded(key, poolSize, options) { const cacheKey = getCacheKey(key, options); - const { eslintPath = 'eslint' } = options; - const source = require.resolve('./worker'); + const { eslintPath = "eslint" } = options; + const source = require.resolve("./worker"); const workerOptions = { enableWorkerThreads: true, numWorkers: poolSize, @@ -64,7 +72,9 @@ async function loadESLintThreaded(key, poolSize, options) { const local = await loadESLint(options); - let worker = /** @type {Worker?} */ (new JestWorker(source, workerOptions)); + let worker = + /** @type {Worker | null} */ + (new JestWorker(source, workerOptions)); /** @type {Linter} */ const context = { @@ -87,13 +97,13 @@ async function loadESLintThreaded(key, poolSize, options) { } /** - * @param {string|undefined} key - * @param {Options} options - * @returns {Promise} + * @param {string | undefined} key a cache key + * @param {Options} options options + * @returns {Promise} linter */ async function getESLint(key, { threads, ...options }) { const max = - typeof threads !== 'number' + typeof threads !== "number" ? threads ? cpus().length - 1 : 1 @@ -110,17 +120,8 @@ async function getESLint(key, { threads, ...options }) { return cache[cacheKey]; } -/** - * @param {string|undefined} key - * @param {Options} options - * @returns {string} - */ -function getCacheKey(key, options) { - return stringify({ key, options }, jsonStringifyReplacerSortKeys); -} - module.exports = { + getESLint, loadESLint, loadESLintThreaded, - getESLint, }; diff --git a/src/index.js b/src/index.js index 98d3b8d..7c53bcf 100644 --- a/src/index.js +++ b/src/index.js @@ -1,24 +1,24 @@ -const { isAbsolute, join } = require('path'); +const { isAbsolute, join } = require("node:path"); -const { isMatch } = require('micromatch'); +const { isMatch } = require("micromatch"); -const { getOptions } = require('./options'); -const linter = require('./linter'); -const { arrify, parseFiles, parseFoldersToGlobs } = require('./utils'); +const linter = require("./linter"); +const { getOptions } = require("./options"); +const { arrify, parseFiles, parseFoldersToGlobs } = require("./utils"); /** @typedef {import('webpack').Compiler} Compiler */ /** @typedef {import('webpack').Module} Module */ /** @typedef {import('webpack').NormalModule} NormalModule */ /** @typedef {import('./options').Options} Options */ -const ESLINT_PLUGIN = 'ESLintWebpackPlugin'; -const DEFAULT_FOLDER_TO_EXCLUDE = '**/node_modules/**'; +const ESLINT_PLUGIN = "ESLintWebpackPlugin"; +const DEFAULT_FOLDER_TO_EXCLUDE = "**/node_modules/**"; let compilerId = 0; class ESLintWebpackPlugin { /** - * @param {Options} options + * @param {Options=} options options */ constructor(options = {}) { this.key = ESLINT_PLUGIN; @@ -27,7 +27,7 @@ class ESLintWebpackPlugin { } /** - * @param {Compiler} compiler + * @param {Compiler} compiler compiler * @returns {void} */ apply(compiler) { @@ -49,7 +49,7 @@ class ESLintWebpackPlugin { exclude: excludedFiles, resourceQueryExclude: excludedResourceQueries, extensions: arrify(this.options.extensions), - files: parseFiles(this.options.files || '', this.getContext(compiler)), + files: parseFiles(this.options.files || "", this.getContext(compiler)), }; const foldersToExclude = this.options.exclude @@ -61,16 +61,17 @@ class ESLintWebpackPlugin { // If `lintDirtyModulesOnly` is disabled, // execute the linter on the build if (!this.options.lintDirtyModulesOnly) { - compiler.hooks.run.tapPromise(this.key, (c) => - this.run(c, options, wanted, exclude), + compiler.hooks.run.tapPromise(this.key, (compiler) => + this.run(compiler, options, wanted, exclude), ); } let hasCompilerRunByDirtyModule = this.options.lintDirtyModulesOnly; - compiler.hooks.watchRun.tapPromise(this.key, (c) => { - if (!hasCompilerRunByDirtyModule) - return this.run(c, options, wanted, exclude); + compiler.hooks.watchRun.tapPromise(this.key, (compiler) => { + if (!hasCompilerRunByDirtyModule) { + return this.run(compiler, options, wanted, exclude); + } hasCompilerRunByDirtyModule = false; @@ -79,12 +80,13 @@ class ESLintWebpackPlugin { } /** - * @param {Compiler} compiler - * @param {Omit & {resourceQueryExclude: RegExp[]}} options - * @param {string[]} wanted - * @param {string[]} exclude + * @param {Compiler} compiler compiler + * @param {Omit & { resourceQueryExclude: RegExp[] }} options options + * @param {string[]} wanted wanted files + * @param {string[]} exclude excluded files */ async run(compiler, options, wanted, exclude) { + // Do not re-hook const isCompilerHooked = compiler.hooks.compilation.taps.find( ({ name }) => name === this.key, ); @@ -105,30 +107,23 @@ class ESLintWebpackPlugin { options, compilation, )); - } catch (e) { - compilation.errors.push(e); + } catch (err) { + compilation.errors.push(err); return; } /** @type {string[]} */ const files = []; - // Add the file to be linted - compilation.hooks.succeedModule.tap(this.key, addFile); - - if (!this.options.lintDirtyModulesOnly) { - compilation.hooks.stillValidModule.tap(this.key, addFile); - } - /** - * @param {Module} module + * @param {Module} module module */ function addFile(module) { const { resource } = /** @type {NormalModule} */ (module); if (!resource) return; - const [file, query] = resource.split('?'); + const [file, query] = resource.split("?"); const isFileNotListed = file && !files.includes(file); const isFileWanted = isMatch(file, wanted, { dot: true }) && @@ -144,6 +139,13 @@ class ESLintWebpackPlugin { } } + // Add the file to be linted + compilation.hooks.succeedModule.tap(this.key, addFile); + + if (!this.options.lintDirtyModulesOnly) { + compilation.hooks.stillValidModule.tap(this.key, addFile); + } + // Lint all files added compilation.hooks.finishModules.tap(this.key, () => { if (files.length > 0 && threads <= 1) lint(files); @@ -152,16 +154,14 @@ class ESLintWebpackPlugin { // await and interpret results compilation.hooks.additionalAssets.tapAsync( this.key, - async function (callback) { + async (callback) => { const { errors, warnings, generateReportAsset } = await report(); if (warnings) { - // @ts-ignore compilation.warnings.push(warnings); } if (errors) { - // @ts-ignore compilation.errors.push(errors); } @@ -182,9 +182,8 @@ class ESLintWebpackPlugin { } /** - * - * @param {Compiler} compiler - * @returns {string} + * @param {Compiler} compiler compiler + * @returns {string} context */ getContext(compiler) { const compilerContext = String(compiler.options.context); diff --git a/src/linter.js b/src/linter.js index 17d6bae..3121cef 100644 --- a/src/linter.js +++ b/src/linter.js @@ -1,8 +1,8 @@ -const { dirname, isAbsolute, join } = require('path'); +const { dirname, isAbsolute, join } = require("node:path"); -const ESLintError = require('./ESLintError'); -const { getESLint } = require('./getESLint'); -const { arrify } = require('./utils'); +const ESLintError = require("./ESLintError"); +const { getESLint } = require("./getESLint"); +const { arrify } = require("./utils"); /** @typedef {import('eslint').ESLint} ESLint */ /** @typedef {import('eslint').ESLint.Formatter} Formatter */ @@ -21,16 +21,170 @@ const { arrify } = require('./utils'); const resultStorage = new WeakMap(); /** - * @param {string|undefined} key - * @param {Options} options - * @param {Compilation} compilation - * @returns {Promise<{lint: Linter, report: Reporter, threads: number}>} + * @param {Compilation} compilation compilation + * @returns {LintResultMap} lint result map + */ +function getResultStorage({ compiler }) { + let storage = resultStorage.get(compiler); + if (!storage) { + resultStorage.set(compiler, (storage = {})); + } + return storage; +} + +/** + * @param {Promise[]} results results + * @returns {Promise} flatted results + */ +async function flatten(results) { + /** + * @param {LintResult[]} acc acc + * @param {LintResult[]} list list + * @returns {LintResult[]} result + */ + const flat = (acc, list) => [...acc, ...list]; + return (await Promise.all(results)).reduce(flat, []); +} + +/** + * @param {ESLint} eslint eslint + * @param {LintResult[]} results results + * @returns {Promise} result without warnings + */ +async function removeIgnoredWarnings(eslint, results) { + const filterPromises = results.map(async (result) => { + // Short circuit the call to isPathIgnored. + // fatal is false for ignored file warnings. + // ruleId is unset for internal ESLint errors. + // line is unset for warnings not involving file contents. + const { messages, warningCount, errorCount, filePath } = result; + const [firstMessage] = messages; + const hasWarning = warningCount === 1 && errorCount === 0; + const ignored = + messages.length === 0 || + (hasWarning && + !firstMessage.fatal && + !firstMessage.ruleId && + !firstMessage.line && + (await eslint.isPathIgnored(filePath))); + return ignored ? false : result; + }); + + return (await Promise.all(filterPromises)).filter( + (result) => result !== false, + ); +} + +/** + * @param {ESLint} eslint eslint + * @param {string | FormatterFunction=} formatter formatter + * @returns {Promise} loaded formatter + */ +async function loadFormatter(eslint, formatter) { + if (typeof formatter === "function") { + return { format: formatter }; + } + + if (typeof formatter === "string") { + try { + return eslint.loadFormatter(formatter); + } catch { + // Load the default formatter. + } + } + + return eslint.loadFormatter(); +} + +/** + * @param {Formatter} formatter formatter + * @param {{ errors: LintResult[]; warnings: LintResult[]; }} results results + * @returns {Promise<{ errors?: ESLintError, warnings?: ESLintError }>} errors and warnings + */ +async function formatResults(formatter, results) { + let errors; + let warnings; + if (results.warnings.length > 0) { + warnings = new ESLintError(await formatter.format(results.warnings)); + } + + if (results.errors.length > 0) { + errors = new ESLintError(await formatter.format(results.errors)); + } + + return { + errors, + warnings, + }; +} + +/** + * @param {LintResult} file file + * @returns {boolean} true when has errors, otherwise false + */ +function fileHasErrors(file) { + return file.errorCount > 0; +} + +/** + * @param {LintResult} file file + * @returns {boolean} true when has warnings, otherwise false + */ +function fileHasWarnings(file) { + return file.warningCount > 0; +} + +/** + * @param {Options} options options results + * @param {LintResult[]} results results + * @returns {{ errors: LintResult[], warnings: LintResult[] }} parsed errors and warnings + */ +function parseResults(options, results) { + /** @type {LintResult[]} */ + const errors = []; + + /** @type {LintResult[]} */ + const warnings = []; + + for (const file of results) { + if (fileHasErrors(file)) { + const messages = file.messages.filter( + (message) => options.emitError && message.severity === 2, + ); + + if (messages.length > 0) { + errors.push({ ...file, messages }); + } + } + + if (fileHasWarnings(file)) { + const messages = file.messages.filter( + (message) => options.emitWarning && message.severity === 1, + ); + + if (messages.length > 0) { + warnings.push({ ...file, messages }); + } + } + } + + return { + errors, + warnings, + }; +} + +/** + * @param {string | undefined} key a cache key + * @param {Options} options options + * @param {Compilation} compilation compilation + * @returns {Promise<{lint: Linter, report: Reporter, threads: number}>} linter with additional functions */ async function linter(key, options, compilation) { /** @type {ESLint} */ let eslint; - /** @type {(files: string|string[]) => Promise} */ + /** @type {(files: string | string[]) => Promise} */ let lintFiles; /** @type {() => Promise} */ @@ -46,38 +200,34 @@ async function linter(key, options, compilation) { try { ({ eslint, lintFiles, cleanup, threads } = await getESLint(key, options)); - } catch (e) { - throw new ESLintError(e.message); + } catch (err) { + throw new ESLintError(err.message); } - return { - lint, - report, - threads, - }; - /** - * @param {string | string[]} files + * @param {string | string[]} files files */ function lint(files) { for (const file of arrify(files)) { delete crossRunResultStorage[file]; } rawResults.push( - lintFiles(files).catch((e) => { - // @ts-ignore - compilation.errors.push(new ESLintError(e.message)); + lintFiles(files).catch((err) => { + compilation.errors.push(new ESLintError(err.message)); return []; }), ); } + /** + * @returns {Promise} report + */ async function report() { // Filter out ignored files. let results = await removeIgnoredWarnings( eslint, // Get the current results, resetting the rawResults to empty - await flatten(rawResults.splice(0, rawResults.length)), + await flatten(rawResults.splice(0)), ); await cleanup(); @@ -99,24 +249,20 @@ async function linter(key, options, compilation) { parseResults(options, results), ); - return { - errors, - warnings, - generateReportAsset, - }; - /** - * @param {Compilation} compilation + * @param {Compilation} compilation compilation * @returns {Promise} */ async function generateReportAsset({ compiler }) { const { outputReport } = options; /** - * @param {string} name - * @param {string | Buffer} content + * @param {string} name name + * @param {string | Buffer} content content + * @returns {Promise} */ const save = (name, content) => - /** @type {Promise} */ ( + /** @type {Promise} */ + ( new Promise((finish, bail) => { if (!compiler.outputFileSystem) return; @@ -124,13 +270,15 @@ async function linter(key, options, compilation) { mkdir(dirname(name), { recursive: true }, (err) => { /* istanbul ignore if */ - if (err) bail(err); - else - writeFile(name, content, (/** @type {any} */ err2) => { + if (err) { + bail(err); + } else { + writeFile(name, content, (/** @type {unknown} */ err2) => { /* istanbul ignore if */ if (err2) bail(err2); else finish(); }); + } }); }) ); @@ -150,160 +298,19 @@ async function linter(key, options, compilation) { await save(filePath, content); } - } -} -/** - * @param {Formatter} formatter - * @param {{ errors: LintResult[]; warnings: LintResult[]; }} results - * @returns {Promise<{errors?: ESLintError, warnings?: ESLintError}>} - */ -async function formatResults(formatter, results) { - let errors; - let warnings; - if (results.warnings.length > 0) { - warnings = new ESLintError(await formatter.format(results.warnings)); - } - - if (results.errors.length > 0) { - errors = new ESLintError(await formatter.format(results.errors)); + return { + errors, + warnings, + generateReportAsset, + }; } return { - errors, - warnings, - }; -} - -/** - * @param {Options} options - * @param {LintResult[]} results - * @returns {{errors: LintResult[], warnings: LintResult[]}} - */ -function parseResults(options, results) { - /** @type {LintResult[]} */ - const errors = []; - - /** @type {LintResult[]} */ - const warnings = []; - - results.forEach((file) => { - if (fileHasErrors(file)) { - const messages = file.messages.filter( - (message) => options.emitError && message.severity === 2, - ); - - if (messages.length > 0) { - errors.push({ ...file, messages }); - } - } - - if (fileHasWarnings(file)) { - const messages = file.messages.filter( - (message) => options.emitWarning && message.severity === 1, - ); - - if (messages.length > 0) { - warnings.push({ ...file, messages }); - } - } - }); - - return { - errors, - warnings, + lint, + report, + threads, }; } -/** - * @param {LintResult} file - * @returns {boolean} - */ -function fileHasErrors(file) { - return file.errorCount > 0; -} - -/** - * @param {LintResult} file - * @returns {boolean} - */ -function fileHasWarnings(file) { - return file.warningCount > 0; -} - -/** - * @param {ESLint} eslint - * @param {string|FormatterFunction=} formatter - * @returns {Promise} - */ -async function loadFormatter(eslint, formatter) { - if (typeof formatter === 'function') { - return { format: formatter }; - } - - if (typeof formatter === 'string') { - try { - return eslint.loadFormatter(formatter); - } catch (_) { - // Load the default formatter. - } - } - - return eslint.loadFormatter(); -} - -/** - * @param {ESLint} eslint - * @param {LintResult[]} results - * @returns {Promise} - */ -async function removeIgnoredWarnings(eslint, results) { - const filterPromises = results.map(async (result) => { - // Short circuit the call to isPathIgnored. - // fatal is false for ignored file warnings. - // ruleId is unset for internal ESLint errors. - // line is unset for warnings not involving file contents. - const { messages, warningCount, errorCount, filePath } = result; - const [firstMessage] = messages; - const hasWarning = warningCount === 1 && errorCount === 0; - const ignored = - messages.length === 0 || - (hasWarning && - !firstMessage.fatal && - !firstMessage.ruleId && - !firstMessage.line && - (await eslint.isPathIgnored(filePath))); - return ignored ? false : result; - }); - - return (await Promise.all(filterPromises)).filter( - (result) => result !== false, - ); -} - -/** - * @param {Promise[]} results - * @returns {Promise} - */ -async function flatten(results) { - /** - * @param {LintResult[]} acc - * @param {LintResult[]} list - */ - const flat = (acc, list) => [...acc, ...list]; - return (await Promise.all(results)).reduce(flat, []); -} - -/** - * @param {Compilation} compilation - * @returns {LintResultMap} - */ -function getResultStorage({ compiler }) { - let storage = resultStorage.get(compiler); - if (!storage) { - resultStorage.set(compiler, (storage = {})); - } - return storage; -} - module.exports = linter; diff --git a/src/options.js b/src/options.js index c1f5bd3..77761d8 100644 --- a/src/options.js +++ b/src/options.js @@ -1,55 +1,55 @@ -const { validate } = require('schema-utils'); +const { validate } = require("schema-utils"); -const schema = require('./options.json'); +const schema = require("./options.json"); /** @typedef {import("eslint").ESLint.Options} ESLintOptions */ /** @typedef {import('eslint').ESLint.LintResult} LintResult */ /** * @callback FormatterFunction - * @param {LintResult[]} results - * @returns {string} + * @param {LintResult[]} results results + * @returns {string} formatted result */ /** - * @typedef {Object} OutputReport - * @property {string=} filePath - * @property {string|FormatterFunction=} formatter + * @typedef {object} OutputReport + * @property {string=} filePath a file path + * @property {string | FormatterFunction=} formatter a formatter */ /** - * @typedef {Object} PluginOptions - * @property {string=} context - * @property {boolean=} emitError - * @property {boolean=} emitWarning - * @property {string=} eslintPath - * @property {string|string[]=} exclude - * @property {string|string[]=} extensions - * @property {boolean=} failOnError - * @property {boolean=} failOnWarning - * @property {string|string[]=} files - * @property {boolean=} fix - * @property {string|FormatterFunction=} formatter - * @property {boolean=} lintDirtyModulesOnly - * @property {boolean=} quiet - * @property {OutputReport=} outputReport - * @property {number|boolean=} threads - * @property {RegExp|RegExp[]=} resourceQueryExclude - * @property {string=} configType + * @typedef {object} PluginOptions + * @property {string=} context a string indicating the root of your files + * @property {boolean=} emitError the errors found will always be emitted + * @property {boolean=} emitWarning the warnings found will always be emitted + * @property {string | string[]=} exclude specify the files and/or directories to exclude + * @property {string | string[]=} extensions specify the extensions that should be checked + * @property {boolean=} failOnError will cause the module build to fail if there are any errors + * @property {boolean=} failOnWarning will cause the module build to fail if there are any warning + * @property {string | string[]=} files specify directories, files, or globs + * @property {boolean=} fix apply fixes + * @property {string | FormatterFunction=} formatter specify the formatter you would like to use to format your results + * @property {boolean=} lintDirtyModulesOnly lint only changed files, skip linting on start + * @property {boolean=} quiet will process and report errors only and ignore warnings + * @property {string=} eslintPath path to `eslint` instance that will be used for linting + * @property {OutputReport=} outputReport writes the output of the errors to a file - for example, a `json` file for use for reporting + * @property {number | boolean=} threads number of worker threads + * @property {RegExp | RegExp[]=} resourceQueryExclude Specify the resource query to exclude + * @property {string=} configType config type */ /** @typedef {PluginOptions & ESLintOptions} Options */ /** - * @param {Options} pluginOptions - * @returns {PluginOptions} + * @param {Options} pluginOptions plugin options + * @returns {PluginOptions} normalized plugin options */ function getOptions(pluginOptions) { const options = { cache: true, - cacheLocation: 'node_modules/.cache/eslint-webpack-plugin/.eslintcache', - configType: 'flat', - extensions: 'js', + cacheLocation: "node_modules/.cache/eslint-webpack-plugin/.eslintcache", + configType: "flat", + extensions: "js", emitError: true, emitWarning: true, failOnError: true, @@ -58,18 +58,18 @@ function getOptions(pluginOptions) { ...(pluginOptions.quiet ? { emitError: true, emitWarning: false } : {}), }; - // @ts-ignore + // @ts-expect-error need better types validate(schema, options, { - name: 'ESLint Webpack Plugin', - baseDataPath: 'options', + name: "ESLint Webpack Plugin", + baseDataPath: "options", }); return options; } /** - * @param {Options} loaderOptions - * @returns {ESLintOptions} + * @param {Options} loaderOptions loader options + * @returns {ESLintOptions} eslint options */ function getESLintOptions(loaderOptions) { const eslintOptions = { ...loaderOptions }; @@ -78,14 +78,14 @@ function getESLintOptions(loaderOptions) { const { fix, extensions, ...eslintOnlyOptions } = schema.properties; // No need to guard the for-in because schema.properties has hardcoded keys. - // eslint-disable-next-line guard-for-in + for (const option in eslintOnlyOptions) { - // @ts-ignore + // @ts-expect-error need better types delete eslintOptions[option]; } // Some options aren't available in flat mode - if (loaderOptions.configType === 'flat') { + if (loaderOptions.configType === "flat") { delete eslintOptions.extensions; } @@ -93,6 +93,6 @@ function getESLintOptions(loaderOptions) { } module.exports = { - getOptions, getESLintOptions, + getOptions, }; diff --git a/src/utils.js b/src/utils.js index 13aa67e..fc82b4c 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,55 +1,56 @@ -const { resolve } = require('path'); -const { statSync } = require('fs'); +// eslint-disable-next-line jsdoc/no-restricted-syntax +/** @typedef {any} EXPECTED_ANY */ -const normalizePath = require('normalize-path'); +const { statSync } = require("node:fs"); +const { resolve } = require("node:path"); + +const normalizePath = require("normalize-path"); /** * @template T - * @param {T} value - * @return { - T extends (null | undefined) - ? [] - : T extends string - ? [string] - : T extends readonly unknown[] - ? T - : T extends Iterable - ? T[] - : [T] - } + * @typedef {T extends (null | undefined) + * ? [] + * : T extends string + * ? [string] + * : T extends readonly unknown[] + * ? T + * : T extends Iterable + * ? T[] + * : [T]} ArrifyResult */ + /* istanbul ignore next */ +/** + * @template T + * @param {T} value value + * @returns {ArrifyResult} array of values + */ function arrify(value) { - // eslint-disable-next-line no-undefined if (value === null || value === undefined) { - // @ts-ignore - return []; + return /** @type {ArrifyResult} */ ([]); } if (Array.isArray(value)) { - // @ts-ignore - return value; + return /** @type {ArrifyResult} */ (value); } - if (typeof value === 'string') { - // @ts-ignore - return [value]; + if (typeof value === "string") { + return /** @type {ArrifyResult} */ ([value]); } - // @ts-ignore - if (typeof value[Symbol.iterator] === 'function') { - // @ts-ignore + // @ts-expect-error need better types + if (typeof value[Symbol.iterator] === "function") { + // @ts-expect-error need better types return [...value]; } - // @ts-ignore - return [value]; + return /** @type {ArrifyResult} */ ([value]); } /** - * @param {string|string[]} files - * @param {string} context - * @returns {string[]} + * @param {string | string[]} files files + * @param {string} context context + * @returns {string[]} normalized paths */ function parseFiles(files, context) { return arrify(files).map((/** @type {string} */ file) => @@ -58,16 +59,16 @@ function parseFiles(files, context) { } /** - * @param {string|string[]} patterns - * @param {string|string[]} extensions - * @returns {string[]} + * @param {string | string[]} patterns patterns + * @param {string | string[]} extensions extensions + * @returns {string[]} globs */ function parseFoldersToGlobs(patterns, extensions = []) { const extensionsList = arrify(extensions); - const [prefix, postfix] = extensionsList.length > 1 ? ['{', '}'] : ['', '']; + const [prefix, postfix] = extensionsList.length > 1 ? ["{", "}"] : ["", ""]; const extensionsGlob = extensionsList - .map((/** @type {string} */ extension) => extension.replace(/^\./u, '')) - .join(','); + .map((/** @type {string} */ extension) => extension.replace(/^\./u, "")) + .join(","); return arrify(patterns).map((/** @type {string} */ pattern) => { try { @@ -78,11 +79,11 @@ function parseFoldersToGlobs(patterns, extensions = []) { return pattern.replace( /[/\\]*?$/u, `/**${ - extensionsGlob ? `/*.${prefix + extensionsGlob + postfix}` : '' + extensionsGlob ? `/*.${prefix + extensionsGlob + postfix}` : "" }`, ); } - } catch (_) { + } catch { // Return the pattern as is on error. } return pattern; @@ -91,22 +92,23 @@ function parseFoldersToGlobs(patterns, extensions = []) { /** * @param {string} _ key, but unused - * @param {any} value + * @param {EXPECTED_ANY} value value + * @returns {{ [x: string]: EXPECTED_ANY }} result */ const jsonStringifyReplacerSortKeys = (_, value) => { /** - * @param {{ [x: string]: any; }} sorted - * @param {string | number} key + * @param {{ [x: string]: EXPECTED_ANY }} sorted sorted + * @param {string | number} key key + * @returns {{ [x: string]: EXPECTED_ANY }} result */ const insert = (sorted, key) => { - // eslint-disable-next-line no-param-reassign sorted[key] = value[key]; return sorted; }; - if (value instanceof Object && !(value instanceof Array)) { - let sorted = Object.keys(value).sort().reduce(insert, {}); - Object.keys(value).forEach((key) => delete value[key]); + if (value instanceof Object && !Array.isArray(value)) { + const sorted = Object.keys(value).sort().reduce(insert, {}); + for (const key of Object.keys(value)) delete value[key]; Object.assign(value, sorted); } @@ -115,7 +117,7 @@ const jsonStringifyReplacerSortKeys = (_, value) => { module.exports = { arrify, + jsonStringifyReplacerSortKeys, parseFiles, parseFoldersToGlobs, - jsonStringifyReplacerSortKeys, }; diff --git a/src/worker.js b/src/worker.js index a714b68..888f089 100644 --- a/src/worker.js +++ b/src/worker.js @@ -3,11 +3,6 @@ /** @typedef {import('eslint').ESLint.LintResult} LintResult */ /** @typedef {{new (arg0: ESLintOptions): ESLint; outputFixes: (arg0: LintResult[]) => any;}} ESLintClass */ -Object.assign(module.exports, { - lintFiles, - setup, -}); - /** @type {ESLintClass} */ let ESLint; @@ -18,20 +13,23 @@ let eslint; let fix; /** - * @typedef {object} setupOptions - * @property {string=} eslintPath - import path of eslint - * @property {string=} configType - * @property {ESLintOptions} eslintOptions - linter options - * - * @param {setupOptions} arg0 - setup worker + * @param {object} options setup worker + * @param {string=} options.eslintPath import path of eslint + * @param {string=} options.configType a config type + * @param {ESLintOptions} options.eslintOptions linter options + * @returns {ESLint} eslint */ function setup({ eslintPath, configType, eslintOptions }) { - fix = !!(eslintOptions && eslintOptions.fix); - const eslintModule = require(eslintPath || 'eslint'); + fix = Boolean(eslintOptions && eslintOptions.fix); + + const eslintModule = require(eslintPath || "eslint"); - if (eslintModule.ESLint && parseFloat(eslintModule.ESLint.version) >= 9) { + if ( + eslintModule.ESLint && + Number.parseFloat(eslintModule.ESLint.version) >= 9 + ) { return eslintModule - .loadESLint({ useFlatConfig: configType === 'flat' }) + .loadESLint({ useFlatConfig: configType === "flat" }) .then((/** @type {ESLintClass} */ classESLint) => { ESLint = classESLint; eslint = new ESLint(eslintOptions); @@ -47,24 +45,24 @@ function setup({ eslintPath, configType, eslintOptions }) { } else { ({ ESLint } = eslintModule); - if (configType === 'flat') { + if (configType === "flat") { throw new Error( "Couldn't find FlatESLint, you might need to set eslintPath to 'eslint/use-at-your-own-risk'", ); } } - if (configType === 'flat') { - eslint = new FlatESLint(eslintOptions); - } else { - eslint = new ESLint(eslintOptions); - } + eslint = + configType === "flat" + ? new FlatESLint(eslintOptions) + : new ESLint(eslintOptions); return eslint; } /** - * @param {string | string[]} files + * @param {string | string[]} files files + * @returns {Promise} lint results */ async function lintFiles(files) { /** @type {LintResult[]} */ @@ -75,3 +73,6 @@ async function lintFiles(files) { } return result; } + +module.exports.lintFiles = lintFiles; +module.exports.setup = setup; diff --git a/test/autofix-stop.test.js b/test/autofix-stop.test.js index 5634286..3cda6a1 100644 --- a/test/autofix-stop.test.js +++ b/test/autofix-stop.test.js @@ -1,21 +1,21 @@ -import { join } from 'path'; +import { join } from "node:path"; -import { copySync, removeSync } from 'fs-extra'; -import chokidar from 'chokidar'; +import { watch } from "chokidar"; +import { copySync, removeSync } from "fs-extra"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('autofix stop', () => { - const entry = join(__dirname, 'fixtures/nonfixable-clone.js'); +describe("autofix stop", () => { + const entry = join(__dirname, "fixtures/nonfixable-clone.js"); let changed = false; let watcher; beforeAll(() => { - copySync(join(__dirname, 'fixtures/nonfixable.js'), entry); + copySync(join(__dirname, "fixtures/nonfixable.js"), entry); - watcher = chokidar.watch(entry); - watcher.on('change', () => { + watcher = watch(entry); + watcher.on("change", () => { changed = true; }); }); @@ -25,8 +25,8 @@ describe('autofix stop', () => { removeSync(entry); }); - it('should not change file if there are no fixable errors/warnings', async () => { - const compiler = pack('nonfixable-clone', { fix: true }); + it("should not change file if there are no fixable errors/warnings", async () => { + const compiler = pack("nonfixable-clone", { fix: true }); await compiler.runAsync(); expect(changed).toBe(false); diff --git a/test/autofix.test.js b/test/autofix.test.js index 3b0cc58..d837ab8 100644 --- a/test/autofix.test.js +++ b/test/autofix.test.js @@ -1,36 +1,36 @@ -import { join } from 'path'; +import { join } from "node:path"; -import { copySync, removeSync, readFileSync } from 'fs-extra'; +import { copySync, readFileSync, removeSync } from "fs-extra"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('autofix stop', () => { - const entry = join(__dirname, 'fixtures/fixable-clone.js'); +describe("autofix stop", () => { + const entry = join(__dirname, "fixtures/fixable-clone.js"); beforeAll(() => { - copySync(join(__dirname, 'fixtures/fixable.js'), entry); + copySync(join(__dirname, "fixtures/fixable.js"), entry); }); afterAll(() => { removeSync(entry); }); - test.each([[{}], [{ threads: false }]])( - 'should not throw error if file ok after auto-fixing', + it.each([[{}], [{ threads: false }]])( + "should not throw error if file ok after auto-fixing", async (cfg) => { - const compiler = pack('fixable-clone', { + const compiler = pack("fixable-clone", { ...cfg, fix: true, - extensions: ['js', 'cjs', 'mjs'], + extensions: ["js", "cjs", "mjs"], overrideConfig: { - rules: { semi: ['error', 'always'] }, + rules: { semi: ["error", "always"] }, }, }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(false); - expect(readFileSync(entry).toString('utf8')).toMatchInlineSnapshot(` + expect(readFileSync(entry).toString("utf8")).toMatchInlineSnapshot(` "function foo() { return true; } diff --git a/test/cached.test.js b/test/cached.test.js index 2497c80..9ac828c 100644 --- a/test/cached.test.js +++ b/test/cached.test.js @@ -1,13 +1,13 @@ -import { join } from 'path'; +import { join } from "node:path"; -import { removeSync } from 'fs-extra'; +import { removeSync } from "fs-extra"; -import webpack from 'webpack'; +import webpack from "webpack"; -import conf from './utils/conf'; +import conf from "./utils/conf"; -describe('error (cached module)', () => { - const cacheLocation = join(__dirname, 'cache'); +describe("error (cached module)", () => { + const cacheLocation = join(__dirname, "cache"); beforeEach(() => { removeSync(cacheLocation); @@ -17,10 +17,10 @@ describe('error (cached module)', () => { removeSync(cacheLocation); }); - it('should return error even if module is cached', (done) => { - const config = conf('error'); + it("should return error even if module is cached", (done) => { + const config = conf("error"); config.cache = { - type: 'filesystem', + type: "filesystem", idleTimeout: 0, idleTimeoutAfterLargeChanges: 0, idleTimeoutForInitialStore: 0, diff --git a/test/child-compiler.test.js b/test/child-compiler.test.js index afbde63..5a37aa9 100644 --- a/test/child-compiler.test.js +++ b/test/child-compiler.test.js @@ -1,8 +1,8 @@ -import webpack from 'webpack'; +import webpack from "webpack"; -import conf from './utils/conf'; +import conf from "./utils/conf"; -const PLUGIN_NAME = 'ChildPlugin'; +const PLUGIN_NAME = "ChildPlugin"; class ChildPlugin { constructor(options) { this.options = webpack.config.getNormalizedWebpackOptions(options); @@ -23,13 +23,13 @@ class ChildPlugin { } } -describe('child compiler', () => { - it('should have linting process', (done) => { - const config = conf('good', { threads: false }); +describe("child compiler", () => { + it("should have linting process", (done) => { + const config = conf("good", { threads: false }); config.plugins.push( new ChildPlugin({ entry: { - child: './child-entry', + child: "./child-entry", }, }), ); diff --git a/test/circular-plugin.test.js b/test/circular-plugin.test.js index 54b93ad..3c96335 100644 --- a/test/circular-plugin.test.js +++ b/test/circular-plugin.test.js @@ -1,10 +1,11 @@ -import pack from './utils/pack'; -import { ESLint } from 'eslint'; +import { ESLint } from "eslint"; +import pack from "./utils/pack"; -(ESLint && parseFloat(ESLint.version) < 9 ? describe.skip : describe)( - 'circular plugin', +(ESLint && Number.parseFloat(ESLint.version) < 9 ? describe.skip : describe)( + "circular plugin", () => { - it('should support plugins with circular configs', async () => { + // eslint-disable-next-line jest/require-top-level-describe + test("should support plugins with circular configs", async () => { const plugin = { configs: {}, rules: {}, @@ -21,14 +22,14 @@ import { ESLint } from 'eslint'; }); const loaderOptions = { - configType: 'flat', + configType: "flat", overrideConfig: { - plugins: { plugin: plugin }, + plugins: { plugin }, }, overrideConfigFile: true, }; - const compiler = pack('good', loaderOptions); + const compiler = pack("good", loaderOptions); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/config-for-tests/.eslintrc.js b/test/config-for-tests/.eslintrc.js new file mode 100644 index 0000000..8b6befd --- /dev/null +++ b/test/config-for-tests/.eslintrc.js @@ -0,0 +1,28 @@ +module.exports = { + ignorePatterns: ["**/ignore.js"], + globals: { + __dirname: "readonly", + __filename: "readonly", + exports: "writable", + module: "readonly", + require: "readonly", + console: "readonly", + }, + parserOptions: { + ecmaVersion: 2018, + env: { + browser: true, + node: true, + es6: true, + }, + sourceType: "module", + }, + rules: { + "no-console": "warn", + + "no-undef": "error", + "no-var": "error", + "no-unused-vars": "error", + "prefer-const": "error", + }, +}; diff --git a/test/config-for-tests/eslint.config.mjs b/test/config-for-tests/eslint.config.mjs new file mode 100644 index 0000000..131ef9f --- /dev/null +++ b/test/config-for-tests/eslint.config.mjs @@ -0,0 +1,19 @@ +import { defineConfig } from "eslint/config"; +// eslint-disable-next-line import/no-extraneous-dependencies +import globals from "globals"; + +export default defineConfig({ + languageOptions: { + globals: { + ...globals.node, + }, + }, + rules: { + "no-console": "warn", + + "no-undef": "error", + "no-var": "error", + "no-unused-vars": "error", + "prefer-const": "error", + }, +}); diff --git a/test/context.test.js b/test/context.test.js index 84fb54d..d8105ad 100644 --- a/test/context.test.js +++ b/test/context.test.js @@ -1,18 +1,18 @@ -import { join } from 'path'; +import { join } from "node:path"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('context', () => { - it('absolute', async () => { - const compiler = pack('good', { context: join(__dirname, 'fixtures') }); +describe("context", () => { + it("absolute", async () => { + const compiler = pack("good", { context: join(__dirname, "fixtures") }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(false); }); - it('relative', async () => { - const compiler = pack('good', { context: '../fixtures/' }); + it("relative", async () => { + const compiler = pack("good", { context: "../fixtures/" }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/emit-error.test.js b/test/emit-error.test.js index ca82903..1724b26 100644 --- a/test/emit-error.test.js +++ b/test/emit-error.test.js @@ -1,29 +1,29 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('emit error', () => { - it('should not emit errors if emitError is false', async () => { - const compiler = pack('error', { emitError: false }); +describe("emit error", () => { + it("should not emit errors if emitError is false", async () => { + const compiler = pack("error", { emitError: false }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(false); }); - it('should emit errors if emitError is undefined', async () => { - const compiler = pack('error', {}); + it("should emit errors if emitError is undefined", async () => { + const compiler = pack("error", {}); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(true); }); - it('should emit errors if emitError is true', async () => { - const compiler = pack('error', { emitError: true }); + it("should emit errors if emitError is true", async () => { + const compiler = pack("error", { emitError: true }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(true); }); - it('should emit errors, but not warnings if emitError is true and emitWarning is false', async () => { - const compiler = pack('full-of-problems', { + it("should emit errors, but not warnings if emitError is true and emitWarning is false", async () => { + const compiler = pack("full-of-problems", { emitError: true, emitWarning: false, }); @@ -33,8 +33,8 @@ describe('emit error', () => { expect(stats.hasErrors()).toBe(true); }); - it('should emit errors and warnings if emitError is true and emitWarning is undefined', async () => { - const compiler = pack('full-of-problems', { emitError: true }); + it("should emit errors and warnings if emitError is true and emitWarning is undefined", async () => { + const compiler = pack("full-of-problems", { emitError: true }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(true); diff --git a/test/emit-warning.test.js b/test/emit-warning.test.js index 4cd2100..cb5deab 100644 --- a/test/emit-warning.test.js +++ b/test/emit-warning.test.js @@ -1,29 +1,29 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('emit warning', () => { - it('should not emit warnings if emitWarning is false', async () => { - const compiler = pack('warn', { emitWarning: false }); +describe("emit warning", () => { + it("should not emit warnings if emitWarning is false", async () => { + const compiler = pack("warn", { emitWarning: false }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); }); - it('should emit warnings if emitWarning is undefined', async () => { - const compiler = pack('warn', {}); + it("should emit warnings if emitWarning is undefined", async () => { + const compiler = pack("warn", {}); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(true); }); - it('should emit warnings if emitWarning is true', async () => { - const compiler = pack('warn', { emitWarning: true }); + it("should emit warnings if emitWarning is true", async () => { + const compiler = pack("warn", { emitWarning: true }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(true); }); - it('should emit warnings, but not warnings if emitWarning is true and emitError is false', async () => { - const compiler = pack('full-of-problems', { + it("should emit warnings, but not warnings if emitWarning is true and emitError is false", async () => { + const compiler = pack("full-of-problems", { emitWarning: true, emitError: false, }); @@ -33,8 +33,8 @@ describe('emit warning', () => { expect(stats.hasErrors()).toBe(false); }); - it('should emit warnings and errors if emitWarning is true and emitError is undefined', async () => { - const compiler = pack('full-of-problems', { emitWarning: true }); + it("should emit warnings and errors if emitWarning is true and emitError is undefined", async () => { + const compiler = pack("full-of-problems", { emitWarning: true }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(true); diff --git a/test/empty.test.js b/test/empty.test.js index 220ef05..4bba6f8 100644 --- a/test/empty.test.js +++ b/test/empty.test.js @@ -1,16 +1,16 @@ -import { join } from 'path'; +import { join } from "node:path"; -import webpack from 'webpack'; +import webpack from "webpack"; -import ESLintPlugin from '../src'; +import ESLintPlugin from "../src"; -describe('empty', () => { - it('no error when no files matching', (done) => { +describe("empty", () => { + it("no error when no files matching", (done) => { const compiler = webpack({ - context: join(__dirname, 'fixtures', 'empty'), - mode: 'development', - entry: '../', - plugins: [new ESLintPlugin({ configType: 'eslintrc' })], + context: join(__dirname, "fixtures", "empty"), + mode: "development", + entry: "../", + plugins: [new ESLintPlugin({ configType: "eslintrc" })], }); compiler.run((err, stats) => { diff --git a/test/error.test.js b/test/error.test.js index c802698..2021d87 100644 --- a/test/error.test.js +++ b/test/error.test.js @@ -1,28 +1,28 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('error', () => { +describe("error", () => { afterEach(() => { jest.restoreAllMocks(); }); - it('should return error if file is bad', async () => { - const compiler = pack('error'); + it("should return error if file is bad", async () => { + const compiler = pack("error"); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); }); - it('should propagate eslint exceptions as errors', async () => { - jest.mock('eslint', () => { - return { - ESLint: function ESLint() { - this.lintFiles = async () => Promise.reject(new Error('Oh no!')); - }, - }; - }); + it("should propagate eslint exceptions as errors", async () => { + jest.mock("eslint", () => ({ + ESLint: function ESLint() { + this.lintFiles = async () => { + throw new Error("Oh no!"); + }; + }, + })); - const compiler = pack('good', { threads: false }); + const compiler = pack("good", { threads: false }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/eslint-lint.test.js b/test/eslint-lint.test.js index a3c406f..7154f7b 100644 --- a/test/eslint-lint.test.js +++ b/test/eslint-lint.test.js @@ -1,13 +1,20 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('eslint lint', () => { +describe("eslint lint", () => { const mockLintFiles = jest.fn().mockReturnValue([]); beforeAll(() => { - jest.mock('eslint', () => { + jest.mock("eslint", () => { + function ESLint() { + this.lintFiles = mockLintFiles; + } + + ESLint.version = "9.0.0"; + return { - ESLint: function ESLint() { - this.lintFiles = mockLintFiles; + ESLint, + async loadESLint() { + return ESLint; }, }; }); @@ -17,32 +24,32 @@ describe('eslint lint', () => { mockLintFiles.mockClear(); }); - it('should lint one file', async () => { - const compiler = pack('lint-one', { threads: false }); + it("should lint one file", async () => { + const compiler = pack("lint-one", { threads: false }); await compiler.runAsync(); expect(mockLintFiles).toHaveBeenCalledTimes(1); }); - it('should lint two files', async () => { - const compiler = pack('lint-two', { threads: false }); + it("should lint two files", async () => { + const compiler = pack("lint-two", { threads: false }); await compiler.runAsync(); const files = [ - expect.stringMatching('lint-two-entry.js'), - expect.stringMatching('lint.js'), + expect.stringMatching("lint-two-entry.js"), + expect.stringMatching("lint.js"), ]; expect(mockLintFiles).toHaveBeenCalledWith(files); }); - it('should lint more files', async () => { - const compiler = pack('lint-more', { threads: false }); + it("should lint more files", async () => { + const compiler = pack("lint-more", { threads: false }); await compiler.runAsync(); const files = [ - expect.stringMatching('lint-more-entry.js'), - expect.stringMatching('lint-more.js'), - expect.stringMatching('lint.js'), + expect.stringMatching("lint-more-entry.js"), + expect.stringMatching("lint-more.js"), + expect.stringMatching("lint.js"), ]; expect(mockLintFiles).toHaveBeenCalledWith(files); }); diff --git a/test/eslint-options.test.js b/test/eslint-options.test.js index 7e914ef..df053e3 100644 --- a/test/eslint-options.test.js +++ b/test/eslint-options.test.js @@ -1,9 +1,9 @@ -import { getESLintOptions } from '../src/options'; +import { getESLintOptions } from "../src/options"; -describe('eslint options', () => { - it('should filter loader options', () => { +describe("eslint options", () => { + it("should filter loader options", () => { const options = { - formatter: 'table', + formatter: "table", ignore: false, }; expect(getESLintOptions(options)).toStrictEqual({ @@ -11,11 +11,11 @@ describe('eslint options', () => { }); }); - it('should keep the fix option', () => { + it("should keep the fix option", () => { // The fix option should be kept because it is common to both the loader and ESLint. const options = { - eslintPath: 'some/place/where/eslint/lives', - formatter: 'table', + eslintPath: "some/place/where/eslint/lives", + formatter: "table", fix: true, emitError: false, emitWarning: false, diff --git a/test/eslint-path.test.js b/test/eslint-path.test.js index 63d87dd..5c24c3f 100644 --- a/test/eslint-path.test.js +++ b/test/eslint-path.test.js @@ -1,15 +1,15 @@ -import { join } from 'path'; +import { join } from "node:path"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('eslint path', () => { - it('should use another instance of eslint via eslintPath config', async () => { - const eslintPath = join(__dirname, 'mock/eslint'); - const compiler = pack('good', { eslintPath }); +describe("eslint path", () => { + it("should use another instance of eslint via eslintPath config", async () => { + const eslintPath = join(__dirname, "mock/eslint"); + const compiler = pack("good", { eslintPath }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); - expect(stats.compilation.errors[0].message).toContain('Fake error'); + expect(stats.compilation.errors[0].message).toContain("Fake error"); }); }); diff --git a/test/eslintignore.test.js b/test/eslintignore.test.js deleted file mode 100644 index b37f92a..0000000 --- a/test/eslintignore.test.js +++ /dev/null @@ -1,15 +0,0 @@ -import ESLintError from '../src/ESLintError'; - -import pack from './utils/pack'; - -describe('eslintignore', () => { - it('should ignores files present in .eslintignore', async () => { - const compiler = pack('ignore', { ignore: true }); - - const stats = await compiler.runAsync(); - expect(stats.hasWarnings()).toBe(false); - expect( - stats.compilation.errors.filter((x) => x instanceof ESLintError), - ).toEqual([]); - }); -}); diff --git a/test/eslintrc-config.test.js b/test/eslintrc-config.test.js new file mode 100644 index 0000000..a1d3735 --- /dev/null +++ b/test/eslintrc-config.test.js @@ -0,0 +1,25 @@ +import { join } from "node:path"; + +import pack from "./utils/pack"; + +describe("succeed on eslintrc-configuration", () => { + it("should work with eslintrc configuration type", async () => { + const overrideConfigFile = join( + __dirname, + "fixtures", + "eslintrc-config.js", + ); + const compiler = pack("full-of-problems", { + configType: "eslintrc", + overrideConfigFile, + threads: 1, + }); + + const stats = await compiler.runAsync(); + const { errors } = stats.compilation; + + expect(stats.hasErrors()).toBe(true); + expect(errors).toHaveLength(1); + expect(errors[0].message).toContain("full-of-problems.js"); + }); +}); diff --git a/test/exclude.test.js b/test/exclude.test.js index 6ee306d..547bf77 100644 --- a/test/exclude.test.js +++ b/test/exclude.test.js @@ -1,24 +1,24 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('exclude', () => { - it('should exclude with globs', async () => { - const compiler = pack('exclude', { exclude: ['*error*'] }); +describe("exclude", () => { + it("should exclude with globs", async () => { + const compiler = pack("exclude", { exclude: ["*error*"] }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(false); }); - it('should exclude files', async () => { - const compiler = pack('exclude', { exclude: ['error.js'] }); + it("should exclude files", async () => { + const compiler = pack("exclude", { exclude: ["error.js"] }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(false); }); - it('should exclude folders', async () => { - const compiler = pack('exclude-folder', { exclude: ['folder'] }); + it("should exclude folders", async () => { + const compiler = pack("exclude-folder", { exclude: ["folder"] }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/fail-on-config.test.js b/test/fail-on-config.test.js index 6f40a04..93b3076 100644 --- a/test/fail-on-config.test.js +++ b/test/fail-on-config.test.js @@ -1,11 +1,14 @@ -import { join } from 'path'; +import { join } from "node:path"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('fail on config', () => { - it('fails when .eslintrc is not a proper format', async () => { - const overrideConfigFile = join(__dirname, '.badeslintrc'); - const compiler = pack('error', { overrideConfigFile }); +describe("fail on config", () => { + it("fails when .eslintrc is not a proper format", async () => { + const overrideConfigFile = join(__dirname, ".badeslintrc"); + const compiler = pack("error", { + configType: "eslintrc", + overrideConfigFile, + }); const stats = await compiler.runAsync(); const { errors } = stats.compilation; diff --git a/test/fail-on-error.test.js b/test/fail-on-error.test.js index f9856dc..cc54d01 100644 --- a/test/fail-on-error.test.js +++ b/test/fail-on-error.test.js @@ -1,21 +1,21 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('fail on error', () => { - it('should emits errors', async () => { - const compiler = pack('error', { failOnError: true }); +describe("fail on error", () => { + it("should emits errors", async () => { + const compiler = pack("error", { failOnError: true }); - await expect(compiler.runAsync()).rejects.toThrow('error'); + await expect(compiler.runAsync()).rejects.toThrow("error"); }); - it('should emit warnings when disabled', async () => { - const compiler = pack('error', { failOnError: false }); + it("should emit warnings when disabled", async () => { + const compiler = pack("error", { failOnError: false }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(true); }); - it('should correctly identifies a success', async () => { - const compiler = pack('good', { failOnError: true }); + it("should correctly identifies a success", async () => { + const compiler = pack("good", { failOnError: true }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(false); diff --git a/test/fail-on-warning.test.js b/test/fail-on-warning.test.js index 92d7ad8..cc3ca9b 100644 --- a/test/fail-on-warning.test.js +++ b/test/fail-on-warning.test.js @@ -1,14 +1,14 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('fail on warning', () => { - it('should emits errors', async () => { - const compiler = pack('warn', { failOnWarning: true }); +describe("fail on warning", () => { + it("should emits errors", async () => { + const compiler = pack("warn", { failOnWarning: true }); - await expect(compiler.runAsync()).rejects.toThrow('warning'); + await expect(compiler.runAsync()).rejects.toThrow("warning"); }); - it('should correctly identifies a success', async () => { - const compiler = pack('good', { failOnWarning: true }); + it("should correctly identifies a success", async () => { + const compiler = pack("good", { failOnWarning: true }); const stats = await compiler.runAsync(); expect(stats.hasErrors()).toBe(false); diff --git a/test/fixtures/eslintrc-config.js b/test/fixtures/eslintrc-config.js new file mode 100644 index 0000000..f12321f --- /dev/null +++ b/test/fixtures/eslintrc-config.js @@ -0,0 +1,15 @@ +module.exports = { + root: true, + parserOptions: { + ecmaVersion: 2018, + env: { + es6: true, + jest: true, + }, + sourceType: 'module', + }, + rules: { + strict: 'error', + 'global-require': 'off', + }, +}; diff --git a/test/fixtures/good-entry.js b/test/fixtures/good-entry.js index 90d29c2..ede5b6f 100644 --- a/test/fixtures/good-entry.js +++ b/test/fixtures/good-entry.js @@ -1 +1 @@ -require('./good'); +require("./good"); diff --git a/test/fixtures/good.js b/test/fixtures/good.js index dc3c38b..f71f8c5 100644 --- a/test/fixtures/good.js +++ b/test/fixtures/good.js @@ -1,3 +1,6 @@ +/** + * @returns {string} value + */ function test() { return "value" } diff --git a/test/fixtures/multiple-entry.js b/test/fixtures/multiple-entry.js index 32ada72..5bb8d0e 100644 --- a/test/fixtures/multiple-entry.js +++ b/test/fixtures/multiple-entry.js @@ -1,2 +1,2 @@ -require('./good'); -require('./error'); +require("./good"); +require("./error"); diff --git a/test/flat-config.test.js b/test/flat-config.test.js index 91d953a..eac3cbd 100644 --- a/test/flat-config.test.js +++ b/test/flat-config.test.js @@ -1,15 +1,16 @@ -import { join } from 'path'; +import { join } from "node:path"; -import pack from './utils/pack'; -import { ESLint } from 'eslint'; +import { ESLint } from "eslint"; +import pack from "./utils/pack"; -(ESLint && parseFloat(ESLint.version) >= 9 ? describe.skip : describe)( - 'succeed on flat-configuration', +(ESLint && Number.parseFloat(ESLint.version) >= 9 ? describe.skip : describe)( + "succeed on flat-configuration", () => { - it('cannot load FlatESLint class on default ESLint module', async () => { - const overrideConfigFile = join(__dirname, 'fixtures', 'flat-config.js'); - const compiler = pack('full-of-problems', { - configType: 'flat', + // eslint-disable-next-line jest/require-top-level-describe, jest/consistent-test-it + it("cannot load FlatESLint class on default ESLint module", async () => { + const overrideConfigFile = join(__dirname, "fixtures", "flat-config.js"); + const compiler = pack("full-of-problems", { + configType: "flat", overrideConfigFile, threads: 1, }); @@ -25,17 +26,17 @@ import { ESLint } from 'eslint'; }); (process.version.match(/^v(\d+\.\d+)/)[1] >= 20 ? it : it.skip)( - 'finds errors on files', + "finds errors on files", async () => { const overrideConfigFile = join( __dirname, - 'fixtures', - 'flat-config.js', + "fixtures", + "flat-config.js", ); - const compiler = pack('full-of-problems', { - configType: 'flat', + const compiler = pack("full-of-problems", { + configType: "flat", // needed for now - eslintPath: 'eslint/use-at-your-own-risk', + eslintPath: "eslint/use-at-your-own-risk", overrideConfigFile, threads: 1, }); @@ -43,9 +44,13 @@ import { ESLint } from 'eslint'; const stats = await compiler.runAsync(); const { errors } = stats.compilation; + // eslint-disable-next-line jest/no-standalone-expect expect(stats.hasErrors()).toBe(true); + // eslint-disable-next-line jest/no-standalone-expect expect(errors).toHaveLength(1); + // eslint-disable-next-line jest/no-standalone-expect expect(errors[0].message).toMatch(/full-of-problems\.js/i); + // eslint-disable-next-line jest/no-standalone-expect expect(stats.hasWarnings()).toBe(true); }, ); diff --git a/test/formatter-custom.test.js b/test/formatter-custom.test.js index 25979c2..f8ac7f0 100644 --- a/test/formatter-custom.test.js +++ b/test/formatter-custom.test.js @@ -1,33 +1,34 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('formatter eslint', () => { - it('should use custom formatter as function', async () => { - const formatter = require('./mock/formatter'); - const compiler = pack('error', { formatter }); +describe("formatter eslint", () => { + it("should use custom formatter as function", async () => { + const formatter = require("./mock/formatter"); + + const compiler = pack("error", { formatter }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); expect(stats.compilation.errors[0].message).toBeTruthy(); const message = JSON.parse( - stats.compilation.errors[0].message.replace('[eslint] ', ''), + stats.compilation.errors[0].message.replace("[eslint] ", ""), ); - expect(message.formatter).toEqual('mock'); + expect(message.formatter).toBe("mock"); expect(message.results).toBeTruthy(); }); - it('should use custom formatter as string', async () => { - const formatter = './test/mock/formatter'; - const compiler = pack('error', { formatter }); + it("should use custom formatter as string", async () => { + const formatter = "./test/mock/formatter"; + const compiler = pack("error", { formatter }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); expect(stats.compilation.errors[0].message).toBeTruthy(); const message = JSON.parse( - stats.compilation.errors[0].message.replace('[eslint] ', ''), + stats.compilation.errors[0].message.replace("[eslint] ", ""), ); - expect(message.formatter).toEqual('mock'); + expect(message.formatter).toBe("mock"); expect(message.results).toBeTruthy(); }); }); diff --git a/test/formatter-eslint.test.js b/test/formatter-eslint.test.js index 7b991e0..fe79803 100644 --- a/test/formatter-eslint.test.js +++ b/test/formatter-eslint.test.js @@ -1,8 +1,8 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('formatter eslint', () => { - it('should use eslint formatter', async () => { - const compiler = pack('error'); +describe("formatter eslint", () => { + it("should use eslint formatter", async () => { + const compiler = pack("error"); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/formatter-official.test.js b/test/formatter-official.test.js index 814a666..38daaef 100644 --- a/test/formatter-official.test.js +++ b/test/formatter-official.test.js @@ -1,8 +1,8 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('formatter official', () => { - it('should use official formatter', async () => { - const compiler = pack('error', { formatter: 'json' }); +describe("formatter official", () => { + it("should use official formatter", async () => { + const compiler = pack("error", { formatter: "json" }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/formatter-write.test.js b/test/formatter-write.test.js index e3a6019..e047c0c 100644 --- a/test/formatter-write.test.js +++ b/test/formatter-write.test.js @@ -1,17 +1,17 @@ -import { join } from 'path'; +import { join } from "node:path"; -import { readFileSync, removeSync } from 'fs-extra'; -import webpack from 'webpack'; +import { readFileSync, removeSync } from "fs-extra"; +import webpack from "webpack"; -import conf from './utils/conf'; +import conf from "./utils/conf"; -describe('formatter write', () => { - it('should write results to relative file with a custom formatter', (done) => { - const outputFilename = 'outputReport-relative.txt'; - const config = conf('error', { - formatter: 'json', +describe("formatter write", () => { + it("should write results to relative file with a custom formatter", (done) => { + const outputFilename = "outputReport-relative.txt"; + const config = conf("error", { + formatter: "json", outputReport: { - formatter: 'json', + formatter: "json", filePath: outputFilename, }, }); @@ -21,7 +21,7 @@ describe('formatter write', () => { const compiler = webpack(config); compiler.run((err, stats) => { - const contents = readFileSync(outputFilepath, 'utf8'); + const contents = readFileSync(outputFilepath, "utf8"); expect(err).toBeNull(); expect(stats.hasWarnings()).toBe(false); @@ -31,10 +31,10 @@ describe('formatter write', () => { }); }); - it('should write results to absolute file with a same formatter', (done) => { - const outputFilename = 'outputReport-absolute.txt'; - const outputFilepath = join(__dirname, 'output', outputFilename); - const config = conf('error', { + it("should write results to absolute file with a same formatter", (done) => { + const outputFilename = "outputReport-absolute.txt"; + const outputFilepath = join(__dirname, "outputs", outputFilename); + const config = conf("error", { outputReport: { filePath: outputFilepath, }, @@ -44,7 +44,7 @@ describe('formatter write', () => { const compiler = webpack(config); compiler.run((err, stats) => { - const contents = readFileSync(outputFilepath, 'utf8'); + const contents = readFileSync(outputFilepath, "utf8"); expect(err).toBeNull(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/ignore.test.js b/test/ignore.test.js new file mode 100644 index 0000000..45a34e2 --- /dev/null +++ b/test/ignore.test.js @@ -0,0 +1,25 @@ +import eslint from "eslint"; +import ESLintError from "../src/ESLintError"; +import pack from "./utils/pack"; + +describe("eslintignore", () => { + it("should ignores files present in .eslintignore", async () => { + const pluginConfig = + Number.parseFloat(eslint.ESLint.version) >= 9 + ? { + ignore: true, + ignorePatterns: ["**/ignore.js"], + } + : { + ignore: true, + }; + + const compiler = pack("ignore", pluginConfig); + + const stats = await compiler.runAsync(); + expect(stats.hasWarnings()).toBe(false); + expect( + stats.compilation.errors.filter((x) => x instanceof ESLintError), + ).toEqual([]); + }); +}); diff --git a/test/lint-dirty-modules-only.test.js b/test/lint-dirty-modules-only.test.js index dc960c6..a09903c 100644 --- a/test/lint-dirty-modules-only.test.js +++ b/test/lint-dirty-modules-only.test.js @@ -1,14 +1,15 @@ -import { join } from 'path'; -import { writeFileSync } from 'fs'; +import { writeFileSync } from "node:fs"; +import { join } from "node:path"; -import { removeSync } from 'fs-extra'; +import { removeSync } from "fs-extra"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -const target = join(__dirname, 'fixtures', 'lint-dirty-modules-only-entry.js'); +const target = join(__dirname, "fixtures", "lint-dirty-modules-only-entry.js"); -describe('lint dirty modules only', () => { +describe("lint dirty modules only", () => { let watch; + afterEach(() => { if (watch) { watch.close(); @@ -16,35 +17,36 @@ describe('lint dirty modules only', () => { removeSync(target); }); - it('skips linting on initial run', (done) => { - writeFileSync(target, 'const foo = false\n'); + it("skips linting on initial run", (done) => { + writeFileSync(target, "const foo = false\n"); + // eslint-disable-next-line no-use-before-define let next = firstPass; - const compiler = pack('lint-dirty-modules-only', { + const compiler = pack("lint-dirty-modules-only", { lintDirtyModulesOnly: true, }); watch = compiler.watch({}, (err, stats) => next(err, stats)); - function firstPass(err, stats) { - expect(err).toBeNull(); - expect(stats.hasWarnings()).toBe(false); - expect(stats.hasErrors()).toBe(false); - - next = secondPass; - - writeFileSync(target, 'const bar = false;\n'); - } - function secondPass(err, stats) { expect(err).toBeNull(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); const { errors } = stats.compilation; - expect(errors.length).toBe(1); + expect(errors).toHaveLength(1); expect(stats.compilation.errors[0].message).toEqual( - expect.stringMatching('no-unused-vars'), + expect.stringMatching("no-unused-vars"), ); done(); } + + function firstPass(err, stats) { + expect(err).toBeNull(); + expect(stats.hasWarnings()).toBe(false); + expect(stats.hasErrors()).toBe(false); + + next = secondPass; + + writeFileSync(target, "const bar = false;\n"); + } }); }); diff --git a/test/mock/eslint/index.js b/test/mock/eslint/index.js index 4ee0b46..bedbf51 100644 --- a/test/mock/eslint/index.js +++ b/test/mock/eslint/index.js @@ -1,15 +1,15 @@ class ESLintMock { // Disabled because these are simplified mock methods. - // eslint-disable-next-line class-methods-use-this + async lintFiles() { return [ { - filePath: '', + filePath: "", messages: [ { - ruleId: 'no-undef', + ruleId: "no-undef", severity: 2, - message: 'Fake error', + message: "Fake error", line: 1, column: 11, }, @@ -18,11 +18,11 @@ class ESLintMock { warningCount: 0, fixableErrorCount: 0, fixableWarningCount: 0, - source: '', + source: "", }, ]; } - // eslint-disable-next-line class-methods-use-this + async loadFormatter() { return { format(results) { @@ -32,6 +32,9 @@ class ESLintMock { } } +ESLintMock.version = "9"; + module.exports = { ESLint: ESLintMock, + loadESLint: async () => ESLintMock, }; diff --git a/test/mock/formatter/index.js b/test/mock/formatter/index.js index bd8a6fa..8d5e10c 100644 --- a/test/mock/formatter/index.js +++ b/test/mock/formatter/index.js @@ -1,6 +1,6 @@ module.exports = function format(results) { return JSON.stringify({ - formatter: 'mock', + formatter: "mock", results, }); }; diff --git a/test/multiple-instances.test.js b/test/multiple-instances.test.js index 3d86942..98813ec 100644 --- a/test/multiple-instances.test.js +++ b/test/multiple-instances.test.js @@ -1,23 +1,33 @@ -import ESLintPlugin from '../src'; +import { join } from "node:path"; +import eslint from "eslint"; +import ESLintPlugin from "../src"; +import pack from "./utils/pack"; -import pack from './utils/pack'; +const configType = + Number.parseFloat(eslint.ESLint.version) >= 9 ? "flat" : "eslintrc"; +const config = + Number.parseFloat(eslint.ESLint.version) >= 9 + ? join(__dirname, "./config-for-tests/eslint.config.mjs") + : join(__dirname, "./config-for-tests/.eslintrc.js"); -describe('multiple instances', () => { +describe("multiple instances", () => { it("should don't fail", async () => { const compiler = pack( - 'multiple', + "multiple", {}, { plugins: [ new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'error.js', + exclude: "error.js", }), new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'error.js', + exclude: "error.js", }), ], }, @@ -28,49 +38,53 @@ describe('multiple instances', () => { expect(stats.hasErrors()).toBe(false); }); - it('should fail on first instance', async () => { + it("should fail on first instance", async () => { const compiler = pack( - 'multiple', + "multiple", {}, { plugins: [ new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'good.js', + exclude: "good.js", }), new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'error.js', + exclude: "error.js", }), ], }, ); - await expect(compiler.runAsync()).rejects.toThrow(); + await expect(compiler.runAsync()).rejects.toThrow("error.js"); }); - it('should fail on second instance', async () => { + it("should fail on second instance", async () => { const compiler = pack( - 'multiple', + "multiple", {}, { plugins: [ new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'error.js', + exclude: "error.js", }), new ESLintPlugin({ - configType: 'eslintrc', + configType, + overrideConfigFile: config, ignore: false, - exclude: 'good.js', + exclude: "good.js", }), ], }, ); - await expect(compiler.runAsync()).rejects.toThrow(); + await expect(compiler.runAsync()).rejects.toThrow("error.js"); }); }); diff --git a/test/ok.test.js b/test/ok.test.js index 4336711..73faad9 100644 --- a/test/ok.test.js +++ b/test/ok.test.js @@ -1,8 +1,8 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('ok', () => { +describe("ok", () => { it("should don't throw error if file is ok", async () => { - const compiler = pack('good'); + const compiler = pack("good"); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/parameters.test.js b/test/parameters.test.js index 1c8044f..58029a7 100644 --- a/test/parameters.test.js +++ b/test/parameters.test.js @@ -1,13 +1,13 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('parameters', () => { - it('should supports query strings parameters', async () => { +describe("parameters", () => { + it("should supports query strings parameters", async () => { const loaderOptions = { overrideConfig: { rules: { semi: 0 }, }, }; - const compiler = pack('good', loaderOptions); + const compiler = pack("good", loaderOptions); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/query.test.js b/test/query.test.js index 0210ebf..d6a11af 100644 --- a/test/query.test.js +++ b/test/query.test.js @@ -1,14 +1,14 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('query', () => { - it('should correctly resolve file despite query path', async () => { +describe("query", () => { + it("should correctly resolve file despite query path", async () => { const compiler = pack( - 'query', + "query", {}, { resolve: { alias: { - 'alias-ignore': false, + "alias-ignore": false, }, }, }, diff --git a/test/quiet.test.js b/test/quiet.test.js index 11c3cb8..fb3cb33 100644 --- a/test/quiet.test.js +++ b/test/quiet.test.js @@ -1,16 +1,16 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('quiet', () => { - it('should not emit warnings if quiet is set', async () => { - const compiler = pack('warn', { quiet: true }); +describe("quiet", () => { + it("should not emit warnings if quiet is set", async () => { + const compiler = pack("warn", { quiet: true }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(false); }); - it('should emit errors, but not emit warnings if quiet is set', async () => { - const compiler = pack('full-of-problems', { quiet: true }); + it("should emit errors, but not emit warnings if quiet is set", async () => { + const compiler = pack("full-of-problems", { quiet: true }); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(false); diff --git a/test/resource-query.test.js b/test/resource-query.test.js index 49b40b1..ff5d8ec 100644 --- a/test/resource-query.test.js +++ b/test/resource-query.test.js @@ -1,15 +1,15 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('resource-query', () => { - it('should exclude the match resource query', async () => { +describe("resource-query", () => { + it("should exclude the match resource query", async () => { const compiler = pack( - 'resource-query', + "resource-query", { resourceQueryExclude: /media/, - extensions: ['.js', '.ts'], + extensions: [".js", ".ts"], }, { - module: { rules: [{ resourceQuery: /media/, type: 'asset/source' }] }, + module: { rules: [{ resourceQuery: /media/, type: "asset/source" }] }, }, ); diff --git a/test/symbols.test.js b/test/symbols.test.js index 34ce638..36581f8 100644 --- a/test/symbols.test.js +++ b/test/symbols.test.js @@ -1,17 +1,17 @@ -import { join } from 'path'; +import { join } from "node:path"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('symbols', () => { +describe("symbols", () => { afterEach(() => { jest.restoreAllMocks(); }); - it('should return error', async () => { + it("should return error", async () => { const compiler = pack( - 'symbols', + "symbols", {}, - { context: join(__dirname, 'fixtures/[symbols]') }, + { context: join(__dirname, "fixtures/[symbols]") }, ); const stats = await compiler.runAsync(); diff --git a/test/threads.test.js b/test/threads.test.js index 9cceca0..cd89a65 100644 --- a/test/threads.test.js +++ b/test/threads.test.js @@ -1,12 +1,12 @@ /* eslint-env jest */ -import { join } from 'path'; +import { join } from "node:path"; +import eslint from "eslint"; +import { loadESLint, loadESLintThreaded } from "../src/getESLint"; -import { loadESLint, loadESLintThreaded } from '../src/getESLint'; - -describe('Threading', () => { - test('Threaded interface should look like non-threaded interface', async () => { +describe("Threading", () => { + it("threaded interface should look like non-threaded interface", async () => { const single = await loadESLint({}); - const threaded = await loadESLintThreaded('foo', 1, {}); + const threaded = await loadESLintThreaded("foo", 1, {}); for (const key of Object.keys(single)) { expect(typeof single[key]).toEqual(typeof threaded[key]); } @@ -20,12 +20,20 @@ describe('Threading', () => { threaded.cleanup(); }); - test('Threaded should lint files', async () => { - const threaded = await loadESLintThreaded('bar', 1, { ignore: false }); + it("threaded should lint files", async () => { + const threaded = await loadESLintThreaded("bar", 1, { + ignore: false, + configType: + Number.parseFloat(eslint.ESLint.version) >= 9 ? "flat" : "eslintrc", + overrideConfigFile: + Number.parseFloat(eslint.ESLint.version) >= 9 + ? join(__dirname, "./config-for-tests/eslint.config.mjs") + : join(__dirname, "./config-for-tests/.eslintrc.js"), + }); try { const [good, bad] = await Promise.all([ - threaded.lintFiles(join(__dirname, 'fixtures/good.js')), - threaded.lintFiles(join(__dirname, 'fixtures/error.js')), + threaded.lintFiles(join(__dirname, "fixtures/good.js")), + threaded.lintFiles(join(__dirname, "fixtures/error.js")), ]); expect(good[0].errorCount).toBe(0); expect(good[0].warningCount).toBe(0); @@ -36,34 +44,33 @@ describe('Threading', () => { } }); - describe('worker coverage', () => { + describe("worker coverage", () => { beforeEach(() => { jest.resetModules(); }); - test('worker can start', async () => { + it("worker can start", async () => { const mockThread = { parentPort: { on: jest.fn() }, workerData: {} }; const mockLintFiles = jest.fn(); - jest.mock('eslint', () => { - return { - ESLint: Object.assign( - function ESLint() { - this.lintFiles = mockLintFiles; - }, - { - outputFixes: jest.fn(), - }, - ), - }; - }); - jest.mock('worker_threads', () => mockThread); - const { setup, lintFiles } = require('../src/worker'); + jest.mock("eslint", () => ({ + ESLint: Object.assign( + function ESLint() { + this.lintFiles = mockLintFiles; + }, + { + outputFixes: jest.fn(), + }, + ), + })); + jest.mock("worker_threads", () => mockThread); + + const { lintFiles, setup } = require("../src/worker"); await setup({}); - await lintFiles('foo'); - expect(mockLintFiles).toHaveBeenCalledWith('foo'); + await lintFiles("foo"); + expect(mockLintFiles).toHaveBeenCalledWith("foo"); await setup({ eslintOptions: { fix: true } }); - await lintFiles('foo'); + await lintFiles("foo"); }); }); }); diff --git a/test/utils.test.js b/test/utils.test.js index a13ee4c..b1a7c48 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -1,53 +1,52 @@ -import { parseFoldersToGlobs, parseFiles } from '../src/utils'; +import { parseFiles, parseFoldersToGlobs } from "../src/utils"; -jest.mock('fs', () => { - return { - statSync(pattern) { - return { - isDirectory() { - return pattern.indexOf('/path/') === 0; - }, - }; - }, - }; -}); +jest.mock("fs", () => ({ + statSync(pattern) { + return { + isDirectory() { + return pattern.indexOf("/path/") === 0; + }, + }; + }, +})); -test('parseFiles should return relative files from context', () => { - expect( - parseFiles( - ['**/*', '../package-a/src/**/', '../package-b/src/**/'], - 'main/src', - ), - ).toEqual( - expect.arrayContaining([ - expect.stringContaining('main/src/**/*'), - expect.stringContaining('main/package-a/src/**'), - expect.stringContaining('main/package-b/src/**'), - ]), - ); -}); +describe("utils", () => { + it("parseFiles should return relative files from context", () => { + expect( + parseFiles( + ["**/*", "../package-a/src/**/", "../package-b/src/**/"], + "main/src", + ), + ).toEqual( + expect.arrayContaining([ + expect.stringContaining("main/src/**/*"), + expect.stringContaining("main/package-a/src/**"), + expect.stringContaining("main/package-b/src/**"), + ]), + ); + }); -test('parseFoldersToGlobs should return globs for folders', () => { - const withoutSlash = '/path/to/code'; - const withSlash = `${withoutSlash}/`; + it("parseFoldersToGlobs should return globs for folders", () => { + const withoutSlash = "/path/to/code"; + const withSlash = `${withoutSlash}/`; - expect(parseFoldersToGlobs(withoutSlash, 'js')).toMatchInlineSnapshot(` + expect(parseFoldersToGlobs(withoutSlash, "js")).toMatchInlineSnapshot(` [ "/path/to/code/**/*.js", ] `); - expect(parseFoldersToGlobs(withSlash, 'js')).toMatchInlineSnapshot(` + expect(parseFoldersToGlobs(withSlash, "js")).toMatchInlineSnapshot(` [ "/path/to/code/**/*.js", ] `); - expect( - parseFoldersToGlobs( - [withoutSlash, withSlash, '/some/file.js'], - ['js', 'cjs', 'mjs'], - ), - ).toMatchInlineSnapshot(` + expect( + parseFoldersToGlobs( + [withoutSlash, withSlash, "/some/file.js"], + ["js", "cjs", "mjs"], + ), + ).toMatchInlineSnapshot(` [ "/path/to/code/**/*.{js,cjs,mjs}", "/path/to/code/**/*.{js,cjs,mjs}", @@ -55,23 +54,24 @@ test('parseFoldersToGlobs should return globs for folders', () => { ] `); - expect(parseFoldersToGlobs(withoutSlash)).toMatchInlineSnapshot(` + expect(parseFoldersToGlobs(withoutSlash)).toMatchInlineSnapshot(` [ "/path/to/code/**", ] `); - expect(parseFoldersToGlobs(withSlash)).toMatchInlineSnapshot(` + expect(parseFoldersToGlobs(withSlash)).toMatchInlineSnapshot(` [ "/path/to/code/**", ] `); -}); + }); -test('parseFoldersToGlobs should return unmodified globs for globs (ignoring extensions)', () => { - expect(parseFoldersToGlobs('**.notjs', 'js')).toMatchInlineSnapshot(` + it("parseFoldersToGlobs should return unmodified globs for globs (ignoring extensions)", () => { + expect(parseFoldersToGlobs("**.notjs", "js")).toMatchInlineSnapshot(` [ "**.notjs", ] `); + }); }); diff --git a/test/utils/conf.js b/test/utils/conf.js index 806822f..96c6ef6 100644 --- a/test/utils/conf.js +++ b/test/utils/conf.js @@ -1,23 +1,30 @@ -import { join } from 'path'; +import { join } from "node:path"; +import eslint from "eslint"; -import ESLintPlugin from '../../src'; +import ESLintPlugin from "../../src"; export default (entry, pluginConf = {}, webpackConf = {}) => { - const testDir = join(__dirname, '..'); + const testDir = join(__dirname, ".."); return { entry: `./${entry}-entry.js`, - context: join(testDir, 'fixtures'), - mode: 'development', + context: join(testDir, "fixtures"), + mode: "development", output: { - path: join(testDir, 'output'), + path: join(testDir, "outputs"), }, plugins: [ new ESLintPlugin({ - configType: 'eslintrc', + // Do not cache for tests + cache: false, + configType: + Number.parseFloat(eslint.ESLint.version) >= 9 ? "flat" : "eslintrc", + overrideConfigFile: + Number.parseFloat(eslint.ESLint.version) >= 9 + ? join(testDir, "./config-for-tests/eslint.config.mjs") + : join(testDir, "./config-for-tests/.eslintrc.js"), // this disables the use of .eslintignore, since it contains the fixtures // folder to skip it on the global linting, but here we want the opposite - // (we only use .eslintignore on the test that checks this) ignore: false, // TODO: update tests to run both states: test.each([[{threads: false}], [{threads: true}]])('it should...', async ({threads}) => {...}) threads: true, diff --git a/test/utils/pack.js b/test/utils/pack.js index acba716..abb1930 100644 --- a/test/utils/pack.js +++ b/test/utils/pack.js @@ -1,13 +1,13 @@ -import webpack from 'webpack'; +import webpack from "webpack"; -import conf from './conf'; +import conf from "./conf"; /** * new a test webpack compiler - * @param {String} context - * @param {import('../../src/options').Options} pluginConf - * @param {webpack.Configuration} webpackConf - * @returns {ReturnType} + * @param {string} context context + * @param {import('../../src/options').Options} pluginConf plugin options + * @param {webpack.Configuration} webpackConf webpack configuration + * @returns {ReturnType} return result from webpack */ export default (context, pluginConf = {}, webpackConf = {}) => { const compiler = webpack(conf(context, pluginConf, webpackConf)); diff --git a/test/warning.test.js b/test/warning.test.js index d378f4c..ca0ba3c 100644 --- a/test/warning.test.js +++ b/test/warning.test.js @@ -1,8 +1,8 @@ -import pack from './utils/pack'; +import pack from "./utils/pack"; -describe('warning', () => { - it('should emit warnings', async () => { - const compiler = pack('warn'); +describe("warning", () => { + it("should emit warnings", async () => { + const compiler = pack("warn"); const stats = await compiler.runAsync(); expect(stats.hasWarnings()).toBe(true); diff --git a/test/watch.test.js b/test/watch.test.js index dd58dde..76ac2dd 100644 --- a/test/watch.test.js +++ b/test/watch.test.js @@ -1,18 +1,19 @@ -import { join } from 'path'; -import { writeFileSync } from 'fs'; +import { writeFileSync } from "node:fs"; +import { join } from "node:path"; -import { removeSync } from 'fs-extra'; +import { removeSync } from "fs-extra"; -import pack from './utils/pack'; +import pack from "./utils/pack"; -const target = join(__dirname, 'fixtures', 'watch-entry.js'); -const target2 = join(__dirname, 'fixtures', 'watch-leaf.js'); +const target = join(__dirname, "fixtures", "watch-entry.js"); +const target2 = join(__dirname, "fixtures", "watch-leaf.js"); const targetExpectedPattern = expect.stringMatching( - target.replace(/\\/g, '\\\\'), + target.replaceAll("\\", "\\\\"), ); -describe('watch', () => { +describe("watch", () => { let watch; + afterEach(() => { if (watch) { watch.close(); @@ -21,8 +22,8 @@ describe('watch', () => { removeSync(target2); }); - it('should watch', (done) => { - const compiler = pack('good'); + it("should watch", (done) => { + const compiler = pack("good"); watch = compiler.watch({}, (err, stats) => { expect(err).toBeNull(); @@ -32,29 +33,41 @@ describe('watch', () => { }); }); - it('should watch with unique messages', (done) => { - writeFileSync(target, 'var foo = stuff\n'); + it("should watch with unique messages", (done) => { + writeFileSync(target, "var foo = stuff\n"); + // eslint-disable-next-line no-use-before-define let next = firstPass; - const compiler = pack('watch'); + const compiler = pack("watch"); watch = compiler.watch({}, (err, stats) => next(err, stats)); - function firstPass(err, stats) { + function finish(err, stats) { + expect(err).toBeNull(); + expect(stats.hasWarnings()).toBe(false); + const { errors } = stats.compilation; + const [{ message }] = errors; + expect(stats.hasErrors()).toBe(true); + expect(message).toEqual(expect.stringMatching("prefer-const")); + done(); + } + + function thirdPass(err, stats) { expect(err).toBeNull(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); const { errors } = stats.compilation; - expect(errors.length).toBe(1); + expect(errors).toHaveLength(1); const [{ message }] = errors; expect(message).toEqual(targetExpectedPattern); - expect(message).toEqual(expect.stringMatching('\\(3 errors,')); + expect(message).toEqual(expect.stringMatching("no-unused-vars")); + // `prefer-const` fails here + expect(message).toEqual(expect.stringMatching("prefer-const")); - next = secondPass; + next = finish; - writeFileSync(target2, 'let bar = false;\n'); writeFileSync( target, - "const x = require('./watch-leaf')\n\nconst foo = false;\n", + "/* eslint-disable no-unused-vars */\nconst foo = false;\n", ); } @@ -63,13 +76,13 @@ describe('watch', () => { expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); const { errors } = stats.compilation; - expect(errors.length).toBe(1); + expect(errors).toHaveLength(1); const [{ message }] = errors; expect(message).toEqual(targetExpectedPattern); - expect(message).toEqual(expect.stringMatching('no-unused-vars')); + expect(message).toEqual(expect.stringMatching("no-unused-vars")); // `prefer-const` passes here - expect(message).toEqual(expect.stringMatching('prefer-const')); - expect(message).toEqual(expect.stringMatching('\\(4 errors,')); + expect(message).toEqual(expect.stringMatching("prefer-const")); + expect(message).toEqual(expect.stringMatching("\\(4 errors,")); next = thirdPass; @@ -79,34 +92,23 @@ describe('watch', () => { ); } - function thirdPass(err, stats) { + function firstPass(err, stats) { expect(err).toBeNull(); expect(stats.hasWarnings()).toBe(false); expect(stats.hasErrors()).toBe(true); const { errors } = stats.compilation; - expect(errors.length).toBe(1); + expect(errors).toHaveLength(1); const [{ message }] = errors; expect(message).toEqual(targetExpectedPattern); - expect(message).toEqual(expect.stringMatching('no-unused-vars')); - // `prefer-const` fails here - expect(message).toEqual(expect.stringMatching('prefer-const')); + expect(message).toEqual(expect.stringMatching("\\(3 errors,")); - next = finish; + next = secondPass; + writeFileSync(target2, "let bar = false;\n"); writeFileSync( target, - '/* eslint-disable no-unused-vars */\nconst foo = false;\n', + "const x = require('./watch-leaf')\n\nconst foo = false;\n", ); } - - function finish(err, stats) { - expect(err).toBeNull(); - expect(stats.hasWarnings()).toBe(false); - const { errors } = stats.compilation; - const [{ message }] = errors; - expect(stats.hasErrors()).toBe(true); - expect(message).toEqual(expect.stringMatching('prefer-const')); - done(); - } }); }); diff --git a/types/ESLintError.d.ts b/types/ESLintError.d.ts index 229a683..ff953c2 100644 --- a/types/ESLintError.d.ts +++ b/types/ESLintError.d.ts @@ -1,7 +1,7 @@ export = ESLintError; declare class ESLintError extends Error { /** - * @param {string=} messages + * @param {string=} messages messages */ constructor(messages?: string | undefined); stack: string; diff --git a/types/getESLint.d.ts b/types/getESLint.d.ts index 1b494cd..30e355e 100644 --- a/types/getESLint.d.ts +++ b/types/getESLint.d.ts @@ -1,6 +1,6 @@ -export type ESLint = import('eslint').ESLint; -export type LintResult = import('eslint').ESLint.LintResult; -export type Options = import('./options').Options; +export type ESLint = import("eslint").ESLint; +export type LintResult = import("eslint").ESLint.LintResult; +export type Options = import("./options").Options; export type AsyncTask = () => Promise; export type LintTask = (files: string | string[]) => Promise; export type Linter = { @@ -12,6 +12,15 @@ export type Linter = { export type Worker = JestWorker & { lintFiles: LintTask; }; +/** + * @param {string | undefined} key a cache key + * @param {Options} options options + * @returns {Promise} linter + */ +export function getESLint( + key: string | undefined, + { threads, ...options }: Options, +): Promise; /** @typedef {import('eslint').ESLint} ESLint */ /** @typedef {import('eslint').ESLint.LintResult} LintResult */ /** @typedef {import('./options').Options} Options */ @@ -20,28 +29,19 @@ export type Worker = JestWorker & { /** @typedef {{threads: number, eslint: ESLint, lintFiles: LintTask, cleanup: AsyncTask}} Linter */ /** @typedef {JestWorker & {lintFiles: LintTask}} Worker */ /** - * @param {Options} options - * @returns {Promise} + * @param {Options} options options + * @returns {Promise} linter */ export function loadESLint(options: Options): Promise; /** - * @param {string|undefined} key - * @param {number} poolSize - * @param {Options} options - * @returns {Promise} + * @param {string | undefined} key a cache key + * @param {number} poolSize number of workers + * @param {Options} options options + * @returns {Promise} linter */ export function loadESLintThreaded( key: string | undefined, poolSize: number, options: Options, ): Promise; -/** - * @param {string|undefined} key - * @param {Options} options - * @returns {Promise} - */ -export function getESLint( - key: string | undefined, - { threads, ...options }: Options, -): Promise; -import { Worker as JestWorker } from 'jest-worker'; +import { Worker as JestWorker } from "jest-worker"; diff --git a/types/index.d.ts b/types/index.d.ts index 6e522b2..37dfd25 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,41 +1,40 @@ export = ESLintWebpackPlugin; declare class ESLintWebpackPlugin { /** - * @param {Options} options + * @param {Options=} options options */ - constructor(options?: Options); + constructor(options?: Options | undefined); key: string; - options: import('./options').PluginOptions; + options: import("./options").PluginOptions; /** - * @param {Compiler} compiler - * @param {Omit & {resourceQueryExclude: RegExp[]}} options - * @param {string[]} wanted - * @param {string[]} exclude + * @param {Compiler} compiler compiler + * @param {Omit & { resourceQueryExclude: RegExp[] }} options options + * @param {string[]} wanted wanted files + * @param {string[]} exclude excluded files */ run( compiler: Compiler, - options: Omit & { + options: Omit & { resourceQueryExclude: RegExp[]; }, wanted: string[], exclude: string[], ): Promise; /** - * @param {Compiler} compiler + * @param {Compiler} compiler compiler * @returns {void} */ apply(compiler: Compiler): void; /** - * - * @param {Compiler} compiler - * @returns {string} + * @param {Compiler} compiler compiler + * @returns {string} context */ getContext(compiler: Compiler): string; } declare namespace ESLintWebpackPlugin { export { Compiler, Module, NormalModule, Options }; } -type Compiler = import('webpack').Compiler; -type Module = import('webpack').Module; -type NormalModule = import('webpack').NormalModule; -type Options = import('./options').Options; +type Compiler = import("webpack").Compiler; +type Module = import("webpack").Module; +type NormalModule = import("webpack").NormalModule; +type Options = import("./options").Options; diff --git a/types/linter.d.ts b/types/linter.d.ts index 977999a..dfaeaf9 100644 --- a/types/linter.d.ts +++ b/types/linter.d.ts @@ -1,9 +1,9 @@ export = linter; /** - * @param {string|undefined} key - * @param {Options} options - * @param {Compilation} compilation - * @returns {Promise<{lint: Linter, report: Reporter, threads: number}>} + * @param {string | undefined} key a cache key + * @param {Options} options options + * @param {Compilation} compilation compilation + * @returns {Promise<{lint: Linter, report: Reporter, threads: number}>} linter with additional functions */ declare function linter( key: string | undefined, @@ -30,13 +30,13 @@ declare namespace linter { LintResultMap, }; } -type ESLint = import('eslint').ESLint; -type Formatter = import('eslint').ESLint.Formatter; -type LintResult = import('eslint').ESLint.LintResult; -type Compiler = import('webpack').Compiler; -type Compilation = import('webpack').Compilation; -type Options = import('./options').Options; -type FormatterFunction = import('./options').FormatterFunction; +type ESLint = import("eslint").ESLint; +type Formatter = import("eslint").ESLint.Formatter; +type LintResult = import("eslint").ESLint.LintResult; +type Compiler = import("webpack").Compiler; +type Compilation = import("webpack").Compilation; +type Options = import("./options").Options; +type FormatterFunction = import("./options").FormatterFunction; type GenerateReport = (compilation: Compilation) => Promise; type Report = { errors?: ESLintError; @@ -48,4 +48,4 @@ type Linter = (files: string | string[]) => void; type LintResultMap = { [files: string]: LintResult; }; -import ESLintError = require('./ESLintError'); +import ESLintError = require("./ESLintError"); diff --git a/types/options.d.ts b/types/options.d.ts index 3ea14a2..1a2c79f 100644 --- a/types/options.d.ts +++ b/types/options.d.ts @@ -1,70 +1,127 @@ -export type ESLintOptions = import('eslint').ESLint.Options; -export type LintResult = import('eslint').ESLint.LintResult; +export type ESLintOptions = import("eslint").ESLint.Options; +export type LintResult = import("eslint").ESLint.LintResult; export type FormatterFunction = (results: LintResult[]) => string; export type OutputReport = { + /** + * a file path + */ filePath?: string | undefined; + /** + * a formatter + */ formatter?: (string | FormatterFunction) | undefined; }; export type PluginOptions = { + /** + * a string indicating the root of your files + */ context?: string | undefined; + /** + * the errors found will always be emitted + */ emitError?: boolean | undefined; + /** + * the warnings found will always be emitted + */ emitWarning?: boolean | undefined; - eslintPath?: string | undefined; + /** + * specify the files and/or directories to exclude + */ exclude?: (string | string[]) | undefined; + /** + * specify the extensions that should be checked + */ extensions?: (string | string[]) | undefined; + /** + * will cause the module build to fail if there are any errors + */ failOnError?: boolean | undefined; + /** + * will cause the module build to fail if there are any warning + */ failOnWarning?: boolean | undefined; + /** + * specify directories, files, or globs + */ files?: (string | string[]) | undefined; + /** + * apply fixes + */ fix?: boolean | undefined; + /** + * specify the formatter you would like to use to format your results + */ formatter?: (string | FormatterFunction) | undefined; + /** + * lint only changed files, skip linting on start + */ lintDirtyModulesOnly?: boolean | undefined; + /** + * will process and report errors only and ignore warnings + */ quiet?: boolean | undefined; + /** + * path to `eslint` instance that will be used for linting + */ + eslintPath?: string | undefined; + /** + * writes the output of the errors to a file - for example, a `json` file for use for reporting + */ outputReport?: OutputReport | undefined; + /** + * number of worker threads + */ threads?: (number | boolean) | undefined; + /** + * Specify the resource query to exclude + */ resourceQueryExclude?: (RegExp | RegExp[]) | undefined; + /** + * config type + */ configType?: string | undefined; }; export type Options = PluginOptions & ESLintOptions; +/** + * @param {Options} loaderOptions loader options + * @returns {ESLintOptions} eslint options + */ +export function getESLintOptions(loaderOptions: Options): ESLintOptions; /** @typedef {import("eslint").ESLint.Options} ESLintOptions */ /** @typedef {import('eslint').ESLint.LintResult} LintResult */ /** * @callback FormatterFunction - * @param {LintResult[]} results - * @returns {string} + * @param {LintResult[]} results results + * @returns {string} formatted result */ /** - * @typedef {Object} OutputReport - * @property {string=} filePath - * @property {string|FormatterFunction=} formatter + * @typedef {object} OutputReport + * @property {string=} filePath a file path + * @property {string | FormatterFunction=} formatter a formatter */ /** - * @typedef {Object} PluginOptions - * @property {string=} context - * @property {boolean=} emitError - * @property {boolean=} emitWarning - * @property {string=} eslintPath - * @property {string|string[]=} exclude - * @property {string|string[]=} extensions - * @property {boolean=} failOnError - * @property {boolean=} failOnWarning - * @property {string|string[]=} files - * @property {boolean=} fix - * @property {string|FormatterFunction=} formatter - * @property {boolean=} lintDirtyModulesOnly - * @property {boolean=} quiet - * @property {OutputReport=} outputReport - * @property {number|boolean=} threads - * @property {RegExp|RegExp[]=} resourceQueryExclude - * @property {string=} configType + * @typedef {object} PluginOptions + * @property {string=} context a string indicating the root of your files + * @property {boolean=} emitError the errors found will always be emitted + * @property {boolean=} emitWarning the warnings found will always be emitted + * @property {string | string[]=} exclude specify the files and/or directories to exclude + * @property {string | string[]=} extensions specify the extensions that should be checked + * @property {boolean=} failOnError will cause the module build to fail if there are any errors + * @property {boolean=} failOnWarning will cause the module build to fail if there are any warning + * @property {string | string[]=} files specify directories, files, or globs + * @property {boolean=} fix apply fixes + * @property {string | FormatterFunction=} formatter specify the formatter you would like to use to format your results + * @property {boolean=} lintDirtyModulesOnly lint only changed files, skip linting on start + * @property {boolean=} quiet will process and report errors only and ignore warnings + * @property {string=} eslintPath path to `eslint` instance that will be used for linting + * @property {OutputReport=} outputReport writes the output of the errors to a file - for example, a `json` file for use for reporting + * @property {number | boolean=} threads number of worker threads + * @property {RegExp | RegExp[]=} resourceQueryExclude Specify the resource query to exclude + * @property {string=} configType config type */ /** @typedef {PluginOptions & ESLintOptions} Options */ /** - * @param {Options} pluginOptions - * @returns {PluginOptions} + * @param {Options} pluginOptions plugin options + * @returns {PluginOptions} normalized plugin options */ export function getOptions(pluginOptions: Options): PluginOptions; -/** - * @param {Options} loaderOptions - * @returns {ESLintOptions} - */ -export function getESLintOptions(loaderOptions: Options): ESLintOptions; diff --git a/types/utils.d.ts b/types/utils.d.ts index 80827bd..082d8cc 100644 --- a/types/utils.d.ts +++ b/types/utils.d.ts @@ -1,21 +1,4 @@ -/** - * @template T - * @param {T} value - * @return { - T extends (null | undefined) - ? [] - : T extends string - ? [string] - : T extends readonly unknown[] - ? T - : T extends Iterable - ? T[] - : [T] - } - */ -export function arrify( - value: T, -): T extends null | undefined +export type ArrifyResult = T extends null | undefined ? [] : T extends string ? [string] @@ -24,23 +7,48 @@ export function arrify( : T extends Iterable ? T_1[] : [T]; +export type EXPECTED_ANY = any; +/** + * @template T + * @typedef {T extends (null | undefined) + * ? [] + * : T extends string + * ? [string] + * : T extends readonly unknown[] + * ? T + * : T extends Iterable + * ? T[] + * : [T]} ArrifyResult + */ /** - * @param {string|string[]} files - * @param {string} context - * @returns {string[]} + * @template T + * @param {T} value value + * @returns {ArrifyResult} array of values + */ +export function arrify(value: T): ArrifyResult; +/** + * @param {string} _ key, but unused + * @param {EXPECTED_ANY} value value + * @returns {{ [x: string]: EXPECTED_ANY }} result + */ +export function jsonStringifyReplacerSortKeys( + _: string, + value: EXPECTED_ANY, +): { + [x: string]: EXPECTED_ANY; +}; +/** + * @param {string | string[]} files files + * @param {string} context context + * @returns {string[]} normalized paths */ export function parseFiles(files: string | string[], context: string): string[]; /** - * @param {string|string[]} patterns - * @param {string|string[]} extensions - * @returns {string[]} + * @param {string | string[]} patterns patterns + * @param {string | string[]} extensions extensions + * @returns {string[]} globs */ export function parseFoldersToGlobs( patterns: string | string[], extensions?: string | string[], ): string[]; -/** - * @param {string} _ key, but unused - * @param {any} value - */ -export function jsonStringifyReplacerSortKeys(_: string, value: any): any; diff --git a/types/worker.d.ts b/types/worker.d.ts index 5a4e683..cbefe06 100644 --- a/types/worker.d.ts +++ b/types/worker.d.ts @@ -1,18 +1,28 @@ -export type setupOptions = { - /** - * - import path of eslint - */ - eslintPath?: string | undefined; - configType?: string | undefined; - /** - * - linter options - */ - eslintOptions: ESLintOptions; -}; -export type ESLint = import('eslint').ESLint; -export type ESLintOptions = import('eslint').ESLint.Options; -export type LintResult = import('eslint').ESLint.LintResult; +export type ESLint = import("eslint").ESLint; +export type ESLintOptions = import("eslint").ESLint.Options; +export type LintResult = import("eslint").ESLint.LintResult; export type ESLintClass = { new (arg0: ESLintOptions): ESLint; outputFixes: (arg0: LintResult[]) => any; }; +/** + * @param {string | string[]} files files + * @returns {Promise} lint results + */ +export function lintFiles(files: string | string[]): Promise; +/** + * @param {object} options setup worker + * @param {string=} options.eslintPath import path of eslint + * @param {string=} options.configType a config type + * @param {ESLintOptions} options.eslintOptions linter options + * @returns {ESLint} eslint + */ +export function setup({ + eslintPath, + configType, + eslintOptions, +}: { + eslintPath?: string | undefined; + configType?: string | undefined; + eslintOptions: ESLintOptions; +}): ESLint;