@shayanthenerd/eslint-config 0.32.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/README.md +65 -40
  2. package/dist/configs/astro.mjs +5 -1
  3. package/dist/configs/css.mjs +3 -3
  4. package/dist/configs/packageJson.mjs +1 -1
  5. package/dist/configs/react.mjs +2 -2
  6. package/dist/configs/tailwind.mjs +7 -1
  7. package/dist/configs/typescript.mjs +4 -6
  8. package/dist/helpers/ignores/defaultIgnorePatterns.mjs +1 -6
  9. package/dist/helpers/options/defaultOptions.mjs +13 -3
  10. package/dist/helpers/options/enableDetectedConfigs.mjs +20 -8
  11. package/dist/index.d.mts +1 -0
  12. package/dist/rules/astro.mjs +61 -54
  13. package/dist/rules/baseline.mjs +1 -1
  14. package/dist/rules/css.mjs +30 -10
  15. package/dist/rules/html.mjs +11 -3
  16. package/dist/rules/importX.mjs +2 -2
  17. package/dist/rules/javascript.mjs +6 -5
  18. package/dist/rules/markdown.mjs +7 -1
  19. package/dist/rules/next.mjs +2 -0
  20. package/dist/rules/node.mjs +1 -1
  21. package/dist/rules/packageJson.mjs +166 -153
  22. package/dist/rules/perfectionist.mjs +41 -11
  23. package/dist/rules/playwright.mjs +10 -0
  24. package/dist/rules/react.mjs +56 -54
  25. package/dist/rules/stylistic.mjs +1 -1
  26. package/dist/rules/tanstack.mjs +1 -1
  27. package/dist/rules/typescript.mjs +3 -2
  28. package/dist/rules/unicorn.mjs +38 -7
  29. package/dist/rules/vue.mjs +38 -41
  30. package/dist/rules/zod.mjs +2 -0
  31. package/dist/types/eslint-schema.d.mts +1086 -669
  32. package/dist/types/index.d.mts +44 -9
  33. package/dist/types/options/baseline.d.mts +24 -3
  34. package/dist/types/options/react.d.mts +9 -9
  35. package/dist/types/options/typescript.d.mts +3 -3
  36. package/dist/types/options/vue.d.mts +1 -1
  37. package/package.json +39 -37
package/README.md CHANGED
@@ -25,40 +25,40 @@ ESLint configuration for enforcing best practices and maintaining a consistent c
25
25
  ## Plugin Support
26
26
  Legend:
27
27
  - ✅ — **Enabled** by default
