diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..abe810c5 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +__fixtures__/ +dist/ diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a09ea6ea..896807e1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -19,7 +19,8 @@ jobs: - name: Lint and test run: | yarn install --frozen-lockfile - yarn prepublishOnly + yarn build yarn lint yarn prettier --check '**/*' yarn test + yarn test:integration diff --git a/.gitignore b/.gitignore index aab752e0..9a0c8974 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /.husky/ /.idea/ /dist/ -/node_modules/ +node_modules /docs/.vitepress/dist /docs/.vitepress/cache yarn-error.log diff --git a/.prettierignore b/.prettierignore index 1559e0d8..3f7e7daa 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ .eslintcache +.eslintignore .gitignore .husky .npmignore @@ -6,3 +7,4 @@ LICENSE yarn.lock dist +__fixtures__ diff --git a/__tests__/integrations/__fixtures__/flat-config/.npmrc b/__tests__/integrations/__fixtures__/flat-config/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/__tests__/integrations/__fixtures__/flat-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/__tests__/integrations/__fixtures__/flat-config/a.vue b/__tests__/integrations/__fixtures__/flat-config/a.vue new file mode 100644 index 00000000..6f0b8f75 --- /dev/null +++ b/__tests__/integrations/__fixtures__/flat-config/a.vue @@ -0,0 +1,11 @@ + + + diff --git a/__tests__/integrations/__fixtures__/flat-config/eslint.config.js b/__tests__/integrations/__fixtures__/flat-config/eslint.config.js new file mode 100644 index 00000000..5ae8ab92 --- /dev/null +++ b/__tests__/integrations/__fixtures__/flat-config/eslint.config.js @@ -0,0 +1,10 @@ +import plugin from "eslint-plugin-vuejs-accessibility"; + +export default [ + ...plugin.configs["flat/recommended"], + { + rules: { + "vuejs-accessibility/alt-text": "warn" + } + } +]; diff --git a/__tests__/integrations/__fixtures__/flat-config/package.json b/__tests__/integrations/__fixtures__/flat-config/package.json new file mode 100644 index 00000000..ce85990d --- /dev/null +++ b/__tests__/integrations/__fixtures__/flat-config/package.json @@ -0,0 +1,11 @@ +{ + "private": true, + "name": "integration-test-for-flat-config", + "type": "module", + "version": "1.0.0", + "description": "Integration test for flat config", + "dependencies": { + "eslint": "^9.0.0", + "eslint-plugin-vuejs-accessibility": "file:../../../.." + } +} diff --git a/__tests__/integrations/__fixtures__/legacy-config/.eslintrc.json b/__tests__/integrations/__fixtures__/legacy-config/.eslintrc.json new file mode 100644 index 00000000..b8124b09 --- /dev/null +++ b/__tests__/integrations/__fixtures__/legacy-config/.eslintrc.json @@ -0,0 +1,13 @@ +{ + "root": true, + "extends": ["plugin:vuejs-accessibility/recommended"], + "plugins": ["vuejs-accessibility"], + "parser": "vue-eslint-parser", + "parserOptions": { + "sourceType": "module", + "ecmaVersion": 2019 + }, + "rules": { + "vuejs-accessibility/alt-text": "warn" + } +} diff --git a/__tests__/integrations/__fixtures__/legacy-config/.npmrc b/__tests__/integrations/__fixtures__/legacy-config/.npmrc new file mode 100644 index 00000000..43c97e71 --- /dev/null +++ b/__tests__/integrations/__fixtures__/legacy-config/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/__tests__/integrations/__fixtures__/legacy-config/a.vue b/__tests__/integrations/__fixtures__/legacy-config/a.vue new file mode 100644 index 00000000..6f0b8f75 --- /dev/null +++ b/__tests__/integrations/__fixtures__/legacy-config/a.vue @@ -0,0 +1,11 @@ + + + diff --git a/__tests__/integrations/__fixtures__/legacy-config/package.json b/__tests__/integrations/__fixtures__/legacy-config/package.json new file mode 100644 index 00000000..34d02ee5 --- /dev/null +++ b/__tests__/integrations/__fixtures__/legacy-config/package.json @@ -0,0 +1,11 @@ +{ + "private": true, + "name": "integration-test-for-legacy-config", + "type": "module", + "version": "1.0.0", + "description": "Integration test for legacy config", + "dependencies": { + "eslint": "^8.57.0-0", + "eslint-plugin-vuejs-accessibility": "file:../../../.." + } +} diff --git a/__tests__/integrations/flat-config.spec.ts b/__tests__/integrations/flat-config.spec.ts new file mode 100644 index 00000000..e4998163 --- /dev/null +++ b/__tests__/integrations/flat-config.spec.ts @@ -0,0 +1,40 @@ +import cp from "child_process"; +import path from "path"; +import semver from "semver"; +import { readPackageJson } from "./helper"; + +const ESLINT = `.${path.sep}node_modules${path.sep}.bin${path.sep}eslint`; + +describe("Integration with flat config", () => { + let originalCwd: null | string = null; + const dirFixture = path.join(__dirname, "__fixtures__/flat-config"); + + beforeEach(() => { + originalCwd = process.cwd(); + process.chdir(dirFixture); + cp.execSync("npm i -f", { stdio: "inherit" }); + }); + afterEach(() => { + originalCwd && process.chdir(originalCwd); + }); + + it("should work with config", () => { + expect.assertions(2); + + const eslintPackageJson = readPackageJson( + path.resolve(dirFixture, "node_modules/eslint") + ); + + if (!semver.satisfies(process.version, eslintPackageJson.engines.node)) { + return; + } + + const result = JSON.parse( + cp.execSync(`${ESLINT} a.vue --max-warnings 1 --format=json`, { + encoding: "utf-8" + }) + ); + expect(result.length).toBe(1); + expect(result[0].messages[0].messageId).toBe("imgMissingAlt"); + }); +}); diff --git a/__tests__/integrations/helper.ts b/__tests__/integrations/helper.ts new file mode 100644 index 00000000..d69995d1 --- /dev/null +++ b/__tests__/integrations/helper.ts @@ -0,0 +1,8 @@ +import fs from "fs"; +import path from "path"; + +export function readPackageJson(base: string) { + return JSON.parse( + fs.readFileSync(path.resolve(base, "package.json"), "utf-8") + ); +} diff --git a/__tests__/integrations/legacy-config.spec.ts b/__tests__/integrations/legacy-config.spec.ts new file mode 100644 index 00000000..a7570d0d --- /dev/null +++ b/__tests__/integrations/legacy-config.spec.ts @@ -0,0 +1,40 @@ +import cp from "child_process"; +import path from "path"; +import semver from "semver"; +import { readPackageJson } from "./helper"; + +const ESLINT = `.${path.sep}node_modules${path.sep}.bin${path.sep}eslint`; + +describe("Integration with legacy config", () => { + let originalCwd: null | string = null; + const dirFixture = path.join(__dirname, "__fixtures__/legacy-config"); + + beforeEach(() => { + originalCwd = process.cwd(); + process.chdir(dirFixture); + cp.execSync("npm i -f", { stdio: "inherit" }); + }); + afterEach(() => { + originalCwd && process.chdir(originalCwd); + }); + + it("should work with config", () => { + expect.assertions(2); + + const eslintPackageJson = readPackageJson( + path.resolve(dirFixture, "node_modules/eslint") + ); + + if (!semver.satisfies(process.version, eslintPackageJson.engines.node)) { + return; + } + + const result = JSON.parse( + cp.execSync(`${ESLINT} a.vue --max-warnings 1 --format=json`, { + encoding: "utf-8" + }) + ); + expect(result.length).toBe(1); + expect(result[0].messages[0].messageId).toBe("imgMissingAlt"); + }); +}); diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.mts similarity index 100% rename from docs/.vitepress/config.ts rename to docs/.vitepress/config.mts diff --git a/docs/index.md b/docs/index.md index 74073a93..7b0f8711 100644 --- a/docs/index.md +++ b/docs/index.md @@ -22,7 +22,33 @@ pnpm add -D eslint-plugin-vuejs-accessibility ## 📖 Usage -Add `vuejs-accessibility` to the plugins section of your `eslint` configuration. You can omit the `eslint-plugin-` prefix: +### Configuration (`eslint.config.js`) + +Use `eslint.config.js` file to configure rules. This is the default in ESLint v9, but can be used starting from ESLint v8.57.0. See also: https://eslint.org/docs/latest/use/configure/configuration-files-new. + +Example eslint.config.js: + +```js +import pluginVueA11y from "eslint-plugin-vuejs-accessibility"; + +export default [ + // add more generic rulesets here, such as: + // js.configs.recommended, + ...pluginVueA11y.configs["flat/recommended"], + { + rules: { + // override/add rules settings here, such as: + // "vuejs-accessibility/alt-text": "error" + } + } +]; +``` + +### Configuration (`.eslintrc`) + +Use `.eslintrc.*` file to configure rules in ESLint < v9. See also: https://eslint.org/docs/latest/use/configure/. + +Add `vuejs-accessibility` to the plugins section of your configuration. You can omit the `eslint-plugin-` prefix: ```json { diff --git a/docs/rule-overview/rule-overview.data.ts b/docs/rule-overview/rule-overview.data.mts similarity index 73% rename from docs/rule-overview/rule-overview.data.ts rename to docs/rule-overview/rule-overview.data.mts index ca67c9ed..857bcad9 100644 --- a/docs/rule-overview/rule-overview.data.ts +++ b/docs/rule-overview/rule-overview.data.mts @@ -1,6 +1,6 @@ import { defineLoader } from "vitepress"; -import recommended from "../../src/configs/recommended"; -import { rules } from "../.vitepress/rulesForSidebar"; +import { rules as baseRules } from "../../src/configs/rules.js"; +import { rules } from "../.vitepress/rulesForSidebar.js"; export type Data = Array<{ name: string; @@ -23,8 +23,8 @@ export default defineLoader({ }); function getRecommendedRules() { - if (recommended.rules) { - return Object.keys(recommended.rules).map(removeRulePrefix); + if (baseRules) { + return Object.keys(baseRules).map(removeRulePrefix); } return []; } diff --git a/package.json b/package.json index 73a5ebc4..2763e93c 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,15 @@ "version": "2.2.1", "description": "An eslint plugin for checking Vue.js files for accessibility", "main": "dist/index.js", + "files": [ + "dist" + ], "scripts": { "lint": "eslint --cache .", + "build": "tsc -p tsconfig.build.json", "prepublishOnly": "tsc -p tsconfig.build.json", "test": "jest", + "test:integration": "jest --testTimeout 60000 --testRegex \".*\\.spec\\.ts$\"", "release": "np", "docs:dev": "vitepress dev docs", "docs:build": "vitepress build docs" @@ -42,15 +47,18 @@ "@types/eslint-scope": "^3.7.2", "@types/jest": "^29.2.5", "@types/node": "^20.1.0", + "@types/semver": "^7.5.7", "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^6.9.1", + "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.8.0", "eslint-plugin-eslint-plugin": "^6.0.0", + "globals": "^14.0.0", "husky": "^9.0.5", "jest": "^29.2.2", "np": "^10.0.0", "prettier": "^3.0.0", "pretty-quick": "^4.0.0", + "semver": "^7.6.0", "ts-jest": "^29.0.3", "ts-node": "^10.3.0", "typescript": "^5.0.2", diff --git a/src/configs/flat/recommended.ts b/src/configs/flat/recommended.ts new file mode 100644 index 00000000..a483fbec --- /dev/null +++ b/src/configs/flat/recommended.ts @@ -0,0 +1,34 @@ +import globals from "globals"; +import { rules } from "../rules"; + +const recommended = [ + { + name: "vuejs-accessibility:setup:base", + plugins: { + get "vuejs-accessibility"() { + return require("../../index"); + } + }, + languageOptions: { + sourceType: "module", + globals: globals.browser + } + }, + { + name: "vuejs-accessibility:setup:with-files-rules-and-parser", + files: ["*.vue", "**/*.vue"], + plugins: { + get "vuejs-accessibility"() { + return require("../../index"); + } + }, + languageOptions: { + parser: require("vue-eslint-parser"), + sourceType: "module", + globals: globals.browser + }, + rules + } +]; + +export = recommended; diff --git a/src/configs/recommended.ts b/src/configs/recommended.ts index 47ec21e1..731c9294 100644 --- a/src/configs/recommended.ts +++ b/src/configs/recommended.ts @@ -1,4 +1,5 @@ import type { Linter } from "eslint"; +import { rules } from "./rules"; const recommended: Linter.BaseConfig = { parser: require.resolve("vue-eslint-parser"), @@ -11,28 +12,7 @@ const recommended: Linter.BaseConfig = { es6: true }, plugins: ["vuejs-accessibility"], - rules: { - "vuejs-accessibility/alt-text": "error", - "vuejs-accessibility/anchor-has-content": "error", - "vuejs-accessibility/aria-props": "error", - "vuejs-accessibility/aria-role": "error", - "vuejs-accessibility/aria-unsupported-elements": "error", - "vuejs-accessibility/click-events-have-key-events": "error", - "vuejs-accessibility/form-control-has-label": "error", - "vuejs-accessibility/heading-has-content": "error", - "vuejs-accessibility/iframe-has-title": "error", - "vuejs-accessibility/interactive-supports-focus": "error", - "vuejs-accessibility/label-has-for": "error", - "vuejs-accessibility/media-has-caption": "error", - "vuejs-accessibility/mouse-events-have-key-events": "error", - "vuejs-accessibility/no-access-key": "error", - "vuejs-accessibility/no-autofocus": "error", - "vuejs-accessibility/no-distracting-elements": "error", - "vuejs-accessibility/no-redundant-roles": "error", - "vuejs-accessibility/no-static-element-interactions": "error", - "vuejs-accessibility/role-has-required-aria-props": "error", - "vuejs-accessibility/tabindex-no-positive": "error" - } + rules }; export default recommended; diff --git a/src/configs/rules.ts b/src/configs/rules.ts new file mode 100644 index 00000000..133c96a1 --- /dev/null +++ b/src/configs/rules.ts @@ -0,0 +1,26 @@ +import type { Linter } from "eslint"; + +const rules = { + "vuejs-accessibility/alt-text": "error", + "vuejs-accessibility/anchor-has-content": "error", + "vuejs-accessibility/aria-props": "error", + "vuejs-accessibility/aria-role": "error", + "vuejs-accessibility/aria-unsupported-elements": "error", + "vuejs-accessibility/click-events-have-key-events": "error", + "vuejs-accessibility/form-control-has-label": "error", + "vuejs-accessibility/heading-has-content": "error", + "vuejs-accessibility/iframe-has-title": "error", + "vuejs-accessibility/interactive-supports-focus": "error", + "vuejs-accessibility/label-has-for": "error", + "vuejs-accessibility/media-has-caption": "error", + "vuejs-accessibility/mouse-events-have-key-events": "error", + "vuejs-accessibility/no-access-key": "error", + "vuejs-accessibility/no-autofocus": "error", + "vuejs-accessibility/no-distracting-elements": "error", + "vuejs-accessibility/no-redundant-roles": "error", + "vuejs-accessibility/no-static-element-interactions": "error", + "vuejs-accessibility/role-has-required-aria-props": "error", + "vuejs-accessibility/tabindex-no-positive": "error" +} satisfies Linter.RulesRecord; + +export { rules }; diff --git a/src/index.ts b/src/index.ts index 32c75c79..c9876182 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ -import recommended from "./configs/recommended"; +import { default as recommended } from "./configs/recommended"; +import flatRecommended from "./configs/flat/recommended"; import altText from "./rules/alt-text"; import anchorHasContent from "./rules/anchor-has-content"; @@ -22,33 +23,35 @@ import noStaticElementInteractions from "./rules/no-static-element-interactions" import roleHasRequiredAriaProps from "./rules/role-has-required-aria-props"; import tabindexNoPositive from "./rules/tabindex-no-positive"; -const plugin = { - configs: { - recommended - }, - rules: { - "alt-text": altText, - "anchor-has-content": anchorHasContent, - "aria-props": ariaProps, - "aria-role": ariaRole, - "aria-unsupported-elements": ariaUnsupportedElements, - "click-events-have-key-events": clickEventsHaveKeyEvents, - "form-control-has-label": formControlHasLabel, - "heading-has-content": headingHasContent, - "iframe-has-title": iframeHasTitle, - "interactive-supports-focus": interactiveSupportsFocus, - "label-has-for": labelHasFor, - "media-has-caption": mediaHasCaption, - "mouse-events-have-key-events": mouseEventsHaveKeyEvents, - "no-access-key": noAccessKey, - "no-autofocus": noAutofocus, - "no-distracting-elements": noDistractingElements, - "no-onchange": noOnchange, - "no-redundant-roles": noRedundantRoles, - "no-static-element-interactions": noStaticElementInteractions, - "role-has-required-aria-props": roleHasRequiredAriaProps, - "tabindex-no-positive": tabindexNoPositive - } +const configs = { + recommended, + "flat/recommended": flatRecommended +}; +const rules = { + "alt-text": altText, + "anchor-has-content": anchorHasContent, + "aria-props": ariaProps, + "aria-role": ariaRole, + "aria-unsupported-elements": ariaUnsupportedElements, + "click-events-have-key-events": clickEventsHaveKeyEvents, + "form-control-has-label": formControlHasLabel, + "heading-has-content": headingHasContent, + "iframe-has-title": iframeHasTitle, + "interactive-supports-focus": interactiveSupportsFocus, + "label-has-for": labelHasFor, + "media-has-caption": mediaHasCaption, + "mouse-events-have-key-events": mouseEventsHaveKeyEvents, + "no-access-key": noAccessKey, + "no-autofocus": noAutofocus, + "no-distracting-elements": noDistractingElements, + "no-onchange": noOnchange, + "no-redundant-roles": noRedundantRoles, + "no-static-element-interactions": noStaticElementInteractions, + "role-has-required-aria-props": roleHasRequiredAriaProps, + "tabindex-no-positive": tabindexNoPositive }; -export = plugin; +export = { + configs, + rules +}; diff --git a/src/rules/interactive-supports-focus.ts b/src/rules/interactive-supports-focus.ts index 7fa5d9d3..d3871ff6 100644 --- a/src/rules/interactive-supports-focus.ts +++ b/src/rules/interactive-supports-focus.ts @@ -71,7 +71,7 @@ function hasTabIndex(node: AST.VElement) { return value === null; } -interface InteractiveSupportsFocus extends Rule.RuleModule { +export interface InteractiveSupportsFocus extends Rule.RuleModule { interactiveHandlers: string[]; interactiveRoles: ARIARoleDefinitionKey[]; } diff --git a/src/utils/defineTemplateBodyVisitor.ts b/src/utils/defineTemplateBodyVisitor.ts index 41776062..8e4b9502 100644 --- a/src/utils/defineTemplateBodyVisitor.ts +++ b/src/utils/defineTemplateBodyVisitor.ts @@ -14,7 +14,8 @@ function defineTemplateBodyVisitor( templateVisitor: TemplateListener, scriptVisitor?: Rule.RuleListener ) { - if (!context.parserServices.defineTemplateBodyVisitor) { + const parserServices = getParserServices(context); + if (!parserServices.defineTemplateBodyVisitor) { if (path.extname(context.getFilename()) === ".vue") { context.report({ loc: { line: 1, column: 0 }, @@ -26,10 +27,21 @@ function defineTemplateBodyVisitor( return {}; } - return context.parserServices.defineTemplateBodyVisitor( + return parserServices.defineTemplateBodyVisitor( templateVisitor, scriptVisitor ); } +/** + * This function is API compatible with eslint v8.x and eslint v9 or later. + * @see https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#from-context-to-sourcecode + */ +function getParserServices(context: Rule.RuleContext) { + // @ts-expect-error TODO: remove this when eslint v8 support is dropped + const legacy = context.sourceCode; + + return legacy ? legacy.parserServices : context.parserServices; +} + export default defineTemplateBodyVisitor; diff --git a/tsconfig.build.json b/tsconfig.build.json index fd6c5ac3..35e615fa 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,4 +1,11 @@ { "extends": "./tsconfig.json", - "exclude": ["bin", "src/**/__tests__", "docs/**", "jest.setup.ts"] + "exclude": [ + "bin", + "src/**/__tests__", + "docs/**", + "jest.setup.ts", + "dist", + "__tests__" + ] } diff --git a/tsconfig.json b/tsconfig.json index c4df42ce..dd54c5ff 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,6 +6,7 @@ "strict": true, "esModuleInterop": true, "resolveJsonModule": true, + "declaration": true, "outDir": "./dist" } } diff --git a/yarn.lock b/yarn.lock index a4433b95..dc57cdc7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1321,6 +1321,11 @@ resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.4.tgz#0a41252ad431c473158b22f9bfb9a63df7541cff" integrity sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ== +"@types/semver@^7.5.7": + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== + "@types/stack-utils@^2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" @@ -1360,25 +1365,17 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/parser@^6.9.1": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b" - integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ== +"@typescript-eslint/parser@^7.0.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.4.0.tgz#540f4321de1e52b886c0fa68628af1459954c1f1" + integrity sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ== dependencies: - "@typescript-eslint/scope-manager" "6.21.0" - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/typescript-estree" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/scope-manager" "7.4.0" + "@typescript-eslint/types" "7.4.0" + "@typescript-eslint/typescript-estree" "7.4.0" + "@typescript-eslint/visitor-keys" "7.4.0" debug "^4.3.4" -"@typescript-eslint/scope-manager@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" - integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== - dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" - "@typescript-eslint/scope-manager@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.0.0.tgz#15ea9abad2b56fc8f5c0b516775f41c86c5c8685" @@ -1387,6 +1384,14 @@ "@typescript-eslint/types" "7.0.0" "@typescript-eslint/visitor-keys" "7.0.0" +"@typescript-eslint/scope-manager@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz#acfc69261f10ece7bf7ece1734f1713392c3655f" + integrity sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw== + dependencies: + "@typescript-eslint/types" "7.4.0" + "@typescript-eslint/visitor-keys" "7.4.0" + "@typescript-eslint/type-utils@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.0.0.tgz#a4c7ae114414e09dbbd3c823b5924793f7483252" @@ -1397,23 +1402,23 @@ debug "^4.3.4" ts-api-utils "^1.0.1" -"@typescript-eslint/types@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" - integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== - "@typescript-eslint/types@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.0.0.tgz#2e5889c7fe3c873fc6dc6420aa77775f17cd5dc6" integrity sha512-9ZIJDqagK1TTs4W9IyeB2sH/s1fFhN9958ycW8NRTg1vXGzzH5PQNzq6KbsbVGMT+oyyfa17DfchHDidcmf5cg== -"@typescript-eslint/typescript-estree@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" - integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== +"@typescript-eslint/types@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.4.0.tgz#ee9dafa75c99eaee49de6dcc9348b45d354419b6" + integrity sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw== + +"@typescript-eslint/typescript-estree@7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.0.tgz#7ce66f2ce068517f034f73fba9029300302fdae9" + integrity sha512-JzsOzhJJm74aQ3c9um/aDryHgSHfaX8SHFIu9x4Gpik/+qxLvxUylhTsO9abcNu39JIdhY2LgYrFxTii3IajLA== dependencies: - "@typescript-eslint/types" "6.21.0" - "@typescript-eslint/visitor-keys" "6.21.0" + "@typescript-eslint/types" "7.0.0" + "@typescript-eslint/visitor-keys" "7.0.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1421,13 +1426,13 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/typescript-estree@7.0.0": - version "7.0.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.0.tgz#7ce66f2ce068517f034f73fba9029300302fdae9" - integrity sha512-JzsOzhJJm74aQ3c9um/aDryHgSHfaX8SHFIu9x4Gpik/+qxLvxUylhTsO9abcNu39JIdhY2LgYrFxTii3IajLA== +"@typescript-eslint/typescript-estree@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz#12dbcb4624d952f72c10a9f4431284fca24624f4" + integrity sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg== dependencies: - "@typescript-eslint/types" "7.0.0" - "@typescript-eslint/visitor-keys" "7.0.0" + "@typescript-eslint/types" "7.4.0" + "@typescript-eslint/visitor-keys" "7.4.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -1448,14 +1453,6 @@ "@typescript-eslint/typescript-estree" "7.0.0" semver "^7.5.4" -"@typescript-eslint/visitor-keys@6.21.0": - version "6.21.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" - integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== - dependencies: - "@typescript-eslint/types" "6.21.0" - eslint-visitor-keys "^3.4.1" - "@typescript-eslint/visitor-keys@7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.0.tgz#83cdadd193ee735fe9ea541f6a2b4d76dfe62081" @@ -1464,6 +1461,14 @@ "@typescript-eslint/types" "7.0.0" eslint-visitor-keys "^3.4.1" +"@typescript-eslint/visitor-keys@7.4.0": + version "7.4.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz#0c8ff2c1f8a6fe8d7d1a57ebbd4a638e86a60a94" + integrity sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA== + dependencies: + "@typescript-eslint/types" "7.4.0" + eslint-visitor-keys "^3.4.1" + "@ungap/structured-clone@^1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" @@ -2935,6 +2940,11 @@ globals@^13.19.0: dependencies: type-fest "^0.20.2" +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== + globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"