@pplancq/eslint-config 6.1.5 → 6.2.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.
- package/CHANGELOG.md +24 -0
- package/README.md +17 -1
- package/main.js +81 -25
- package/package.json +12 -9
- package/rules/base.js +2 -2
- package/rules/import.js +269 -262
- package/rules/playwright.js +3 -2
- package/rules/prettier.js +2 -2
- package/rules/react-jsx-a11y.js +216 -218
- package/rules/react.js +604 -591
- package/rules/typescript.js +554 -548
- package/rules/utils.js +63 -0
- package/rules/vitest.js +176 -168
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
## 6.2.0 (2026-10-26)
|
|
2
|
+
|
|
3
|
+
### 🎉 Features
|
|
4
|
+
|
|
5
|
+
- **eslint-config:** migrate import rules to eslint-plugin-import-x ([#1938](https://github.com/pplancq/dev-tools/pull/1938))
|
|
6
|
+
- **eslint-config:** migrate JSX a11y rules to eslint-plugin-jsx-a11y-x ([#1937](https://github.com/pplancq/dev-tools/pull/1937))
|
|
7
|
+
|
|
8
|
+
### 🐞 Bug Fixes
|
|
9
|
+
|
|
10
|
+
- **eslint-config:** support disableStyleOnly without eslint-plugin-prettier ([#1956](https://github.com/pplancq/dev-tools/pull/1956))
|
|
11
|
+
- **eslint-config:** remove unneeded eslint-import-resolver-node dependency ([#1939](https://github.com/pplancq/dev-tools/pull/1939))
|
|
12
|
+
|
|
13
|
+
### 📦 Dependencies
|
|
14
|
+
|
|
15
|
+
- **deps:** update typescript-eslint mono repo to ^8.71.2 ([#1952](https://github.com/pplancq/dev-tools/pull/1952))
|
|
16
|
+
- **deps:** update dependency @vitest/eslint-plugin to ^1.6.28 ([#1962](https://github.com/pplancq/dev-tools/pull/1962))
|
|
17
|
+
- **deps:** update typescript-eslint mono repo to ^8.71.1 ([#1934](https://github.com/pplancq/dev-tools/pull/1934))
|
|
18
|
+
- **deps:** update dependency eslint-plugin-playwright to ^2.12.1 ([#1932](https://github.com/pplancq/dev-tools/pull/1932))
|
|
19
|
+
|
|
20
|
+
### ❤️ Thank You
|
|
21
|
+
|
|
22
|
+
- Paul PLANCQ
|
|
23
|
+
- pplancq @pplancq
|
|
24
|
+
|
|
1
25
|
## 6.1.5 (2026-10-06)
|
|
2
26
|
|
|
3
27
|
### 📦 Dependencies
|
package/README.md
CHANGED
|
@@ -48,10 +48,24 @@ The following options can be passed to the `defineConfig` function. All options
|
|
|
48
48
|
| unitTestFiles | ['**/*.{test,spec,steps}.{js,jsx,ts,tsx}'] | Patterns for unit test files |
|
|
49
49
|
| unitE2eFiles | ['tests/**/*.{test,spec}.{js,jsx,ts,tsx}'] | Patterns for end-to-end (E2E) test files (ex: Playwright) |
|
|
50
50
|
| enableReact | false | Enables rules for React and Testing Library files |
|
|
51
|
+
| rulesNaming | 'legacy' | Naming of the rules of the plugins replaced by a fork (`eslint-plugin-import-x` and `eslint-plugin-jsx-a11y-x`). 'legacy' (default) keeps the historical rule names (`import/xxx`, `jsx-a11y/xxx`)<br/>'modern' uses the forks namespaces (`import-x/xxx`, `jsx-a11y-x/xxx`), as listed in the [rules documentation](./docs/rules.md). See [Rules naming](#rules-naming) |
|
|
51
52
|
| enableVitest | false | Enables rules for Vitest files |
|
|
52
53
|
| enablePlaywright | false | Enables rules for Playwright E2E test files |
|
|
53
54
|
| enablePrettier | 'off' | 'off' disables Prettier integration (default). Recommended when using Prettier separately; install `eslint-config-prettier` to disable conflicting ESLint formatting rules<br/>'on' enables Prettier as an ESLint rule. **Deprecated**, will be removed in the next major release<br/>'disableStyleOnly' disables conflicting ESLint formatting rules without running Prettier as an ESLint rule. Recommended transition option to keep the same behavior as `'on'` while running Prettier separately |
|
|
54
|
-
| extendConfig | [] | Extends the ESLint configuration
|
|
55
|
+
| extendConfig | [] | Extends the ESLint configuration. With `rulesNaming: 'legacy'`, the `import/*` settings it contains are copied to `import-x/*` |
|
|
56
|
+
|
|
57
|
+
### Rules naming
|
|
58
|
+
|
|
59
|
+
The `import` and `jsx-a11y` plugins are replaced by their maintained forks, [`eslint-plugin-import-x`](https://github.com/un-ts/eslint-plugin-import-x) and [`eslint-plugin-jsx-a11y-x`](https://github.com/eslint-community/eslint-plugin-jsx-a11y-x), which support ESLint 10. The `rulesNaming` option lets you migrate without breaking your configuration:
|
|
60
|
+
|
|
61
|
+
| `rulesNaming` | Rules | Settings |
|
|
62
|
+
| -------------------- | -------------------------------- | ------------------------ |
|
|
63
|
+
| `'legacy'` (default) | `import/xxx`, `jsx-a11y/xxx` | `import-x/*` (see below) |
|
|
64
|
+
| `'modern'` | `import-x/xxx`, `jsx-a11y-x/xxx` | `import-x/*` |
|
|
65
|
+
|
|
66
|
+
- The [rules documentation](./docs/rules.md) lists the `modern` names. With `'legacy'`, replace `import-x/` by `import/` and `jsx-a11y-x/` by `jsx-a11y/`.
|
|
67
|
+
- `eslint-plugin-import-x` only reads the `import-x/*` settings, whatever the rules namespace. In `legacy` mode, the `import/*` settings found in `extendConfig` (for example `import/resolver`) are copied automatically to `import-x/*` and a warning lists them.
|
|
68
|
+
- The default will become `'modern'` in the next major release. See the [Migration Guide](./MIGRATION.md#rules-naming-rulesnaming) to migrate now.
|
|
55
69
|
|
|
56
70
|
### Prettier Configuration
|
|
57
71
|
|
|
@@ -82,4 +96,6 @@ For a complete list of all active ESLint rules in each configuration, please ref
|
|
|
82
96
|
|
|
83
97
|
## Migration
|
|
84
98
|
|
|
99
|
+
To switch to the forks naming (`rulesNaming: 'modern'`), please refer to the [Migration Guide](./MIGRATION.md#rules-naming-rulesnaming).
|
|
100
|
+
|
|
85
101
|
If you are upgrading from version 3 to version 4 of `@pplancq/eslint-config`, please refer to the [Migration Guide](./MIGRATION.md#migration-guide-pplancqeslint-config-v3-to-v4) for detailed instructions.
|
package/main.js
CHANGED
|
@@ -6,12 +6,13 @@ import { playwrightRules } from "./rules/playwright.js";
|
|
|
6
6
|
import { reactJsxA11yRules } from "./rules/react-jsx-a11y.js";
|
|
7
7
|
import { reactRules, reactTestRules, reactTypescriptRules } from "./rules/react.js";
|
|
8
8
|
import { typescriptRules } from "./rules/typescript.js";
|
|
9
|
+
import { mapLegacyImportSettings, prefix } from "./rules/utils.js";
|
|
9
10
|
import { vitestRules } from "./rules/vitest.js";
|
|
10
11
|
|
|
11
|
-
let
|
|
12
|
+
let createPrettierRules = () => ({});
|
|
12
13
|
try {
|
|
13
14
|
const prettierConfig = await import("./rules/prettier.js");
|
|
14
|
-
|
|
15
|
+
createPrettierRules = prettierConfig.prettierRules;
|
|
15
16
|
} catch {
|
|
16
17
|
// eslint-plugin-prettier is not installed
|
|
17
18
|
}
|
|
@@ -27,6 +28,49 @@ const isColorSupported =
|
|
|
27
28
|
const yellow = isColorSupported ? (text) => `\x1b[33m${text}\x1b[39m` : (text) => text;
|
|
28
29
|
const bold = isColorSupported ? (text) => `\x1b[1m${text}\x1b[22m` : (text) => text;
|
|
29
30
|
|
|
31
|
+
const warn = (message) => console.warn(`${bold(yellow("WARNING:"))} ${message}`);
|
|
32
|
+
|
|
33
|
+
const resolveNamespaces = (rulesNaming) => {
|
|
34
|
+
const modern = rulesNaming === "modern";
|
|
35
|
+
|
|
36
|
+
return {
|
|
37
|
+
jsxA11y: modern ? "jsx-a11y-x" : "jsx-a11y",
|
|
38
|
+
import: modern ? "import-x" : "import",
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
const warnLegacyNaming = (enableReact) => {
|
|
43
|
+
const legacyNames = enableReact ? "'import/xxx' and 'jsx-a11y/xxx'" : "'import/xxx'";
|
|
44
|
+
const modernNames = enableReact ? "'import-x/xxx' and 'jsx-a11y-x/xxx'" : "'import-x/xxx'";
|
|
45
|
+
|
|
46
|
+
warn(
|
|
47
|
+
`[rulesNaming: 'legacy'] the rules use the legacy ${legacyNames} names. In the next major release, the default will become 'modern' (${modernNames}). Set rulesNaming: 'modern' to migrate now.`,
|
|
48
|
+
);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const resolvePrettierRules = (enablePrettier) => {
|
|
52
|
+
const prettierRules = createPrettierRules();
|
|
53
|
+
|
|
54
|
+
if (enablePrettier === "disableStyleOnly" && prettierRules.rules?.["prettier/prettier"] !== undefined) {
|
|
55
|
+
prettierRules.rules["prettier/prettier"] = "off";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
return prettierRules;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const resolveExtendConfig = (extendConfig) => {
|
|
62
|
+
const { configs, mapped } = mapLegacyImportSettings(extendConfig);
|
|
63
|
+
|
|
64
|
+
if (mapped.length > 0) {
|
|
65
|
+
const settings = mapped.map((setting) => `'${setting}'`).join(", ");
|
|
66
|
+
warn(
|
|
67
|
+
`[rulesNaming: 'legacy'] eslint-plugin-import-x only reads the 'import-x/*' settings. The following settings were copied automatically: ${settings}. Rename them to 'import-x/*' in your configuration.`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return configs;
|
|
72
|
+
};
|
|
73
|
+
|
|
30
74
|
/**
|
|
31
75
|
* define eslint flat config.
|
|
32
76
|
*
|
|
@@ -35,6 +79,12 @@ const bold = isColorSupported ? (text) => `\x1b[1m${text}\x1b[22m` : (text) => t
|
|
|
35
79
|
* @param {string[]} [options.unitTestFiles=['**\/*.{test,spec,steps}.{js,jsx,ts,tsx}']]
|
|
36
80
|
* @param {string[]} [options.unitE2eFiles=['tests/**\/*.{test,spec}.{js,jsx,ts,tsx}']]
|
|
37
81
|
* @param {boolean} [options.enableReact=false]
|
|
82
|
+
* @param {'legacy' | 'modern'} [options.rulesNaming='legacy']
|
|
83
|
+
* - `'legacy'`: registers `eslint-plugin-import-x` under the `import` namespace (rules named `import/xxx`)
|
|
84
|
+
* and `eslint-plugin-jsx-a11y-x` under the `jsx-a11y` namespace (rules named `jsx-a11y/xxx`).
|
|
85
|
+
* The `import/*` settings found in `extendConfig` are copied to `import-x/*`, the only prefix `eslint-plugin-import-x` reads.
|
|
86
|
+
* - `'modern'`: registers `eslint-plugin-import-x` under its own namespace (rules named `import-x/xxx`)
|
|
87
|
+
* and `eslint-plugin-jsx-a11y-x` under its own namespace (rules named `jsx-a11y-x/xxx`).
|
|
38
88
|
* @param {boolean} [options.enableVitest=false]
|
|
39
89
|
* @param {boolean} [options.enablePlaywright=false]
|
|
40
90
|
* @param {'off' | 'on' | 'disableStyleOnly'} [options.enablePrettier='off']
|
|
@@ -54,46 +104,52 @@ export const defineConfig = ({
|
|
|
54
104
|
unitTestFiles = ["**/*.{test,spec,steps}.{js,jsx,ts,tsx}"],
|
|
55
105
|
unitE2eFiles = ["tests/**/*.{test,spec}.{js,jsx,ts,tsx}"],
|
|
56
106
|
enableReact = false,
|
|
107
|
+
rulesNaming = "legacy",
|
|
57
108
|
enableVitest = false,
|
|
58
109
|
enablePlaywright = false,
|
|
59
110
|
enablePrettier = "off",
|
|
60
111
|
extendConfig = [],
|
|
61
112
|
} = {}) => {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
reactTestRules.files = unitTestFiles;
|
|
65
|
-
vitestRules.files = unitTestFiles;
|
|
66
|
-
playwrightRules.files = unitE2eFiles;
|
|
113
|
+
const ns = resolveNamespaces(rulesNaming);
|
|
114
|
+
const legacyNaming = rulesNaming === "legacy";
|
|
67
115
|
|
|
68
116
|
if (enablePrettier === "on") {
|
|
69
|
-
|
|
70
|
-
|
|
117
|
+
warn(
|
|
118
|
+
"[enablePrettier: 'on'] is deprecated and will be removed in the next major release. Use 'disableStyleOnly' and run Prettier separately for formatting.",
|
|
71
119
|
);
|
|
72
120
|
}
|
|
73
121
|
|
|
74
|
-
if (
|
|
75
|
-
|
|
122
|
+
if (legacyNaming) {
|
|
123
|
+
warnLegacyNaming(enableReact);
|
|
76
124
|
}
|
|
77
125
|
|
|
126
|
+
const extendedConfig = legacyNaming ? resolveExtendConfig(extendConfig) : extendConfig;
|
|
127
|
+
|
|
128
|
+
const prettierRules = resolvePrettierRules(enablePrettier);
|
|
129
|
+
|
|
78
130
|
return [
|
|
79
|
-
importRules,
|
|
80
|
-
baseRules,
|
|
81
|
-
enableReact && reactJsxA11yRules,
|
|
82
|
-
typescriptRules,
|
|
83
|
-
enableReact && reactRules,
|
|
84
|
-
enableReact && reactTypescriptRules,
|
|
85
|
-
enableReact && reactTestRules,
|
|
131
|
+
importRules(ns),
|
|
132
|
+
baseRules(),
|
|
133
|
+
enableReact && reactJsxA11yRules(ns),
|
|
134
|
+
typescriptRules({ files: tsFiles, ...ns }),
|
|
135
|
+
enableReact && reactRules(ns),
|
|
136
|
+
enableReact && reactTypescriptRules({ files: tsFiles, ...ns }),
|
|
137
|
+
enableReact && reactTestRules({ files: unitTestFiles }),
|
|
86
138
|
enablePrettier !== "off" && prettierRules,
|
|
87
139
|
enablePrettier !== "off" && eslintConfigPrettier,
|
|
88
|
-
enableVitest && vitestRules,
|
|
89
|
-
enablePlaywright && playwrightRules,
|
|
140
|
+
enableVitest && vitestRules({ files: unitTestFiles, ...ns }),
|
|
141
|
+
enablePlaywright && playwrightRules({ files: unitE2eFiles }),
|
|
90
142
|
{
|
|
91
143
|
files: ["eslint.config.*"],
|
|
92
|
-
rules:
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
144
|
+
rules: prefix(
|
|
145
|
+
{
|
|
146
|
+
"import-x/no-extraneous-dependencies": "off",
|
|
147
|
+
"import-x/no-default-export": "off",
|
|
148
|
+
},
|
|
149
|
+
"import-x",
|
|
150
|
+
ns.import,
|
|
151
|
+
),
|
|
96
152
|
},
|
|
97
|
-
...
|
|
153
|
+
...extendedConfig,
|
|
98
154
|
].filter(Boolean);
|
|
99
155
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pplancq/eslint-config",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.2.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "pplancq eslint config",
|
|
6
6
|
"author": "pplancq <paul.plancq@outlook.fr>",
|
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
13
|
"docs:generate": "node scripts/generate-docs.mjs",
|
|
14
|
+
"test": "vitest run",
|
|
15
|
+
"test:watch": "vitest",
|
|
14
16
|
"lint:eslint": "eslint \"**/*.{js,mjs}\"",
|
|
15
17
|
"lint:eslint:fix": "eslint \"**/*.{js,mjs}\" --fix",
|
|
16
18
|
"lint:prettier": "prettier . --check --ignore-unknown",
|
|
@@ -37,15 +39,15 @@
|
|
|
37
39
|
"config"
|
|
38
40
|
],
|
|
39
41
|
"dependencies": {
|
|
40
|
-
"@typescript-eslint/eslint-plugin": "^8.71.
|
|
41
|
-
"@typescript-eslint/parser": "^8.71.
|
|
42
|
-
"@vitest/eslint-plugin": "^1.6.
|
|
42
|
+
"@typescript-eslint/eslint-plugin": "^8.71.2",
|
|
43
|
+
"@typescript-eslint/parser": "^8.71.2",
|
|
44
|
+
"@vitest/eslint-plugin": "^1.6.28",
|
|
43
45
|
"eslint-config-prettier": "^10.1.8",
|
|
44
46
|
"eslint-import-resolver-typescript": "^4.4.5",
|
|
45
|
-
"eslint-plugin-import": "^
|
|
47
|
+
"eslint-plugin-import-x": "^4.17.1",
|
|
46
48
|
"eslint-plugin-jest-dom": "^5.10.1",
|
|
47
|
-
"eslint-plugin-jsx-a11y": "^
|
|
48
|
-
"eslint-plugin-playwright": "^2.12.
|
|
49
|
+
"eslint-plugin-jsx-a11y-x": "^0.2.0",
|
|
50
|
+
"eslint-plugin-playwright": "^2.12.1",
|
|
49
51
|
"eslint-plugin-react": "^7.37.5",
|
|
50
52
|
"eslint-plugin-react-hooks": "^7.1.1",
|
|
51
53
|
"eslint-plugin-testing-library": "^7.16.2",
|
|
@@ -65,9 +67,10 @@
|
|
|
65
67
|
},
|
|
66
68
|
"devDependencies": {
|
|
67
69
|
"eslint": "^9.39.5",
|
|
68
|
-
"eslint-plugin-prettier": "^5.5.
|
|
70
|
+
"eslint-plugin-prettier": "^5.5.7",
|
|
69
71
|
"lint-staged": "^17.6.0",
|
|
70
|
-
"prettier": "^3.9.
|
|
72
|
+
"prettier": "^3.9.10",
|
|
73
|
+
"vitest": "^5.0.5"
|
|
71
74
|
},
|
|
72
75
|
"engines": {
|
|
73
76
|
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
|
package/rules/base.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import globals from "globals";
|
|
2
2
|
|
|
3
|
-
export const baseRules = {
|
|
3
|
+
export const baseRules = () => ({
|
|
4
4
|
languageOptions: {
|
|
5
5
|
ecmaVersion: "latest",
|
|
6
6
|
sourceType: "module",
|
|
@@ -1455,4 +1455,4 @@ export const baseRules = {
|
|
|
1455
1455
|
"wrap-regex": "off",
|
|
1456
1456
|
"yield-star-spacing": ["error", "after"],
|
|
1457
1457
|
},
|
|
1458
|
-
};
|
|
1458
|
+
});
|