@webadeva/eslint-config 0.1.1 → 0.1.3

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.
package/README.md CHANGED
@@ -31,12 +31,12 @@ import config from "@webadeva/eslint-config";
31
31
  export default config;
32
32
  ```
33
33
 
34
- | Preset | Import | Includes |
35
- | --------- | ----------------------------------- | ---------------------------- |
36
- | Base | `@webadeva/eslint-config` | TypeScript, Prettier, import |
37
- | React | `@webadeva/eslint-config/react` | Base + React |
38
- | Next.js | `@webadeva/eslint-config/next` | React + Next.js |
39
- | Storybook | `@webadeva/eslint-config/storybook` | Next.js + Storybook |
34
+ | Preset | Import | Includes |
35
+ | --------- | ----------------------------------- | ----------------------- |
36
+ | Base | `@webadeva/eslint-config` | TypeScript, Prettier |
37
+ | React | `@webadeva/eslint-config/react` | Base + React + JSX a11y |
38
+ | Next.js | `@webadeva/eslint-config/next` | React + Next.js |
39
+ | Storybook | `@webadeva/eslint-config/storybook` | Next.js + Storybook |
40
40
 
41
41
  `@webadeva/eslint-config/base` is an alias of the base preset. Only the base preset can be loaded with `require()`. The others are ESM-only because `@eslint-react` is.
42
42
 
@@ -66,16 +66,51 @@ Type-aware rules run on every file that typed linting can cover:
66
66
  - **Up to 8 root-level files outside any tsconfig**, such as config files and scripts, are typed with a [built-in fallback tsconfig](tsconfig.default.json). Root-level `.jsx`/`.tsx` files are included only if `@types/react` is installed.
67
67
  - **Other files outside any tsconfig** get every rule except the type-aware ones. TS files in this situation are reported by `webadeva/typescript-file-in-project`, so they don't go unchecked unnoticed.
68
68
 
69
+ ## Accessibility
70
+
71
+ The React preset (and so the Next.js and Storybook presets) turns on the `recommended` config of [`eslint-plugin-jsx-a11y-x`](https://github.com/es-tooling/eslint-plugin-jsx-a11y-x), a maintained fork of `eslint-plugin-jsx-a11y`. Its rules are prefixed `jsx-a11y-x/`. To use the stricter rule set, or to adjust single rules, add a config after the preset:
72
+
73
+ ```js
74
+ import jsxA11y from "eslint-plugin-jsx-a11y-x";
75
+ import config from "@webadeva/eslint-config/react";
76
+
77
+ export default [
78
+ ...config,
79
+ jsxA11y.configs.strict,
80
+ { rules: { "jsx-a11y-x/no-autofocus": "off" } },
81
+ ];
82
+ ```
83
+
84
+ Install `eslint-plugin-jsx-a11y-x` in your project if you import it yourself like this.
85
+
86
+ Lint rules only see static JSX. To check the rendered DOM, run [`@axe-core/react`](https://github.com/dequelabs/axe-core-npm/tree/develop/packages/react) in development. It is a runtime tool, not an ESLint plugin, so this package doesn't install it. Add it to your app and call it from your entry point:
87
+
88
+ ```bash
89
+ pnpm add -D @axe-core/react
90
+ ```
91
+
92
+ ```js
93
+ import React from "react";
94
+ import ReactDOM from "react-dom";
95
+
96
+ if (process.env.NODE_ENV !== "production") {
97
+ const { default: axe } = await import("@axe-core/react");
98
+ await axe(React, ReactDOM, 1000);
99
+ }
100
+ ```
101
+
102
+ Violations are logged to the browser console. `@axe-core/react` does not support React 18 or later, and it needs Node.js `>=22.12`.
103
+
69
104
  ## Defaults worth knowing
70
105
 
71
106
  - These paths are ignored: `dist`, `*.config.*`, `**/__tests__/**`, `**/__mocks__/**`.
72
- - Prettier runs as a lint rule and uses your Prettier config.
107
+ - Prettier runs as a lint rule and uses your Prettier config. Imports are not linted by a dedicated plugin. Add [`prettier-plugin-organize-imports`](https://github.com/simonhaenisch/prettier-plugin-organize-imports) to your Prettier config, and `eslint --fix` sorts imports and removes unused ones.
73
108
  - The React preset detects your React version, including in monorepos.
74
109
  - Some rules are opinionated: `no-console` warns, and arrow functions are preferred over `function`.
75
110
 
76
111
  ## What's included
77
112
 
78
- [`@eslint/js`](https://eslint.org/docs/latest/rules/), [typescript-eslint](https://typescript-eslint.io/) (recommended + stylistic, type-checked), [Prettier](https://github.com/prettier/eslint-plugin-prettier), [import](https://github.com/import-js/eslint-plugin-import), [eslint-comments](https://github.com/eslint-community/eslint-plugin-eslint-comments), [prefer-arrow-functions](https://github.com/JamieMason/eslint-plugin-prefer-arrow-functions), [@eslint-react](https://eslint-react.xyz/), [react-hooks](https://react.dev/reference/eslint-plugin-react-hooks), [react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh), [Next.js](https://nextjs.org/docs/app/api-reference/config/eslint), [Storybook](https://github.com/storybookjs/eslint-plugin-storybook), and [this package's own rules](docs/rules.md).
113
+ [`@eslint/js`](https://eslint.org/docs/latest/rules/), [typescript-eslint](https://typescript-eslint.io/) (recommended + stylistic, type-checked), [Prettier](https://github.com/prettier/eslint-plugin-prettier), [eslint-comments](https://github.com/eslint-community/eslint-plugin-eslint-comments), [prefer-arrow-functions](https://github.com/JamieMason/eslint-plugin-prefer-arrow-functions), [@eslint-react](https://eslint-react.xyz/), [react-hooks](https://react.dev/reference/eslint-plugin-react-hooks), [react-refresh](https://github.com/ArnaudBarre/eslint-plugin-react-refresh), [jsx-a11y-x](https://github.com/es-tooling/eslint-plugin-jsx-a11y-x), [Next.js](https://nextjs.org/docs/app/api-reference/config/eslint), [Storybook](https://github.com/storybookjs/eslint-plugin-storybook), and [this package's own rules](docs/rules.md).
79
114
 
80
115
  ## Contributing
81
116
 
package/dist/index.cjs CHANGED
@@ -24,8 +24,6 @@ let _eslint_community_eslint_plugin_eslint_comments = require("@eslint-community
24
24
  _eslint_community_eslint_plugin_eslint_comments = __toESM(_eslint_community_eslint_plugin_eslint_comments, 1);
25
25
  let _eslint_js = require("@eslint/js");
26
26
  _eslint_js = __toESM(_eslint_js, 1);
27
- let eslint_plugin_import = require("eslint-plugin-import");
28
- eslint_plugin_import = __toESM(eslint_plugin_import, 1);
29
27
  let eslint_plugin_prefer_arrow_functions = require("eslint-plugin-prefer-arrow-functions");
30
28
  eslint_plugin_prefer_arrow_functions = __toESM(eslint_plugin_prefer_arrow_functions, 1);
31
29
  let eslint_plugin_prettier = require("eslint-plugin-prettier");
@@ -205,9 +203,23 @@ const getProjectFiles = (configPath, seen = /* @__PURE__ */ new Set()) => {
205
203
  projectFilesCache.set(configPath, files);
206
204
  return files;
207
205
  };
