eslint-config-webpack 4.9.3 → 4.9.5

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.
@@ -2,6 +2,7 @@ import importPlugin from "eslint-plugin-import";
2
2
  import unicornPlugin from "eslint-plugin-unicorn";
3
3
  import globals from "globals";
4
4
 
5
+ /** @type {import("eslint").Linter.Config} */
5
6
  const recommendedBrowserOutdatedScriptConfig = {
6
7
  name: "browser/recommended-outdated-script",
7
8
  languageOptions: {
@@ -12,6 +13,7 @@ const recommendedBrowserOutdatedScriptConfig = {
12
13
  },
13
14
  };
14
15
 
16
+ /** @type {import("eslint").Linter.Config} */
15
17
  const recommendedBrowserOutdatedCommonjsConfig = {
16
18
  name: "browser/recommended-outdated-commonjs",
17
19
  languageOptions: {
@@ -22,6 +24,7 @@ const recommendedBrowserOutdatedCommonjsConfig = {
22
24
  },
23
25
  };
24
26
 
27
+ /** @type {import("eslint").Linter.Config} */
25
28
  const recommendedBrowserOutdatedModuleConfig = {
26
29
  name: "browser/recommended-outdated-module",
27
30
  languageOptions: {
@@ -32,6 +35,7 @@ const recommendedBrowserOutdatedModuleConfig = {
32
35
  },
33
36
  };
34
37
 
38
+ /** @type {import("eslint").Linter.Config} */
35
39
  const recommendedBrowserConfig = {
36
40
  name: "browser/recommended",
37
41
  languageOptions: {
package/configs/index.js CHANGED
@@ -9,17 +9,43 @@ import stylisticConfig from "./stylistic.js";
9
9
  import typescriptConfig from "./typescript.js";
10
10
  import webpackSpecial from "./webpack-special.js";
11
11
 
12
- const configs = {
13
- ...browserConfig,
14
- ...javascriptConfig,
15
- ...jestConfig,
16
- ...markdownConfig,
17
- ...nodeConfig,
18
- ...stylisticConfig,
19
- ...typescriptConfig,
20
- ...reactConfig,
21
- ...packageJSON,
22
- ...webpackSpecial,
23
- };
12
+ // TODO merge this file with config.js into one to avoid problems with types
13
+
14
+ /** @typedef {typeof browserConfig & typeof javascriptConfig & typeof jestConfig & typeof markdownConfig & typeof nodeConfig & typeof stylisticConfig & typeof typescriptConfig & typeof reactConfig & typeof packageJSON & typeof webpackSpecial} BasicConfigs */
15
+ /** @typedef {import("eslint").Linter.Config} Config */
16
+ /** @typedef {(Config | Config[])[]} NestedConfig */
17
+ /**
18
+ * @typedef {{
19
+ * recommended: NestedConfig,
20
+ * "node-recommended": NestedConfig,
21
+ * "recommended-module": NestedConfig,
22
+ * "node-recommended-module": NestedConfig,
23
+ * "recommended-commonjs": NestedConfig,
24
+ * "node-recommended-commonjs": NestedConfig,
25
+ * "recommended-dirty": NestedConfig,
26
+ * "node-recommended-dirty": NestedConfig,
27
+ * "browser-recommended": NestedConfig,
28
+ * "browser-outdated-recommended-script": NestedConfig,
29
+ * "browser-outdated-recommended-commonjs": NestedConfig,
30
+ * "browser-outdated-recommended-module": NestedConfig,
31
+ * "browser-outdated-recommended": NestedConfig,
32
+ * "universal-recommended": NestedConfig,
33
+ }} AddvancedConfigs */
34
+
35
+ /** @type {BasicConfigs & AddvancedConfigs} */
36
+ const configs =
37
+ /** @type {BasicConfigs & AddvancedConfigs} */
38
+ ({
39
+ ...browserConfig,
40
+ ...javascriptConfig,
41
+ ...jestConfig,
42
+ ...markdownConfig,
43
+ ...nodeConfig,
44
+ ...stylisticConfig,
45
+ ...typescriptConfig,
46
+ ...reactConfig,
47
+ ...packageJSON,
48
+ ...webpackSpecial,
49
+ });
24
50
 
25
51
  export default configs;
@@ -5,6 +5,7 @@ import globals from "globals";
5
5
  import { allExtensions, javascriptExtensions } from "./utils/extensions.js";
6
6
  import isTypescriptInstalled from "./utils/is-typescript-installed.js";
7
7
 
8
+ /** @type {import("eslint").Linter.Config["rules"]} */
8
9
  const possibleProblems = {
9
10
  "array-callback-return": [
10
11
  "error",
@@ -195,6 +196,7 @@ const possibleProblems = {
195
196
  // "valid-typeof": "error",
196
197
  };
197
198
 
199
+ /** @type {import("eslint").Linter.Config["rules"]} */
198
200
  const suggestions = {
199
201
  "accessor-pairs": "error",
200
202
 
@@ -336,7 +338,8 @@ const suggestions = {
336
338
  // No need
337
339
  // "max-statements": "off",
338
340
 
339
- "new-cap": "error",
341
+ // For `prop-types`
342
+ "new-cap": ["error", { capIsNewExceptionPattern: "^.+Type$" }],
340
343
 
341
344
  "no-alert": "error",
342
345
 
@@ -658,10 +661,12 @@ const suggestions = {
658
661
  yoda: "error",
659
662
  };
660
663
 
664
+ /** @type {import("eslint").Linter.Config["rules"]} */
661
665
  const layoutAndFormatting = {
662
666
  "unicode-bom": ["error", "never"],
663
667
  };
664
668
 
669
+ /** @type {import("eslint").Linter.Config["rules"]} */
665
670
  const unicornRules = {
666
671
  // No need
667
672
  // "unicorn/better-regex": "off",
@@ -685,6 +690,8 @@ const unicornRules = {
685
690
  // No need
686
691
  // "unicorn/consistent-function-scoping": "off",
687
692
 
693
+ "unicorn/consistent-template-literal-escape": "error",
694
+
688
695
  // No need
689
696
  // "unicorn/custom-error-definition": "off",
690
697
 
@@ -701,7 +708,7 @@ const unicornRules = {
701
708
  // No need
702
709
  // "unicorn/explicit-length-check": "off",
703
710
 
704
- // TODO
711
+ // TODO enable in future?
705
712
  "unicorn/filename-case": [
706
713
  "off",
707
714
  {
@@ -730,6 +737,9 @@ const unicornRules = {
730
737
  // No need
731
738
  // "unicorn/import-style": "off",
732
739
 
740
+ // No need
741
+ // "unicorn/isolated-functions": "off",
742
+
733
743
  "unicorn/new-for-builtins": "error",
734
744
 
735
745
  "unicorn/no-abusive-eslint-disable": "error",
@@ -826,7 +836,7 @@ const unicornRules = {
826
836
  // No need
827
837
  // "unicorn/no-this-assignment": "off",
828
838
 
829
- // TODO - enable in future?
839
+ // TODO enable in future? Need to check performance
830
840
  // "unicorn/no-typeof-undefined": "off",
831
841
 
832
842
  "unicorn/no-unnecessary-array-flat-depth": "error",
@@ -854,6 +864,8 @@ const unicornRules = {
854
864
 
855
865
  "unicorn/no-useless-fallback-in-spread": "error",
856
866
 
867
+ "unicorn/no-useless-iterator-to-array": "error",
868
+
857
869
  "unicorn/no-useless-length-check": "error",
858
870
 
859
871
  "unicorn/no-useless-promise-resolve-reject": "error",
@@ -985,6 +997,9 @@ const unicornRules = {
985
997
  // No need
986
998
  // "unicorn/prefer-set-size": "off",
987
999
 
1000
+ // TODO enable in the next major release
1001
+ // "unicorn/prefer-simple-condition-first": "error",
1002
+
988
1003
  // No need
989
1004
  // "unicorn/prefer-single-call": "off",
990
1005
 
@@ -1037,6 +1052,10 @@ const unicornRules = {
1037
1052
  // No need
1038
1053
  // "unicorn/switch-case-braces": "off",
1039
1054
 
1055
+ // TODO maybe?
1056
+ // No need
1057
+ // "unicorn/switch-case-break-position": "off",
1058
+
1040
1059
  // No need
1041
1060
  // "unicorn/template-indent": "off",
1042
1061
 
@@ -1045,6 +1064,7 @@ const unicornRules = {
1045
1064
  "unicorn/throw-new-error": "error",
1046
1065
  };
1047
1066
 
1067
+ /** @type {import("eslint").Linter.Config["rules"]} */
1048
1068
  const importRules = {
1049
1069
  ...importPlugin.flatConfigs.recommended.rules,
1050
1070
 
@@ -1196,52 +1216,62 @@ const importRules = {
1196
1216
  // "import/prefer-default-export": "off",
1197
1217
  };
1198
1218
 
1219
+ const needTypescriptSupport = isTypescriptInstalled();
1220
+ const extensions = needTypescriptSupport ? allExtensions : javascriptExtensions;
1221
+
1222
+ /** @type {import("eslint").Linter.Config} */
1223
+ const baseConfig = {
1224
+ ...javascriptConfig.configs.recommended,
1225
+ files: [`**/*.{${extensions.map((item) => item.slice(1)).join(",")}}`],
1226
+ ignores: ["**/*.d.ts"],
1227
+ settings: {
1228
+ "import/extensions": extensions,
1229
+ "import/ignore": [
1230
+ "eslint-plugin-.*",
1231
+ "\\.(coffee|scss|css|less|hbs|svg|md|jpg|jpeg|png|gif|webp|avif)$",
1232
+ ],
1233
+ "import/resolver": {
1234
+ node: {
1235
+ extensions: [...extensions],
1236
+ },
1237
+ },
1238
+ },
1239
+ plugins: {
1240
+ unicorn: unicornPlugin,
1241
+ import: importPlugin,
1242
+ },
1243
+ linterOptions: {
1244
+ reportUnusedDisableDirectives: true,
1245
+ reportUnusedInlineConfigs: "error",
1246
+ },
1247
+ rules: {
1248
+ ...javascriptConfig.configs.recommended.rules,
1249
+ ...possibleProblems,
1250
+ ...suggestions,
1251
+ ...layoutAndFormatting,
1252
+ ...unicornRules,
1253
+ ...importRules,
1254
+ },
1255
+ };
1256
+
1257
+ /** @typedef {2015 | 2016 | 2017 | 2018 | 2019 | 2020 | 2021 | 2022 | 2023 | 2024 | 2025 | 2026} Year */
1258
+
1199
1259
  /**
1200
- * @param {number} esVersion es version
1201
- * @returns {Record<string, string | number>} config
1260
+ * @param {Year | 5} esVersion es version
1261
+ * @returns {import("eslint").Linter.Config} config
1202
1262
  */
1203
1263
  function getConfig(esVersion) {
1204
- const extensions = isTypescriptInstalled()
1205
- ? allExtensions
1206
- : javascriptExtensions;
1207
1264
  const config = {
1208
- ...javascriptConfig.configs.recommended,
1265
+ ...baseConfig,
1209
1266
  name: `javascript/es${esVersion}`,
1210
- files: [`**/*.{${extensions.map((item) => item.slice(1)).join(",")}}`],
1211
- ignores: ["**/*.d.ts"],
1212
- settings: {
1213
- "import/extensions": extensions,
1214
- "import/ignore": [
1215
- "eslint-plugin-.*",
1216
- "\\.(coffee|scss|css|less|hbs|svg|md|jpg|jpeg|png|gif|webp|avif)$",
1217
- ],
1218
- "import/resolver": {
1219
- node: {
1220
- extensions: [...extensions],
1221
- },
1222
- },
1223
- },
1224
- plugins: {
1225
- unicorn: unicornPlugin,
1226
- import: importPlugin,
1227
- },
1228
1267
  languageOptions: {
1229
1268
  ecmaVersion: esVersion,
1230
1269
  globals: {
1231
1270
  ...globals[`es${esVersion}`],
1232
1271
  },
1233
1272
  },
1234
- linterOptions: {
1235
- reportUnusedDisableDirectives: true,
1236
- reportUnusedInlineConfigs: "error",
1237
- },
1238
1273
  rules: {
1239
- ...javascriptConfig.configs.recommended.rules,
1240
- ...possibleProblems,
1241
- ...suggestions,
1242
- ...layoutAndFormatting,
1243
- ...unicornRules,
1244
- ...importRules,
1274
+ ...baseConfig.rules,
1245
1275
  },
1246
1276
  };
1247
1277
 
@@ -1301,11 +1331,12 @@ function getConfig(esVersion) {
1301
1331
  return config;
1302
1332
  }
1303
1333
 
1334
+ /** @type {Record<"javascript/es5" | "javascript/recommended" | `javascript/es${Year}`, import("eslint").Linter.Config>} */
1304
1335
  const configs = {};
1305
- const esVersions = Array.from({ length: 11 }, (_x, i) => 15 + i);
1336
+ const esVersions = Array.from({ length: 12 }, (_x, i) => 15 + i);
1306
1337
 
1307
1338
  for (const [i, esVersion] of esVersions.entries()) {
1308
- const year = 2000 + esVersion;
1339
+ const year = /** @type {Year} */ (2000 + esVersion);
1309
1340
  const config = getConfig(year);
1310
1341
 
1311
1342
  configs[`javascript/es${year}`] = config;
package/configs/jest.js CHANGED
@@ -1,20 +1,33 @@
1
1
  import globals from "globals";
2
+ import getJsonFile from "./utils/get-json-file.js";
3
+
4
+ /** @type {import("type-fest").PackageJson | null} */
5
+ const packageJson = getJsonFile("package.json");
2
6
 
3
7
  /**
4
- * @returns {Promise<Record<string, string>>} config
8
+ * @returns {Promise<import("eslint").Linter.Config>} config
5
9
  */
6
10
  async function getJestRecommendedConfig() {
7
- let jestPlugin;
11
+ if (packageJson === null) {
12
+ return {
13
+ name: "jest/please-install-jest-to-enable-it",
14
+ };
15
+ }
16
+
17
+ const dependencies = packageJson.dependencies || {};
18
+ const devDependencies = packageJson.devDependencies || {};
8
19
 
9
- try {
10
- jestPlugin = (await import("eslint-plugin-jest")).default;
11
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
12
- } catch (_err) {
13
- // Nothing
20
+ if (
21
+ typeof dependencies.jest === "undefined" &&
22
+ typeof devDependencies.jest === "undefined"
23
+ ) {
24
+ return {
25
+ name: "jest/please-install-jest-to-enable-it",
26
+ };
14
27
  }
15
28
 
16
- const jsdocConfig =
17
- (jestPlugin && jestPlugin.configs["flat/recommended"]) || {};
29
+ const jestPlugin = (await import("eslint-plugin-jest")).default;
30
+ const jsdocConfig = jestPlugin.configs["flat/recommended"];
18
31
 
19
32
  return {
20
33
  ...jsdocConfig,
@@ -1,17 +1,10 @@
1
1
  import isTypescriptInstalled from "./utils/is-typescript-installed.js";
2
2
 
3
3
  /**
4
- * @returns {Promise<Record<string, string>>} config
4
+ * @returns {Promise<import("eslint").Linter.Config[]>} config
5
5
  */
6
6
  async function getMarkdownRecommendedConfig() {
7
- let markdownPlugin;
8
-
9
- try {
10
- markdownPlugin = (await import("@eslint/markdown")).default;
11
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
12
- } catch (_err) {
13
- // Nothing
14
- }
7
+ const markdownPlugin = (await import("@eslint/markdown")).default;
15
8
 
16
9
  return [
17
10
  {
@@ -19,6 +12,7 @@ async function getMarkdownRecommendedConfig() {
19
12
  files: ["**/*.md"],
20
13
  processor: "markdown/markdown",
21
14
  plugins: {
15
+ // @ts-expect-error bad types
22
16
  markdown: markdownPlugin,
23
17
  },
24
18
  },
package/configs/node.js CHANGED
@@ -2,6 +2,7 @@ import importPlugin from "eslint-plugin-import";
2
2
  import globals from "globals";
3
3
  import isTypescriptInstalled from "./utils/is-typescript-installed.js";
4
4
 
5
+ /** @type {import("eslint").Linter.Config["rules"]} */
5
6
  const commonRules = {
6
7
  // No need
7
8
  // "n/callback-return": "error",
@@ -101,12 +102,16 @@ const commonRules = {
101
102
 
102
103
  "n/prefer-global/console": ["error", "always"],
103
104
 
105
+ "n/prefer-global/crypto": ["error", "always"],
106
+
104
107
  "n/prefer-global/process": ["error", "always"],
105
108
 
106
109
  "n/prefer-global/text-decoder": ["error", "always"],
107
110
 
108
111
  "n/prefer-global/text-encoder": ["error", "always"],
109
112
 
113
+ "n/prefer-global/timers": ["error", "always"],
114
+
110
115
  "n/prefer-global/url": ["error", "always"],
111
116
 
112
117
  "n/prefer-global/url-search-params": ["error", "always"],
@@ -123,25 +128,14 @@ const commonRules = {
123
128
  // "n/process-exit-as-throw": "error",
124
129
  };
125
130
 
126
- let nodePlugin;
127
-
128
131
  const ignores = ["**/*.d.ts"];
129
132
 
130
133
  /**
131
- * @returns {Promise<Record<string, string>>} config
134
+ * @returns {Promise<import("eslint").Linter.Config>} config
132
135
  */
133
136
  async function getCommonJSConfig() {
134
- if (!nodePlugin) {
135
- try {
136
- nodePlugin = (await import("eslint-plugin-n")).default;
137
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
138
- } catch (_err) {
139
- // Nothing
140
- }
141
- }
142
-
143
- const nodeConfig =
144
- (nodePlugin && nodePlugin.configs["flat/recommended-script"]) || {};
137
+ const nodePlugin = (await import("eslint-plugin-n")).default;
138
+ const nodeConfig = nodePlugin.configs["flat/recommended-script"];
145
139
 
146
140
  return {
147
141
  ...nodeConfig,
@@ -183,22 +177,11 @@ async function getCommonJSConfig() {
183
177
  }
184
178
 
185
179
  /**
186
- * @returns {Promise<Record<string, string>>} config
180
+ * @returns {Promise<import("eslint").Linter.Config>} config
187
181
  */
188
182
  async function getModuleConfig() {
189
- let nodePlugin;
190
-
191
- if (!nodePlugin) {
192
- try {
193
- nodePlugin = (await import("eslint-plugin-n")).default;
194
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
195
- } catch (_err) {
196
- // Nothing
197
- }
198
- }
199
-
200
- const nodeConfig =
201
- (nodePlugin && nodePlugin.configs["flat/recommended-module"]) || {};
183
+ const nodePlugin = (await import("eslint-plugin-n")).default;
184
+ const nodeConfig = nodePlugin.configs["flat/recommended-module"];
202
185
 
203
186
  return {
204
187
  ...nodeConfig,
@@ -230,19 +213,10 @@ const commonjsConfig = await getCommonJSConfig();
230
213
  const moduleConfig = await getModuleConfig();
231
214
 
232
215
  /**
233
- * @returns {Promise<Record<string, string>>} config
216
+ * @returns {Promise<import("eslint").Linter.Config>} config
234
217
  */
235
218
  async function getDirtyConfig() {
236
- let nodePlugin;
237
-
238
- if (!nodePlugin) {
239
- try {
240
- nodePlugin = (await import("eslint-plugin-n")).default;
241
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
242
- } catch (_err) {
243
- // Nothing
244
- }
245
- }
219
+ const nodePlugin = (await import("eslint-plugin-n")).default;
246
220
 
247
221
  return {
248
222
  name: "node/dirty",
@@ -250,7 +224,12 @@ async function getDirtyConfig() {
250
224
  n: nodePlugin,
251
225
  import: importPlugin,
252
226
  },
253
- ignores: [...new Set([...commonjsConfig.ignores, ...moduleConfig.ignores])],
227
+ ignores: [
228
+ ...new Set([
229
+ ...(commonjsConfig.ignores || []),
230
+ ...(moduleConfig.ignores || []),
231
+ ]),
232
+ ],
254
233
  languageOptions: {
255
234
  sourceType: "module",
256
235
  parserOptions: {
@@ -1,8 +1,7 @@
1
1
  import { configs } from "../plugins/package-json/index.js";
2
2
 
3
- const recommendedBrowserConfig = {
4
- ...configs.recommended,
5
- };
3
+ /** @type {import("eslint").Linter.Config} */
4
+ const recommendedBrowserConfig = configs.recommended;
6
5
 
7
6
  export default {
8
7
  "package-json/recommended": recommendedBrowserConfig,
package/configs/react.js CHANGED
@@ -1,36 +1,42 @@
1
+ import getJsonFile from "./utils/get-json-file.js";
2
+
3
+ /** @type {import("type-fest").PackageJson | null} */
4
+ const packageJson = getJsonFile("package.json");
5
+
1
6
  /**
2
- * @returns {Promise<Record<string, string>>} config
7
+ * @returns {Promise<import("eslint").Linter.Config>} config
3
8
  */
4
9
  async function getReactRecommendedConfig() {
5
- let reactPlugin;
6
-
7
- try {
8
- reactPlugin = (await import("eslint-plugin-react")).default;
9
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
10
- } catch (_err) {
11
- // Nothing
10
+ if (packageJson === null) {
11
+ return {
12
+ name: "react/please-install-react-to-enable-it",
13
+ };
12
14
  }
13
15
 
14
- let reactHooksPlugin;
16
+ const dependencies = packageJson.dependencies || {};
17
+ const devDependencies = packageJson.devDependencies || {};
15
18
 
16
- try {
17
- reactHooksPlugin = (await import("eslint-plugin-react-hooks")).default;
18
- // eslint-disable-next-line unicorn/prefer-optional-catch-binding
19
- } catch (_err) {
20
- // Nothing
19
+ if (
20
+ typeof dependencies.react === "undefined" &&
21
+ typeof dependencies.preact === "undefined" &&
22
+ typeof devDependencies.react === "undefined" &&
23
+ typeof devDependencies.preact === "undefined"
24
+ ) {
25
+ return {
26
+ name: "react/please-install-react-to-enable-it",
27
+ };
21
28
  }
22
29
 
23
- const { recommended, "jsx-runtime": jsxRuntime } = (reactPlugin &&
24
- reactPlugin.configs &&
25
- reactPlugin.configs.flat) || { recommended: {}, "jsx-runtime": {} };
30
+ const reactPlugin = (await import("eslint-plugin-react")).default;
31
+ const { recommended, "jsx-runtime": jsxRuntime } = reactPlugin.configs.flat;
26
32
 
27
- const { recommended: recommendedHooks } = (reactHooksPlugin &&
28
- reactHooksPlugin.configs &&
29
- reactHooksPlugin.configs.flat) || { recommended: {} };
33
+ const reactHooksPlugin = (await import("eslint-plugin-react-hooks")).default;
34
+ const { recommended: recommendedHooks } = reactHooksPlugin.configs.flat;
30
35
 
31
36
  return {
32
37
  ...recommended,
33
38
  ...recommendedHooks,
39
+ name: "react/recommended",
34
40
  plugins: {
35
41
  ...recommended.plugins,
36
42
  ...recommendedHooks.plugins,
@@ -2,6 +2,7 @@ import stylisticPlugin from "@stylistic/eslint-plugin";
2
2
  import prettierPlugin from "eslint-plugin-prettier";
3
3
  import prettierConfig from "eslint-plugin-prettier/recommended";
4
4
 
5
+ /** @type {import("eslint").Linter.Config} */
5
6
  const recommendedConfig = {
6
7
  ...prettierConfig,
7
8
  name: "stylistic/recommended",