28
+ - 🔍 — [**Automatically detected**](#automatic-dependency-detection)
28
29
  - ⚙️ — **Opt-in** (requires manual configuration)
29
- - 🔍 — [**Automatically detected**](#automatic-dependency-detection) (based on project dependencies)
30
-
31
- | Category | Activation |
32
- | :---------------------------------------------------------------------------------------------------- | :--------: |
33
- | **Languages** | |
34
- | [JavaScript][eslint] | ✅  |
35
- | [TypeScript][plugin-ts] | 🔍  |
36
- | [Markdown][plugin-md] | ✅  |
37
- | [HTML][plugin-html] | ⚙️  |
38
- | [CSS][plugin-css] | ⚙️  |
39
- | **Formatting** | |
40
- | [Stylistic][plugin-stylistic] | ✅  |
41
- | [Perfectionist][plugin-perfectionist] | ✅  |
42
- | **Frameworks & Libraries** | |
43
- | [Astro][plugin-astro] ([jsx-accessibility][plugin-jsx-a11y]) | 🔍  |
44
- | [React][plugin-react] ([jsx-accessibility][plugin-jsx-a11y], [@html-eslint/react][plugin-html-react]) | 🔍  |
45
- | [Next][plugin-next] | 🔍  |
46
- | [TanStack Start][plugin-tanstack-start], [TanStack Query][plugin-tanstack-query], [TanStack Router][plugin-tanstack-router] | 🔍  |
47
- | [Vue & Nuxt][plugin-vue] ([vue-accessibility][plugin-vue-a11y]) | 🔍  |
48
- | [Tailwind][plugin-tailwind] | ⚙️  |
49
- | [Zod & Zod Mini][plugin-zod] | 🔍  |
50
- | **Testing Tools** | |
51
- | [Storybook][plugin-storybook] | 🔍  |
52
- | [Vitest][plugin-vitest] | 🔍  |
53
- | [Cypress][plugin-cypress] | 🔍  |
54
- | [Playwright][plugin-playwright] | 🔍  |
55
- | **Miscellaneous** | |
56
- | [_package.json_][plugin-package-json] | ✅  |
57
- | [Node][plugin-n] | ✅  |
58
- | [Promises][plugin-promise] | ✅  |
59
- | [Imports][plugin-import-x] | ✅  |
60
- | [Unicorn][plugin-unicorn] | ✅  |
61
- | [Baseline][plugin-baseline] ([css/use-baseline], [@html-eslint/use-baseline], [@html-eslint/react/use-baseline]) | 🔍  |
30
+
31
+ | Category | Activation |
32
+ | :------------------------------------------------------------------------------------------------------ | :--------: |
33
+ | **Languages** | |
34
+ | [JavaScript][eslint] | ✅  |
35
+ | [TypeScript][plugin-ts] | 🔍  |
36
+ | [Markdown][plugin-md] | ✅  |
37
+ | [HTML][plugin-html] | ⚙️  |
38
+ | [CSS][plugin-css] ([eslint-cssicorn][plugin-cssicorn]) | ⚙️  |
39
+ | **Formatting** | |
40
+ | [Stylistic][plugin-stylistic] | ✅  |
41
+ | [Perfectionist][plugin-perfectionist] | ✅  |
42
+ | **Frameworks & Libraries** | |
43
+ | [Astro][plugin-astro] ([jsx-accessibility][plugin-jsx-a11y-x]) | 🔍  |
44
+ | [React][plugin-react] ([jsx-accessibility][plugin-jsx-a11y-x], [@html-eslint/react][plugin-html-react]) | 🔍  |
45
+ | [Next][plugin-next] | 🔍  |
46
+ | [TanStack Start][plugin-tanstack-start], [TanStack Query][plugin-tanstack-query], [TanStack Router][plugin-tanstack-router] | 🔍  |
47
+ | [Vue & Nuxt][plugin-vue] ([vue-accessibility][plugin-vue-a11y]) | 🔍  |
48
+ | [Tailwind][plugin-tailwind] | ⚙️  |
49
+ | [Zod & Zod Mini][plugin-zod] | 🔍  |
50
+ | **Testing Tools** | |
51
+ | [Storybook][plugin-storybook] | 🔍  |
52
+ | [Vitest][plugin-vitest] | 🔍  |
53
+ | [Cypress][plugin-cypress] | 🔍  |
54
+ | [Playwright][plugin-playwright] | 🔍  |
55
+ | **Miscellaneous** | |
56
+ | [_package.json_][plugin-package-json] | ✅  |
57
+ | [Node][plugin-n] | ✅  |
58
+ | [Promises][plugin-promise] | ✅  |
59
+ | [Imports][plugin-import-x] | ✅  |
60
+ | [Unicorn][plugin-unicorn] | ✅  |
61
+ | [Baseline][plugin-baseline] ([css/use-baseline], [@html-eslint/use-baseline], [@html-eslint/react/use-baseline]) | 🔍  |
62
62
 
63
63
  ## Installation and Configuration
64
64
  1. Install the package and ESLint as dev dependencies:
@@ -81,7 +81,7 @@ Legend:
81
81
  "scripts": {
82
82
  "lint": "eslint --max-warnings=0 --cache --cache-location='node_modules/.cache/.eslintcache'",
83
83
  "lint:fix": "eslint --fix --max-warnings=0 --cache --cache-location='node_modules/.cache/.eslintcache'",
84
- "lint:inspect": "npx @eslint/config-inspector"
84
+ "lint:inspect": "pnpx @eslint/config-inspector"
85
85
  }
86
86
  }
87
87
  ```
@@ -214,8 +214,27 @@ For editor integration, to reduce noise and avoid inconsistent diagnostics from
214
214
  }
215
215
  ```
216
216
 
217
+ ### Astro
218
+ The accessibility rules in [eslint-plugin-astro][plugin-astro] require [eslint-plugin-jsx-a11y-x][plugin-jsx-a11y-x] as a peer dependency. Install it with:
219
+ ```shell
220
+ pnpm add -D eslint-plugin-jsx-a11y-x
221
+ ```
222
+ When both `astro` and `eslint-plugin-jsx-a11y-x` are detected as dependencies, `configs.astro.accessibility` is set to `true` automatically. To disable the accessibility rules, set `configs.astro.accessibility` to `false`.
223
+
224
+ ### Vue
225
+ [ESLint Stylistic][plugin-stylistic] and [eslint-plugin-vue][plugin-vue] don't format `<style>` blocks inside Vue SFCs. On the other hand, [Prettier][prettier] cannot be limited to just `<style>` blocks, and formats the whole file, including `<script>` and `<template>` blocks, which could conflict with ESLint. To work around this, you may use Tailwind, format styles manually, keep styles in separate `.css` files, or use Prettier and resolve any resulting conflicts.
226
+
227
+ Read more about the formatting options and Prettier integration in the [Formatting](#formatting) section.
228
+
217
229
  ### Nuxt
218
- The required Nuxt configurations and rules are already included, so there's no need to install or configure the [@nuxt/eslint][eslint-nuxt] module.
230
+ The required Nuxt configurations and rules are already included, so there's no need to use the [@nuxt/eslint][eslint-nuxt] module.
231
+
232
+ ### React/Next
233
+ The required Next configurations and rules, including for core web vitals, are already provided, so there's no need to use [eslint-config-next][eslint-next]. Similarly, the React integration also provides React-specific configurations and rules for accessibility and React Hooks.
234
+
235
+ ### TanStack Start
236
+ > [!NOTE]
237
+ > The rules in [@tanstack/eslint-plugin-start][plugin-tanstack-start] require type information, and will be disabled automatically if the TypeScript integration is not enabled.
219
238
 
220
239
  ### Markdown
221
240
  Markdown linting is powered by [@eslint/markdown][plugin-md].
@@ -344,7 +363,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
344
363
  ```json title="package.json"
345
364
  {
346
365
  "scripts": {
347
- "format": "prettier --write . '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
366
+ "format": "prettier --write . '!pnpm-lock.yaml' '!**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx,html,vue,astro}' --cache"
348
367
  }
349
368
  }
350
369
  ```
@@ -427,7 +446,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
427
446
  ```json title="package.json"
428
447
  {
429
448
  "scripts": {
430
- "format": "prettier --write . --cache",
449
+ "format": "prettier --write . '!pnpm-lock.yaml' --cache",
431
450
  }
432
451
  }
433
452
  ```
@@ -517,6 +536,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
517
536
 
518
537
  configs?: {
519
538
  astro?: boolean | {
539
+ accessibility?: boolean,
520
540
  overrides?: Overrides,
521
541
  },
522
542
  baseline?: boolean | {
@@ -537,6 +557,7 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
537
557
  overrides?: Overrides,
538
558
  },
539
559
  css?: boolean | {
560
+ allowedUnknownPseudoSelectors?: string[],
540
561
  overrides?: Overrides,
541
562
  },
542
563
  html?: boolean | {
@@ -574,6 +595,8 @@ For file types that ESLint Stylistic does not handle—such as CSS, JSON, YAML,
574
595
  overrides?: Overrides,
575
596
  },
576
597
  packageJson?: boolean | {
598
+ allowedDistTags?: string[],
599
+ allowedDistTagsFor?: ('dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies')[],
577
600
  overrides?: Overrides,
578
601
  },
579
602
  perfectionist?: boolean | {
@@ -745,7 +768,7 @@ This project was inspired by the work of [Anthony Fu][antfu], whose generous con
745
768
  [MIT][license] License © 2025-PRESENT — [Shayan Zamani][ShayanTheNerd]
746
769
 
747
770
  <!-- Badges -->
748
- [license]: ./LICENSE
771
+ [license]: LICENSE
749
772
  [license-badge]: https://img.shields.io/badge/License-MIT-blue.svg?logoColor=FEFEFE&labelColor=3B82F6&color=3B82F6
750
773
  [npm-version-badge]: https://img.shields.io/npm/v/@shayanthenerd/eslint-config?label=&logo=npm&logoColor=FEFEFE&labelColor=3B82F6&color=3B82F6
751
774
  [npmx]: https://www.npmjs.com/package/@shayanthenerd/eslint-config
@@ -759,11 +782,12 @@ This project was inspired by the work of [Anthony Fu][antfu], whose generous con
759
782
  [plugin-astro]: https://ota-meshi.github.io/eslint-plugin-astro
760
783
  [plugin-baseline]: https://baselinejs.vercel.app
761
784
  [plugin-css]: https://github.com/eslint/css
785
+ [plugin-cssicorn]: https://github.com/sindresorhus/eslint-cssicorn
762
786
  [plugin-cypress]: https://github.com/cypress-io/eslint-plugin-cypress
763
787
  [plugin-html]: https://html-eslint.org
764
788
  [plugin-html-react]: https://html-eslint.org/docs/react/getting-started
765
789
  [plugin-import-x]: https://github.com/un-ts/eslint-plugin-import-x
766
- [plugin-jsx-a11y]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y
790
+ [plugin-jsx-a11y-x]: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y-x
767
791
  [plugin-md]: https://github.com/eslint/markdown
768
792
  [plugin-n]: https://github.com/eslint-community/eslint-plugin-n
769
793
  [plugin-next]: https://github.com/vercel/next.js/tree/HEAD/packages/eslint-plugin-next
@@ -792,10 +816,11 @@ This project was inspired by the work of [Anthony Fu][antfu], whose generous con
792
816
 
793
817
  <!-- References -->
794
818
  [antfu]: https://github.com/antfu
795
- [contributing]: ./.github/CONTRIBUTING.md
819
+ [contributing]: .github/CONTRIBUTING.md
796
820
  [eslint]: https://eslint.org
797
821
  [online-preview]: https://eslintconfig.netlify.app
798
822
  [eslint-config-ts-setup]: https://eslint.org/docs/latest/use/configure/configuration-files#typescript-configuration-files
823
+ [eslint-next]: https://nextjs.org/docs/app/api-reference/config/eslint
799
824
  [eslint-nuxt]: https://eslint.nuxt.com
800
825
  [local-pkg]: https://github.com/antfu-collective/local-pkg
801
826
  [prettier]: https://prettier.io
@@ -6,9 +6,10 @@ import * as eslintParserAstro from "astro-eslint-parser";
6
6
  import { mergeConfigs } from "eslint-flat-config-utils";
7
7
  import eslintPluginAstro from "eslint-plugin-astro";
8
8
  import { parser } from "typescript-eslint";
9
+ import path from "node:path";
9
10
  //#region src/configs/astro.ts
10
11
  function getAstroConfig(options) {
11
- const { astro } = options.configs;
12
+ const { tsConfig, configs: { astro } } = options;
12
13
  const { overrides } = isEnabled(astro) ? astro : defaultOptions.configs.astro;
13
14
  const astroConfig = {
14
15
  name: "shayanthenerd/astro",
@@ -22,6 +23,9 @@ function getAstroConfig(options) {
22
23
  parser: eslintParserAstro,
23
24
  parserOptions: {
24
25
  parser,
26
+ projectService: false,
27
+ project: tsConfig ? path.resolve(tsConfig.rootDir, tsConfig.filename) : void 0,
28
+ tsconfigRootDir: tsConfig ? path.resolve(tsConfig.rootDir) : void 0,
25
29
  extraFileExtensions: [".astro"]
26
30
  }
27
31
  },
@@ -3,12 +3,12 @@ import { defaultOptions } from "../helpers/options/defaultOptions.mjs";
3
3
  import { isEnabled } from "../utils/isEnabled.mjs";
4
4
  import { getCssRules } from "../rules/css.mjs";
5
5
  import { mergeConfigs } from "eslint-flat-config-utils";
6
- import eslintPluginUnicorn from "eslint-plugin-unicorn";
6
+ import eslintPluginCssicorn from "eslint-cssicorn";
7
7
  import eslintPluginCss from "@eslint/css";
8
8
  import { tailwind3, tailwind4 } from "tailwind-csstree";
9
9
  //#region src/configs/css.ts
10
10
  function getCssConfig(options) {
11
- const { css, unicorn, tailwind } = options.configs;
11
+ const { css, tailwind } = options.configs;
12
12
  const { overrides } = isEnabled(css) ? css : defaultOptions.configs.css;
13
13
  const tailwindSyntax = isEnabled(tailwind) && tailwind.entryPoint ? tailwind4 : tailwind3;
14
14
  const cssConfig = {
@@ -16,7 +16,7 @@ function getCssConfig(options) {
16
16
  files: [globs.css],
17
17
  plugins: {
18
18
  css: eslintPluginCss,
19
- ...isEnabled(unicorn) && { unicorn: eslintPluginUnicorn }
19
+ cssicorn: eslintPluginCssicorn
20
20
  },
21
21
  language: "css/css",
22
22
  languageOptions: {
@@ -13,7 +13,7 @@ function getPackageJsonConfig(options) {
13
13
  files: [globs.packageJson],
14
14
  plugins: { "package-json": eslintPluginPackageJson },
15
15
  languageOptions: { parser: eslintPluginPackageJson.configs.recommended.languageOptions.parser },
16
- rules: getPackageJsonRules()
16
+ rules: getPackageJsonRules(options)
17
17
  };
18
18
  return mergeConfigs(packageJsonConfig, overrides);
19
19
  }
@@ -4,7 +4,7 @@ import { isEnabled } from "../utils/isEnabled.mjs";
4
4
  import { getReactRules } from "../rules/react.mjs";
5
5
  import { mergeConfigs } from "eslint-flat-config-utils";
6
6
  import eslintPluginUnicorn from "eslint-plugin-unicorn";
7
- import eslintPluginJsxA11y from "eslint-plugin-jsx-a11y";
7
+ import eslintPluginJsxA11yX from "eslint-plugin-jsx-a11y-x";
8
8
  import eslintPluginReact from "@eslint-react/eslint-plugin";
9
9
  import eslintPluginHtmlReact from "@html-eslint/eslint-plugin-react";
10
10
  //#region src/configs/react.ts
@@ -18,7 +18,7 @@ function getReactConfig(options) {
18
18
  "@eslint-react": eslintPluginReact,
19
19
  "@html-eslint/react": eslintPluginHtmlReact,
20
20
  ...isEnabled(unicorn) && { unicorn: eslintPluginUnicorn },
21
- ...isEnabled(accessibility) && { "jsx-a11y": eslintPluginJsxA11y }
21
+ ...isEnabled(accessibility) && { "jsx-a11y-x": eslintPluginJsxA11yX }
22
22
  },
23
23
  rules: getReactRules(options)
24
24
  };
@@ -14,6 +14,11 @@ const astroAttributes = {
14
14
  name: "^class:list$",
15
15
  match: [{ type: MatcherType.String }, { type: MatcherType.ObjectKey }]
16
16
  };
17
+ const reactAttributes = {
18
+ kind: SelectorKind.Attribute,
19
+ name: "^(?:className|.*Class)$",
20
+ match: [{ type: MatcherType.String }, { type: MatcherType.ObjectKey }]
21
+ };
17
22
  const vueAttributes = {
18
23
  kind: SelectorKind.Attribute,
19
24
  name: "^(?:v-bind:)?(exactActiveClass|activeClass|inactiveClass|active-class|inactive-class)$",
@@ -43,13 +48,14 @@ const nuxtUiAppConfigUiFields = {
43
48
  }]
44
49
  };
45
50
  function getTailwindConfig(options) {
46
- const { tsConfig, configs: { vue, nuxt, html, astro, tailwind } } = options;
51
+ const { tsConfig, configs: { vue, nuxt, html, astro, react, tailwind } } = options;
47
52
  const { cwd, config, overrides, entryPoint } = isEnabled(tailwind) ? tailwind : defaultOptions.configs.tailwind;
48
53
  const tsconfigPath = tsConfig ? path.resolve(tsConfig.rootDir, tsConfig.filename) : void 0;
49
54
  const isNuxtUiEnabled = isEnabled(nuxt) && isEnabled(nuxt.ui);
50
55
  const selectors = [
51
56
  ...getDefaultSelectors(),
52
57
  isEnabled(astro) ? astroAttributes : void 0,
58
+ isEnabled(react) ? reactAttributes : void 0,
53
59
  isEnabled(vue) ? vueAttributes : void 0,
54
60
  isNuxtUiEnabled ? nuxtUiAttributes : void 0,
55
61
  isNuxtUiEnabled ? nuxtUiAppConfigUiFields : void 0
@@ -8,26 +8,24 @@ import { parser, plugin } from "typescript-eslint";
8
8
  import path from "node:path";
9
9
  //#region src/configs/typescript.ts
10
10
  function getTypescriptConfig(options) {
11
- const { tsConfig, configs: { vue, astro, typescript } } = options;
12
- const { allowedDefaultProjects } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
11
+ const { tsConfig, configs: { vue, typescript } } = options;
12
+ const { allowedDefaultProjects: userAllowedDefaultProjects } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
13
13
  const { overrides } = isEnabled(typescript) ? typescript : defaultOptions.configs.typescript;
14
14
  const typescriptConfig = {
15
15
  name: "shayanthenerd/typescript",
16
16
  files: [
17
17
  globs.src,
18
18
  globs.jsxTsx,
19
- isEnabled(vue) ? globs.vue : "",
20
- isEnabled(astro) ? globs.astro : ""
19
+ isEnabled(vue) ? globs.vue : ""
21
20
  ].filter(isTruthy),
22
21
  plugins: { "@typescript-eslint": plugin },
23
22
  languageOptions: {
24
23
  parser,
25
24
  parserOptions: {
26
- warnOnUnsupportedTypeScriptVersion: false,
27
25
  tsconfigRootDir: tsConfig ? path.resolve(tsConfig.rootDir) : void 0,
28
26
  projectService: {
29
27
  defaultProject: tsConfig ? tsConfig.filename : void 0,
30
- allowDefaultProject: ["{prettier,eslint}.config.?([mc])ts", ...allowedDefaultProjects]
28
+ allowDefaultProject: userAllowedDefaultProjects
31
29
  }
32
30
  }
33
31
  },
@@ -1,9 +1,7 @@
1
1
  //#region src/helpers/ignores/defaultIgnorePatterns.ts
2
2
  const defaultIgnorePatterns = [
3
- "**/*.min.*",
4
3
  "**/jspm_packages",
5
4
  "**/pnpm-lock.yaml",
6
- "**/bower_components",
7
5
  "**/package-lock.json",
8
6
  "**/typegen.d.ts",
9
7
  "**/next-env.d.ts",
@@ -18,6 +16,7 @@ const defaultIgnorePatterns = [
18
16
  "**/public",
19
17
  "**/output",
20
18
  "**/.output",
19
+ "**/*.min.*",
21
20
  "**/.serverless",
22
21
  "**/.eslint-config-inspector",
23
22
  "**/tmp",
@@ -29,22 +28,18 @@ const defaultIgnorePatterns = [
29
28
  "**/.cache",
30
29
  "**/deno_dir",
31
30
  "**/.parcel-cache",
32
- "**/*.lerna_backup",
33
31
  "**/.postcss-cache",
34
32
  "**/.vitepress/cache",
35
33
  "**/vite.config.*.timestamp-*",
36
34
  "**/.nx",
37
35
  "**/.vite",
38
- "**/.yarn",
39
36
  "**/.nuxt",
40
37
  "**/.next",
41
38
  "**/.astro",
42
39
  "**/.vitest",
43
40
  "**/.vercel",
44
- "**/.svelte-kit",
45
41
  "**/.vite-inspect",
46
42
  "**/coverage",
47
- "**/_fixtures",
48
43
  "**/.nyc_output",
49
44
  "**/__snapshots__",
50
45
  "**/.idea",
@@ -34,7 +34,10 @@ const defaultOptions = {
34
34
  settings: {}
35
35
  },
36
36
  configs: {
37
- astro: { overrides: {} },
37
+ astro: {
38
+ accessibility: false,
39
+ overrides: {}
40
+ },
38
41
  baseline: {
39
42
  baseline: "widely",
40
43
  css: {
@@ -52,7 +55,10 @@ const defaultOptions = {
52
55
  },
53
56
  overrides: {}
54
57
  },
55
- css: { overrides: {} },
58
+ css: {
59
+ allowedUnknownPseudoSelectors: [],
60
+ overrides: {}
61
+ },
56
62
  html: {
57
63
  idNamingConvention: "snake_case",
58
64
  overrides: {}
@@ -77,7 +83,11 @@ const defaultOptions = {
77
83
  ui: { prefix: "U" },
78
84
  overrides: {}
79
85
  },
80
- packageJson: { overrides: {} },
86
+ packageJson: {
87
+ allowedDistTags: [],
88
+ allowedDistTagsFor: [],
89
+ overrides: {}
90
+ },
81
91
  perfectionist: {
82
92
  sortType: "line-length",
83
93
  overrides: {}
@@ -7,8 +7,12 @@ function enableDetectedConfigs(options) {
7
7
  "typescript": options.configs?.typescript === false,
8
8
  "zod": options.configs?.zod === false,
9
9
  "astro": options.configs?.astro === false,
10
+ "eslint-plugin-jsx-a11y-x": isEnabled(options.configs?.astro) && options.configs?.astro?.accessibility === false,
10
11
  "react": options.configs?.react === false,
11
12
  "next": options.configs?.next === false,
13
+ "@tanstack/react-router": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.router === false,
14
+ "@tanstack/react-start": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.start === false,
15
+ "@tanstack/react-query": isEnabled(options.configs?.tanstack) && options.configs?.tanstack?.query === false,
12
16
  "vue": options.configs?.vue === false,
13
17
  "nuxt": options.configs?.nuxt === false,
14
18
  "@nuxt/ui": isEnabled(options.configs?.nuxt) && options.configs?.nuxt?.ui === false,
@@ -19,10 +23,12 @@ function enableDetectedConfigs(options) {
19
23
  "storybook": options.configs?.test?.storybook === false,
20
24
  "@playwright/test": options.configs?.test?.playwright === false
21
25
  };
26
+ const isAstroDetected = isPackageDetected("astro", options);
22
27
  const autoDetectedPackages = {
23
28
  typescript: isPackageDetected("typescript", options),
24
29
  zod: isPackageDetected("zod", options),
25
- astro: isPackageDetected("astro", options),
30
+ astro: isAstroDetected,
31
+ eslintPluginJsxA11yX: isAstroDetected && isPackageDetected("eslint-plugin-jsx-a11y-x", options),
26
32
  react: isPackageDetected("react", options),
27
33
  next: isPackageDetected("next", options),
28
34
  tanstackStart: isPackageDetected("@tanstack/react-start", options),
@@ -38,6 +44,8 @@ function enableDetectedConfigs(options) {
38
44
  storybook: isPackageDetected("storybook", options),
39
45
  playwright: isPackageDetected("@playwright/test", options)
40
46
  };
47
+ options.autoDetectDeps ??= defaultOptions.autoDetectDeps;
48
+ options.env ??= defaultOptions.env;
41
49
  options.configs ??= {};
42
50
  options.configs.test ??= {};
43
51
  options.configs.node ??= true;
@@ -50,7 +58,7 @@ function enableDetectedConfigs(options) {
50
58
  options.configs.importX ??= true;
51
59
  options.configs.stylistic ??= true;
52
60
  options.configs.perfectionist ??= true;
53
- options.configs.baseline ??= options.env === "browser";
61
+ options.configs.baseline ??= options.autoDetectDeps && options.env === "browser";
54
62
  options.configs.typescript ??= autoDetectedPackages.typescript;
55
63
  options.configs.zod ??= autoDetectedPackages.zod;
56
64
  options.configs.astro ??= autoDetectedPackages.astro;
@@ -80,18 +88,22 @@ function enableDetectedConfigs(options) {
80
88
  options.configs.vue = options.configs.vue === true ? {} : options.configs.vue;
81
89
  options.configs.vue.blockLang = { script: "ts" };
82
90
  }
83
- if (options.configs.tanstack) {
84
- if (options.configs.tanstack === true) options.configs.tanstack = {};
85
- options.configs.tanstack.start ??= autoDetectedPackages.tanstackStart;
86
- options.configs.tanstack.query ??= autoDetectedPackages.tanstackQuery;
87
- options.configs.tanstack.router ??= autoDetectedPackages.tanstackRouter;
88
- }
89
91
  if (options.configs.nuxt) {
90
92
  if (options.configs.nuxt === true) options.configs.nuxt = {};
91
93
  options.configs.nuxt.ui ??= autoDetectedPackages.nuxtUI;
92
94
  options.configs.nuxt.icon ??= autoDetectedPackages.nuxtIcon;
93
95
  options.configs.nuxt.image ??= autoDetectedPackages.nuxtImage;
94
96
  }
97
+ if (options.configs.astro) {
98
+ options.configs.astro = options.configs.astro === true ? {} : options.configs.astro;
99
+ options.configs.astro.accessibility ??= autoDetectedPackages.eslintPluginJsxA11yX;
100
+ }
101
+ if (options.configs.tanstack) {
102
+ if (options.configs.tanstack === true) options.configs.tanstack = {};
103
+ options.configs.tanstack.start ??= autoDetectedPackages.tanstackStart;
104
+ options.configs.tanstack.query ??= autoDetectedPackages.tanstackQuery;
105
+ options.configs.tanstack.router ??= autoDetectedPackages.tanstackRouter;
106
+ }
95
107
  if (options.autoDetectDeps === "verbose") logDetectedPackages(explicitlyDisabledConfigs);
96
108
  return options;
97
109
  }
package/dist/index.d.mts CHANGED
@@ -35,6 +35,7 @@ import { Linter } from "eslint";
35
35
  * ],
36
36
  * );
37
37
  */
38
+ declare function defineConfig(): Linter.Config[];
38
39
  declare function defineConfig(options: Options): Linter.Config[];
39
40
  declare function defineConfig(configs: Linter.Config[]): Linter.Config[];
40
41
  declare function defineConfig(options: Options, configs: Linter.Config[]): Linter.Config[];
@@ -1,60 +1,67 @@
1
+ import { defaultOptions } from "../helpers/options/defaultOptions.mjs";
1
2
  import { isEnabled } from "../utils/isEnabled.mjs";
2
3
  //#region src/rules/astro.ts
3
- const astroRules = {
4
- "astro/missing-client-only-directive-value": "error",
5
- "astro/no-conflict-set-directives": "error",
6
- "astro/no-deprecated-astro-canonicalurl": "error",
7
- "astro/no-deprecated-astro-fetchcontent": "error",
8
- "astro/no-deprecated-astro-resolve": "error",
9
- "astro/no-deprecated-getentrybyslug": "error",
10
- "astro/no-exports-from-components": "error",
11
- "astro/no-prerender-export-outside-pages": "error",
12
- "astro/no-unused-define-vars-in-style": "warn",
13
- "astro/no-set-html-directive": "warn",
14
- "astro/no-unsafe-inline-scripts": "warn",
15
- "astro/no-set-text-directive": "warn",
16
- "astro/no-unused-css-selector": "warn",
17
- "astro/prefer-class-list-directive": "warn",
18
- "astro/prefer-split-class-list": "warn",
19
- "astro/jsx-a11y/alt-text": "error",
20
- "astro/jsx-a11y/anchor-ambiguous-text": "warn",
21
- "astro/jsx-a11y/anchor-has-content": "warn",
22
- "astro/jsx-a11y/anchor-is-valid": "error",
23
- "astro/jsx-a11y/aria-activedescendant-has-tabindex": "warn",
24
- "astro/jsx-a11y/aria-props": "error",
25
- "astro/jsx-a11y/aria-proptypes": "error",
26
- "astro/jsx-a11y/aria-role": "warn",
27
- "astro/jsx-a11y/aria-unsupported-elements": "error",
28
- "astro/jsx-a11y/autocomplete-valid": "error",
29
- "astro/jsx-a11y/click-events-have-key-events": "warn",
30
- "astro/jsx-a11y/control-has-associated-label": "warn",
31
- "astro/jsx-a11y/heading-has-content": "warn",
32
- "astro/jsx-a11y/html-has-lang": "error",
33
- "astro/jsx-a11y/iframe-has-title": "warn",
34
- "astro/jsx-a11y/img-redundant-alt": "warn",
35
- "astro/jsx-a11y/interactive-supports-focus": "warn",
36
- "astro/jsx-a11y/label-has-associated-control": "warn",
37
- "astro/jsx-a11y/lang": "error",
38
- "astro/jsx-a11y/media-has-caption": "warn",
39
- "astro/jsx-a11y/mouse-events-have-key-events": "warn",
40
- "astro/jsx-a11y/no-access-key": "warn",
41
- "astro/jsx-a11y/no-aria-hidden-on-focusable": "error",
42
- "astro/jsx-a11y/no-autofocus": "warn",
43
- "astro/jsx-a11y/no-distracting-elements": "warn",
44
- "astro/jsx-a11y/no-interactive-element-to-noninteractive-role": "warn",
45
- "astro/jsx-a11y/no-noninteractive-element-interactions": "warn",
46
- "astro/jsx-a11y/no-noninteractive-element-to-interactive-role": "warn",
47
- "astro/jsx-a11y/no-noninteractive-tabindex": "warn",
48
- "astro/jsx-a11y/no-redundant-roles": "warn",
49
- "astro/jsx-a11y/no-static-element-interactions": "warn",
50
- "astro/jsx-a11y/prefer-tag-over-role": "warn",
51
- "astro/jsx-a11y/role-has-required-aria-props": "warn",
52
- "astro/jsx-a11y/role-supports-aria-props": "warn",
53
- "astro/jsx-a11y/scope": "error",
54
- "astro/jsx-a11y/tabindex-no-positive": "warn"
55
- };
56
4
  function getAstroRules(options) {
57
- const { importX, stylistic } = options.configs;
5
+ const { astro, importX, stylistic } = options.configs;
6
+ const { semi } = isEnabled(stylistic) ? stylistic : defaultOptions.configs.stylistic;
7
+ const { accessibility } = isEnabled(astro) ? astro : defaultOptions.configs.astro;
8
+ const astroRules = {
9
+ "astro/missing-client-only-directive-value": "error",
10
+ "astro/no-conflict-set-directives": "error",
11
+ "astro/no-deprecated-astro-canonicalurl": "error",
12
+ "astro/no-deprecated-astro-fetchcontent": "error",
13
+ "astro/no-deprecated-astro-resolve": "error",
14
+ "astro/no-deprecated-getentrybyslug": "error",
15
+ "astro/no-exports-from-components": "error",
16
+ "astro/no-prerender-export-outside-pages": "error",
17
+ "astro/no-unused-define-vars-in-style": "warn",
18
+ "astro/no-set-html-directive": "warn",
19
+ "astro/no-unsafe-inline-scripts": "warn",
20
+ "astro/no-set-text-directive": "warn",
21
+ "astro/no-unused-css-selector": "warn",
22
+ "astro/prefer-class-list-directive": "warn",
23
+ "astro/prefer-split-class-list": "warn",
24
+ "astro/semi": ["warn", semi]
25
+ };
26
+ const astroJsxA11yRules = {
27
+ "astro/jsx-a11y/alt-text": "error",
28
+ "astro/jsx-a11y/anchor-ambiguous-text": "warn",
29
+ "astro/jsx-a11y/anchor-has-content": "warn",
30
+ "astro/jsx-a11y/anchor-is-valid": "error",
31
+ "astro/jsx-a11y/aria-activedescendant-has-tabindex": "warn",
32
+ "astro/jsx-a11y/aria-props": "error",
33
+ "astro/jsx-a11y/aria-proptypes": "error",
34
+ "astro/jsx-a11y/aria-role": "warn",
35
+ "astro/jsx-a11y/aria-unsupported-elements": "error",
36
+ "astro/jsx-a11y/autocomplete-valid": "error",
37
+ "astro/jsx-a11y/click-events-have-key-events": "warn",
38
+ "astro/jsx-a11y/control-has-associated-label": "warn",
39
+ "astro/jsx-a11y/heading-has-content": "warn",
40
+ "astro/jsx-a11y/html-has-lang": "error",
41
+ "astro/jsx-a11y/iframe-has-title": "warn",
42
+ "astro/jsx-a11y/img-redundant-alt": "warn",
43
+ "astro/jsx-a11y/interactive-supports-focus": "warn",
44
+ "astro/jsx-a11y/label-has-associated-control": "warn",
45
+ "astro/jsx-a11y/lang": "error",
46
+ "astro/jsx-a11y/media-has-caption": "warn",
47
+ "astro/jsx-a11y/mouse-events-have-key-events": "warn",
48
+ "astro/jsx-a11y/no-access-key": "warn",
49
+ "astro/jsx-a11y/no-aria-hidden-on-focusable": "error",
50
+ "astro/jsx-a11y/no-autofocus": "warn",
51
+ "astro/jsx-a11y/no-distracting-elements": "warn",
52
+ "astro/jsx-a11y/no-interactive-element-to-noninteractive-role": "warn",
53
+ "astro/jsx-a11y/no-noninteractive-element-interactions": "warn",
54
+ "astro/jsx-a11y/no-noninteractive-element-to-interactive-role": "warn",
55
+ "astro/jsx-a11y/no-noninteractive-tabindex": "warn",
56
+ "astro/jsx-a11y/no-redundant-roles": "warn",
57
+ "astro/jsx-a11y/no-static-element-interactions": "warn",
58
+ "astro/jsx-a11y/prefer-tag-over-role": "warn",
59
+ "astro/jsx-a11y/role-has-required-aria-props": "warn",
60
+ "astro/jsx-a11y/role-supports-aria-props": "warn",
61
+ "astro/jsx-a11y/scope": "error",
62
+ "astro/jsx-a11y/tabindex-no-positive": "warn"
63
+ };
64
+ if (isEnabled(accessibility)) Object.assign(astroRules, astroJsxA11yRules);
58
65
  if (isEnabled(importX)) astroRules["import-x/exports-last"] = "off";
59
66
  if (isEnabled(stylistic)) astroRules["@stylistic/jsx-one-expression-per-line"] = "off";
60
67
  return astroRules;
@@ -14,7 +14,7 @@ function getBaselineRules(options) {
14
14
  baseline,
15
15
  includeWebApis: { preset: "auto" },
16
16
  includeJsBuiltins: { preset: "auto" },
17
- ignoreFeatures: userIgnoredFeatures,
17
+ ignoreFeatures: ["async-clipboard", ...userIgnoredFeatures],
18
18
  ignoreNodeTypes: userIgnoredNodeTypes
19
19
  }]
20
20
  };