206
+ let projectFilesReadAt = Date.now();
207
+ const changedSinceFilesRead = (filePath) => {
208
+ try {
209
+ return (0, node_fs.statSync)(filePath).ctimeMs >= projectFilesReadAt;
210
+ } catch {
211
+ return false;
212
+ }
213
+ };
208
214
  const isInProject = (filePath) => {
209
215
  const configPath = findNearestConfig((0, node_path.dirname)(filePath));
210
- return configPath !== void 0 && getProjectFiles(configPath).has((0, node_path.resolve)(filePath));
216
+ if (configPath === void 0) return false;
217
+ const path = (0, node_path.resolve)(filePath);
218
+ if (getProjectFiles(configPath).has(path)) return true;
219
+ if (!changedSinceFilesRead(path)) return false;
220
+ projectFilesCache.clear();
221
+ projectFilesReadAt = Date.now();
222
+ return getProjectFiles(configPath).has(path);
211
223
  };
212
224
  /** The tsconfig typescript-eslint uses for files outside every project. */
213
225
  const defaultProjectConfig = packageRequire.resolve("@webadeva/eslint-config/tsconfig.default.json");
@@ -287,8 +299,7 @@ const baseConfigs = [
287
299
  prettier: eslint_plugin_prettier.default,
288
300
  "prefer-arrow-functions": eslint_plugin_prefer_arrow_functions.default,
289
301
  "@typescript-eslint": tseslint$1.plugin,
290
- "eslint-comments": _eslint_community_eslint_plugin_eslint_comments.default,
291
- import: eslint_plugin_import.default
302
+ "eslint-comments": _eslint_community_eslint_plugin_eslint_comments.default
292
303
  },
293
304
  rules: {
294
305
  ..._eslint_js.default.configs.recommended.rules,
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-Wrh4hLMj.mjs";
1
+ import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-BQwdjN7J.mjs";
2
2
  //#region src/index.ts
3
3
  const config = [...baseConfigs, ...untypedFilesConfigs()];
4
4
  //#endregion
package/dist/next.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-Wrh4hLMj.mjs";
2
- import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-C-VV0l5P.mjs";
1
+ import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-BQwdjN7J.mjs";
2
+ import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-DWgZpojs.mjs";
3
3
  import { t as nextConfigs } from "./next-CWjuCwpN.mjs";
4
4
  //#region src/next.ts
5
5
  const config = [
@@ -1,7 +1,8 @@
1
- import { r as ensureTypeScript } from "./untyped-Wrh4hLMj.mjs";
1
+ import { r as ensureTypeScript } from "./untyped-BQwdjN7J.mjs";
2
2
  import { createRequire } from "node:module";
3
3
  import { readFileSync, readdirSync } from "node:fs";
4
4
  import { join } from "node:path";
5
+ import pluginJsxA11y from "eslint-plugin-jsx-a11y-x";
5
6
  import pluginReactHooks from "eslint-plugin-react-hooks";
6
7
  import pluginReactRefresh from "eslint-plugin-react-refresh";
7
8
  //#region src/utils/detect-react-version.ts
@@ -42,6 +43,7 @@ const reactConfigs = [
42
43
  eslintReact.configs["recommended-typescript"],
43
44
  pluginReactHooks.configs.flat["recommended-latest"],
44
45
  pluginReactRefresh.configs.recommended,
46
+ pluginJsxA11y.configs.recommended,
45
47
  {
46
48
  settings: { react: { version: detectReactVersion() } },
47
49
  rules: {
package/dist/react.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-Wrh4hLMj.mjs";
2
- import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-C-VV0l5P.mjs";
1
+ import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-BQwdjN7J.mjs";
2
+ import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-DWgZpojs.mjs";
3
3
  //#region src/react.ts
4
4
  const config = [
5
5
  ...baseConfigs,
@@ -1,5 +1,5 @@
1
- import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-Wrh4hLMj.mjs";
2
- import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-C-VV0l5P.mjs";
1
+ import { n as baseConfigs, t as untypedFilesConfigs } from "./untyped-BQwdjN7J.mjs";
2
+ import { n as reactDisableTypeChecked, t as reactConfigs } from "./react-DWgZpojs.mjs";
3
3
  import { t as nextConfigs } from "./next-CWjuCwpN.mjs";
4
4
  import storybook from "eslint-plugin-storybook";
5
5
  //#region src/configs/storybook.ts
@@ -1,11 +1,10 @@
1
1
  import { createRequire } from "node:module";
2
2
  import eslintComments from "@eslint-community/eslint-plugin-eslint-comments";
3
3
  import pluginJs from "@eslint/js";
4
- import importPlugin from "eslint-plugin-import";
5
4
  import preferArrowFunctions from "eslint-plugin-prefer-arrow-functions";
6
5
  import prettier from "eslint-plugin-prettier";
7
6
  import globals from "globals";
8
- import { existsSync, readdirSync } from "node:fs";
7
+ import { existsSync, readdirSync, statSync } from "node:fs";
9
8
  import { dirname, join, resolve } from "node:path";
10
9
  //#region src/plugin/rules/max-lines.ts
11
10
  const DEFAULTS = {
@@ -177,9 +176,23 @@ const getProjectFiles = (configPath, seen = /* @__PURE__ */ new Set()) => {
177
176
  projectFilesCache.set(configPath, files);
178
177
  return files;
179
178
  };
179
+ let projectFilesReadAt = Date.now();
180
+ const changedSinceFilesRead = (filePath) => {
181
+ try {
182
+ return statSync(filePath).ctimeMs >= projectFilesReadAt;
183
+ } catch {
184
+ return false;
185
+ }
186
+ };
180
187
  const isInProject = (filePath) => {
181
188
  const configPath = findNearestConfig(dirname(filePath));
182
- return configPath !== void 0 && getProjectFiles(configPath).has(resolve(filePath));
189
+ if (configPath === void 0) return false;
190
+ const path = resolve(filePath);
191
+ if (getProjectFiles(configPath).has(path)) return true;
192
+ if (!changedSinceFilesRead(path)) return false;
193
+ projectFilesCache.clear();
194
+ projectFilesReadAt = Date.now();
195
+ return getProjectFiles(configPath).has(path);
183
196
  };
184
197
  /** The tsconfig typescript-eslint uses for files outside every project. */
185
198
  const defaultProjectConfig = packageRequire.resolve("@webadeva/eslint-config/tsconfig.default.json");
@@ -259,8 +272,7 @@ const baseConfigs = [
259
272
  prettier,
260
273
  "prefer-arrow-functions": preferArrowFunctions,
261
274
  "@typescript-eslint": tseslint$1.plugin,
262
- "eslint-comments": eslintComments,
263
- import: importPlugin
275
+ "eslint-comments": eslintComments
264
276
  },
265
277
  rules: {
266
278
  ...pluginJs.configs.recommended.rules,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webadeva/eslint-config",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Shared ESLint flat configs for TypeScript projects: type-aware rules, Prettier, and presets for React, Next.js, and Storybook.",
5
5
  "keywords": [
6
6
  "eslint",
@@ -12,6 +12,7 @@
12
12
  "typescript-eslint",
13
13
  "prettier",
14
14
  "react",
15
+ "a11y",
15
16
  "nextjs",
16
17
  "storybook",
17
18
  "lint"
@@ -101,8 +102,7 @@
101
102
  "@typescript-eslint/eslint-plugin": "^8.71.2",
102
103
  "@typescript-eslint/parser": "^8.71.2",
103
104
  "eslint-config-prettier": "^10.1.8",
104
- "eslint-plugin-import": "^2.32.0",
105
- "eslint-plugin-jsx-a11y": "^6.10.2",
105
+ "eslint-plugin-jsx-a11y-x": "^0.2.0",
106
106
  "eslint-plugin-prefer-arrow-functions": "^3.10.2",
107
107
  "eslint-plugin-prettier": "^5.5.7",
108
108
  "eslint-plugin-react-hooks": "^7.1.1",