eslint-config-webpack 4.1.4 → 4.2.1

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.
@@ -1,5 +1,5 @@
1
- import globals from "globals";
2
1
  import importPlugin from "eslint-plugin-import";
2
+ import globals from "globals";
3
3
 
4
4
  const recommendedBrowserConfig = {
5
5
  languageOptions: {
@@ -11,6 +11,20 @@ const recommendedBrowserConfig = {
11
11
  import: importPlugin,
12
12
  },
13
13
  rules: {
14
+ "unicorn/prefer-dom-node-append": "error",
15
+
16
+ "unicorn/prefer-dom-node-dataset": "error",
17
+
18
+ "unicorn/prefer-dom-node-remove": "error",
19
+
20
+ "unicorn/prefer-dom-node-text-content": "error",
21
+
22
+ "unicorn/prefer-modern-dom-apis": "error",
23
+
24
+ "unicorn/prefer-keyboard-event-key": "error",
25
+
26
+ "unicorn/prefer-query-selector": "error",
27
+
14
28
  "import/extensions": ["error", "always", { ignorePackages: true }],
15
29
  },
16
30
  };
package/configs/index.js CHANGED
@@ -3,6 +3,7 @@ import javascriptConfig from "./javascript.js";
3
3
  import jestConfig from "./jest.js";
4
4
  import markdownConfig from "./markdown.js";
5
5
  import nodeConfig from "./node.js";
6
+ import packageJSON from "./package-json.js";
6
7
  import stylisticConfig from "./stylistic.js";
7
8
  import typescriptConfig from "./typescript.js";
8
9
 
@@ -14,6 +15,7 @@ const configs = {
14
15
  ...nodeConfig,
15
16
  ...stylisticConfig,
16
17
  ...typescriptConfig,
18
+ ...packageJSON,
17
19
  };
18
20
 
19
21
  export default configs;
@@ -1,7 +1,7 @@
1
- import globals from "globals";
2
1
  import javascriptConfig from "@eslint/js";
3
- import unicornPlugin from "eslint-plugin-unicorn";
4
2
  import importPlugin from "eslint-plugin-import";
3
+ import unicornPlugin from "eslint-plugin-unicorn";
4
+ import globals from "globals";
5
5
  import { allExtensions } from "./utils/extensions.js";
6
6
 
7
7
  const possibleProblems = {
@@ -885,13 +885,17 @@ const unicornRules = {
885
885
 
886
886
  "unicorn/prefer-default-parameters": "error",
887
887
 
888
- "unicorn/prefer-dom-node-append": "error",
888
+ // Not here, define only for `browsers`
889
+ // "unicorn/prefer-dom-node-append": "error",
889
890
 
890
- "unicorn/prefer-dom-node-dataset": "error",
891
+ // Not here, define only for `browsers`
892
+ // "unicorn/prefer-dom-node-dataset": "error",
891
893
 
892
- "unicorn/prefer-dom-node-remove": "error",
894
+ // Not here, define only for `browsers`
895
+ // "unicorn/prefer-dom-node-remove": "error",
893
896
 
894
- "unicorn/prefer-dom-node-text-content": "error",
897
+ // Not here, define only for `browsers`
898
+ // "unicorn/prefer-dom-node-text-content": "error",
895
899
 
896
900
  "unicorn/prefer-event-target": "error",
897
901
 
@@ -907,7 +911,8 @@ const unicornRules = {
907
911
  // No need
908
912
  // "unicorn/prefer-json-parse-buffer": "off",
909
913
 
910
- "unicorn/prefer-keyboard-event-key": "error",
914
+ // Not here, define only for `browsers`
915
+ // "unicorn/prefer-keyboard-event-key": "error",
911
916
 
912
917
  "unicorn/prefer-logical-operator-over-ternary": "error",
913
918
 
@@ -918,7 +923,8 @@ const unicornRules = {
918
923
  // `| 0` is faster
919
924
  // "unicorn/prefer-math-trunc": "off",
920
925
 
921
- "unicorn/prefer-modern-dom-apis": "error",
926
+ // Not here, define only for `browsers`
927
+ // "unicorn/prefer-modern-dom-apis": "error",
922
928
 
923
929
  "unicorn/prefer-modern-math-apis": "error",
924
930
 
@@ -941,7 +947,8 @@ const unicornRules = {
941
947
 
942
948
  "unicorn/prefer-prototype-methods": "error",
943
949
 
944
- "unicorn/prefer-query-selector": "error",
950
+ // Not here, define only for `browsers`
951
+ // "unicorn/prefer-query-selector": "error",
945
952
 
946
953
  // No need
947
954
  // "unicorn/prefer-reflect-apply": "off",
@@ -1141,21 +1148,20 @@ const importRules = {
1141
1148
  // No need
1142
1149
  // "import/no-unassigned-import": "off",
1143
1150
 
1144
- // No need
1145
- // TODO consider this in the future
1146
- // "import/order": [
1147
- // "warn",
1148
- // {
1149
- // groups: [
1150
- // "builtin",
1151
- // "external",
1152
- // "internal",
1153
- // "parent",
1154
- // "sibling",
1155
- // "index",
1156
- // ]
1157
- // },
1158
- // ],
1151
+ "import/order": [
1152
+ "error",
1153
+ {
1154
+ named: {
1155
+ enabled: true,
1156
+ import: true,
1157
+ export: true,
1158
+ require: true,
1159
+ cjsExports: true,
1160
+ types: "mixed",
1161
+ },
1162
+ alphabetize: { order: "asc" },
1163
+ },
1164
+ ],
1159
1165
 
1160
1166
  // No need
1161
1167
  // "import/prefer-default-export": "off",
@@ -1195,6 +1201,7 @@ function getConfig(esVersion) {
1195
1201
  },
1196
1202
  linterOptions: {
1197
1203
  reportUnusedDisableDirectives: true,
1204
+ reportUnusedInlineConfigs: "error",
1198
1205
  },
1199
1206
  rules: {
1200
1207
  ...javascriptConfig.configs.recommended.rules,
package/configs/jest.js CHANGED
@@ -206,6 +206,21 @@ async function getJestRecommendedConfig() {
206
206
  // Allow to output information in tests
207
207
  "no-console": "off",
208
208
 
209
+ // Allow to use `eval` for tests
210
+ "no-eval": "off",
211
+
212
+ // Allow to have any regexps in tests, useful to clean up/etc
213
+ "no-control-regex": "off",
214
+
215
+ // Allow to use any builtins, syntax and node API in tests
216
+ "n/no-unsupported-features/es-builtins": "off",
217
+ "n/no-unsupported-features/es-syntax": "off",
218
+ "n/no-unsupported-features/node-builtins": "off",
219
+
220
+ // Allow to `require` and `import` any things in tests
221
+ "n/no-unpublished-require": "off",
222
+ "n/no-unpublished-import": "off",
223
+
209
224
  // Doesn't require jsdoc for tests, they are either redundant or we have a separate task for checking types of tests
210
225
  "jsdoc/require-jsdoc": "off",
211
226
  },
@@ -60,6 +60,10 @@ async function getMarkdownRecommendedConfig() {
60
60
 
61
61
  "n/no-unpublished-import": "off",
62
62
 
63
+ "n/no-missing-import": "off",
64
+
65
+ "n/no-missing-require": "off",
66
+
63
67
  "import/no-unresolved": "off",
64
68
 
65
69
  "import/no-extraneous-dependencies": "off",
package/configs/node.js CHANGED
@@ -1,5 +1,5 @@
1
- import globals from "globals";
2
1
  import importPlugin from "eslint-plugin-import";
2
+ import globals from "globals";
3
3
 
4
4
  const commonRules = {
5
5
  // No need
@@ -38,11 +38,11 @@ const commonRules = {
38
38
  // Deprecated
39
39
  // "n/no-hide-core-modules": "error",
40
40
 
41
- // From recommended
42
- // "n/no-missing-import": "error",
41
+ // We have `import/no-unresolved` rule
42
+ "n/no-missing-import": "off",
43
43
 
44
- // From recommended
45
- // "n/no-missing-require": "error",
44
+ // We have `import/no-unresolved` rule
45
+ "n/no-missing-require": "off",
46
46
 
47
47
  // No need
48
48
  // "n/no-mixed-requires": "error",
@@ -144,6 +144,7 @@ async function getCommonJSConfig() {
144
144
  import: importPlugin,
145
145
  },
146
146
  rules: {
147
+ ...nodeConfig.rules,
147
148
  ...commonRules,
148
149
  "n/exports-style": "error",
149
150
  "n/no-path-concat": "error",
@@ -200,6 +201,7 @@ async function getModuleConfig() {
200
201
  import: importPlugin,
201
202
  },
202
203
  rules: {
204
+ ...nodeConfig.rules,
203
205
  ...commonRules,
204
206
  "import/extensions": [
205
207
  "error",
@@ -0,0 +1,9 @@
1
+ import { configs } from "../plugins/package-json/index.js";
2
+
3
+ const recommendedBrowserConfig = {
4
+ ...configs.recommended,
5
+ };
6
+
7
+ export default {
8
+ "package-json/recommended": recommendedBrowserConfig,
9
+ };
@@ -1,6 +1,6 @@
1
+ import stylisticPlugin from "@stylistic/eslint-plugin";
1
2
  import prettierPlugin from "eslint-plugin-prettier";
2
3
  import prettierConfig from "eslint-plugin-prettier/recommended";
3
- import stylisticPlugin from "@stylistic/eslint-plugin";
4
4
 
5
5
  const recommendedConfig = {
6
6
  ...prettierConfig,
@@ -2,4 +2,4 @@ const javascriptExtensions = [".js", ".cjs", ".mjs", ".jsx"];
2
2
  const typescriptExtensions = [".ts", ".cts", ".mts", ".tsx"];
3
3
  const allExtensions = [...javascriptExtensions, ...typescriptExtensions];
4
4
 
5
- export { javascriptExtensions, typescriptExtensions, allExtensions };
5
+ export { allExtensions, javascriptExtensions, typescriptExtensions };
package/configs.js CHANGED
@@ -3,8 +3,8 @@ import path from "node:path";
3
3
  import { globalIgnores } from "eslint/config";
4
4
  import semver from "semver";
5
5
  import configs from "./configs/index.js";
6
- import ignorePaths from "./ignore-paths.js";
7
6
  import { typescriptExtensions } from "./configs/utils/extensions.js";
7
+ import ignorePaths from "./ignore-paths.js";
8
8
 
9
9
  const SKIP_TIME = 5000;
10
10
 
@@ -295,6 +295,7 @@ configs.recommended = [
295
295
  jestConfig,
296
296
  configs["markdown/recommended"],
297
297
  configs["stylistic/recommended"],
298
+ configs["package-json/recommended"],
298
299
  ];
299
300
 
300
301
  configs["recommended-module"] = [
@@ -306,6 +307,7 @@ configs["recommended-module"] = [
306
307
  jestConfig,
307
308
  configs["markdown/recommended"],
308
309
  configs["stylistic/recommended"],
310
+ configs["package-json/recommended"],
309
311
  ];
310
312
 
311
313
  configs["recommended-commonjs"] = [
@@ -317,6 +319,7 @@ configs["recommended-commonjs"] = [
317
319
  jestConfig,
318
320
  configs["markdown/recommended"],
319
321
  configs["stylistic/recommended"],
322
+ configs["package-json/recommended"],
320
323
  ];
321
324
 
322
325
  configs["recommended-dirty"] = [
@@ -328,6 +331,7 @@ configs["recommended-dirty"] = [
328
331
  jestConfig,
329
332
  configs["markdown/recommended"],
330
333
  configs["stylistic/recommended"],
334
+ configs["package-json/recommended"],
331
335
  ];
332
336
 
333
337
  export { default } from "./configs/index.js";
package/ignore-paths.js CHANGED
@@ -1,9 +1,69 @@
1
1
  export default [
2
- "types/**/*",
2
+ // OS
3
+ ".DS_Store",
4
+ "Thumbs.db",
5
+
6
+ // IDE
7
+ ".idea",
8
+ "*.iml",
9
+ ".vscode",
10
+ ".vscode-test",
11
+ "*.sublime-project",
12
+ "*.sublime-workspace",
13
+
14
+ // Logs
15
+ "logs/**/*",
16
+ "*.log",
17
+ "npm-debug.log*",
18
+ "yarn-debug.log*",
19
+ "yarn-error.log*",
20
+ "lerna-debug.log*",
21
+
22
+ // Diagnostic reports (https://nodejs.org/api/report.html)
23
+ "report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json",
24
+
25
+ // Runtime data
26
+ "pids",
27
+ "*.pid",
28
+ "*.seed",
29
+ "*.pid.lock",
30
+
31
+ // Directory for instrumented libs generated by jscoverage/JSCover
32
+ "lib-cov/**/*",
33
+
34
+ // Coverage directory used by tools like istanbul
35
+ "coverage/**/*",
36
+ "*.lcov",
37
+
38
+ // nyc test coverage
39
+ ".nyc_output",
40
+
41
+ // Compiled binary addons (https://nodejs.org/api/addons.html)
42
+ "build/Release/**/*",
43
+
44
+ // Dependencies
3
45
  "node_modules/**/*",
46
+
47
+ // Optional REPL history
48
+ ".node_repl_history",
49
+
50
+ // Generated code
4
51
  "dist/**/*",
5
- "coverage/**/*",
52
+
53
+ // Test
6
54
  "test/fixtures/**/*",
7
55
  "test/outputs/**/*",
8
- "build/Release/**/*",
56
+
57
+ // Generated types
58
+ "types/**/*",
59
+
60
+ // Reports
61
+ "reports/**/*",
62
+
63
+ // Caches
64
+ ".cache/**/*",
65
+ ".eslintcache",
66
+ ".stylelintcache",
67
+ ".cspellcache",
68
+ "*.tsbuildinfo",
9
69
  ];
package/package.json CHANGED
@@ -1,13 +1,30 @@
1
1
  {
2
2
  "name": "eslint-config-webpack",
3
- "version": "4.1.4",
4
- "author": "Joshua Wiens (https://twitter.com/@d3viant0ne)",
5
- "license": "MIT",
3
+ "version": "4.2.1",
6
4
  "description": "Provides Webpack's eslint rules as an extensible shared config",
5
+ "keywords": [
6
+ "eslint",
7
+ "eslintconfig",
8
+ "config",
9
+ "webpack",
10
+ "javascript",
11
+ "typescript"
12
+ ],
13
+ "homepage": "https://github.com/webpack/eslint-config-webpack#readme",
14
+ "bugs": {
15
+ "url": "https://github.com/webpack/eslint-config-webpack/issues"
16
+ },
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/webpack/eslint-config-webpack.git"
20
+ },
21
+ "license": "MIT",
22
+ "author": "Joshua Wiens (https://twitter.com/@d3viant0ne)",
7
23
  "type": "module",
8
24
  "main": "index.js",
9
25
  "files": [
10
26
  "index.js",
27
+ "plugins",
11
28
  "prettier-config.js",
12
29
  "prettier-config-es5.js",
13
30
  "configs.js",
@@ -16,11 +33,14 @@
16
33
  ],
17
34
  "scripts": {
18
35
  "lint": "npm run lint:code",
19
- "lint:code": "node node_modules/eslint/bin/eslint.js --cache .",
36
+ "lint:code": "eslint --cache .",
20
37
  "release": "standard-version"
21
38
  },
22
39
  "dependencies": {
23
- "semver": "^7.7.2"
40
+ "detect-indent": "^7.0.1",
41
+ "jsonc-eslint-parser": "^2.4.0",
42
+ "semver": "^7.7.2",
43
+ "sort-package-json": "^3.3.1"
24
44
  },
25
45
  "devDependencies": {
26
46
  "@eslint/js": "^9.29.0",
@@ -80,20 +100,5 @@
80
100
  },
81
101
  "engines": {
82
102
  "node": ">= 18.20.0"
83
- },
84
- "repository": {
85
- "type": "git",
86
- "url": "git+https://github.com/webpack/eslint-config-webpack.git"
87
- },
88
- "keywords": [
89
- "eslint",
90
- "eslintconfig",
91
- "config",
92
- "webpack",
93
- "javascirpt"
94
- ],
95
- "bugs": {
96
- "url": "https://github.com/webpack/eslint-config-webpack/issues"
97
- },
98
- "homepage": "https://github.com/webpack/eslint-config-webpack#readme"
103
+ }
99
104
  }
@@ -0,0 +1,48 @@
1
+ import { createRequire } from "node:module";
2
+ import * as parserJsonc from "jsonc-eslint-parser";
3
+ import { rule as orderProperties } from "./rules/order-properties.js";
4
+
5
+ const require = createRequire(import.meta.url);
6
+
7
+ const { version } = require("../../package.json");
8
+
9
+ const rules = {
10
+ "order-properties": orderProperties,
11
+ };
12
+
13
+ const recommendedRules = {
14
+ ...Object.fromEntries(
15
+ Object.entries(rules)
16
+ .filter(([, rule]) => rule.meta.docs?.recommended)
17
+ .map(([name]) => [`package-json/${name}`, "error"]),
18
+ ),
19
+ };
20
+
21
+ const configs = {
22
+ recommended: {
23
+ name: "package-json/recommended",
24
+ files: ["**/package.json"],
25
+ languageOptions: {
26
+ parser: parserJsonc,
27
+ },
28
+ plugins: {
29
+ get "package-json"() {
30
+ // eslint-disable-next-line no-use-before-define
31
+ return plugin;
32
+ },
33
+ },
34
+ rules: recommendedRules,
35
+ },
36
+ };
37
+
38
+ const plugin = {
39
+ configs,
40
+ meta: {
41
+ version,
42
+ },
43
+ rules,
44
+ };
45
+
46
+ export { configs, rules };
47
+
48
+ export default plugin;
@@ -0,0 +1,187 @@
1
+ import detectIndent from "detect-indent";
2
+ import { sortOrder } from "sort-package-json";
3
+
4
+ /**
5
+ * @param {string} string string
6
+ * @returns {"\r\n" | "\n"} detected newline
7
+ */
8
+ function detectNewline(string) {
9
+ if (typeof string !== "string") {
10
+ throw new TypeError("Expected a string");
11
+ }
12
+
13
+ const newlines = string.match(/(?:\r?\n)/g) || [];
14
+
15
+ if (newlines.length === 0) {
16
+ return;
17
+ }
18
+
19
+ const crlf = newlines.filter((newline) => newline === "\r\n").length;
20
+ const lf = newlines.length - crlf;
21
+
22
+ return crlf > lf ? "\r\n" : "\n";
23
+ }
24
+
25
+ /**
26
+ * @param {string} string string
27
+ * @returns {string} result
28
+ */
29
+ function detectNewlineGraceful(string) {
30
+ return detectNewline(string) || "\n";
31
+ }
32
+
33
+ // eslint-disable-next-line jsdoc/no-restricted-syntax
34
+ /** @typedef {Record<string, any>} ObjectToSort */
35
+
36
+ /**
37
+ * @param {ObjectToSort} object object to sort
38
+ * @param {(a: number, b: number) => number} sortWith function to sort
39
+ * @returns {ObjectToSort} object with sorted properties
40
+ */
41
+ function sortObjectKeys(object, sortWith) {
42
+ let keys;
43
+ let sortFn;
44
+
45
+ if (typeof sortWith === "function") {
46
+ sortFn = sortWith;
47
+ } else {
48
+ keys = sortWith;
49
+ }
50
+
51
+ const objectKeys = Object.keys(object);
52
+
53
+ return (keys || [...objectKeys.sort(sortFn)]).reduce((total, key) => {
54
+ if (Object.hasOwn(object, key)) {
55
+ total[key] = object[key];
56
+ }
57
+
58
+ return total;
59
+ }, Object.create(null));
60
+ }
61
+
62
+ /**
63
+ * @param {string} filePath file path
64
+ * @returns {boolean} result
65
+ */
66
+ export const isPackageJson = (filePath) =>
67
+ /(?:^|[/\\])package.json$/.test(filePath);
68
+
69
+ // eslint-disable-next-line jsdoc/no-restricted-syntax
70
+ /**
71
+ * @typedef {import("eslint").AST.Program} PackageJsonAst
72
+ * @property {[any]} body body
73
+ */
74
+
75
+ /**
76
+ * @typedef {import("eslint").SourceCode} PackageJsonSourceCode
77
+ * @property {PackageJsonAst} ast ast
78
+ */
79
+
80
+ /**
81
+ * @template {unknown[]} [Options=unknown[]]
82
+ * @typedef {import("eslint").RuleContext} PackageJsonRuleContext
83
+ * @property {Options} options options
84
+ * @property {PackageJsonSourceCode} sourceCode source code
85
+ */
86
+
87
+ /**
88
+ * @template {unknown[]} Options
89
+ * @typedef {object} PackageJsonRuleModule
90
+ * @property {import("eslint").Rule.RuleMetaData} meta meta
91
+ * @property {(context: PackageJsonRuleContext<Options>) => import("eslint").RuleListener} create function to create
92
+ */
93
+
94
+ /**
95
+ * @type {import("eslint").Rule} rule
96
+ */
97
+ export const rule = {
98
+ create(context) {
99
+ if (!isPackageJson(context.filename)) {
100
+ return {};
101
+ }
102
+
103
+ return {
104
+ "Program:exit"() {
105
+ const { ast, text } = context.sourceCode;
106
+
107
+ const options = {
108
+ order: "sort-package-json",
109
+ ...context.options[0],
110
+ };
111
+
112
+ const requiredOrder =
113
+ options.order === "sort-package-json" ? sortOrder : options.order;
114
+
115
+ const json = JSON.parse(text);
116
+ const orderedSource = sortObjectKeys(json, [
117
+ ...requiredOrder,
118
+ ...Object.keys(json),
119
+ ]);
120
+ const orderedKeys = Object.keys(orderedSource);
121
+
122
+ const { properties } = ast.body[0].expression;
123
+
124
+ for (let i = 0; i < properties.length; i += 1) {
125
+ const property = properties[i].key;
126
+ const { value } = property;
127
+
128
+ if (value === orderedKeys[i]) {
129
+ continue;
130
+ }
131
+
132
+ context.report({
133
+ data: {
134
+ property: value,
135
+ },
136
+ fix(fixer) {
137
+ const { indent, type } = detectIndent(text);
138
+ const endCharacters = text.endsWith("\n") ? "\n" : "";
139
+ const newline = detectNewlineGraceful(text);
140
+ let result =
141
+ JSON.stringify(
142
+ orderedSource,
143
+ null,
144
+ type === "tab" ? "\t" : indent,
145
+ ) + endCharacters;
146
+ if (newline === "\r\n") {
147
+ result = result.replaceAll("\n", newline);
148
+ }
149
+
150
+ return fixer.replaceText(context.sourceCode.ast, result);
151
+ },
152
+ loc: properties[i].loc,
153
+ messageId: "incorrectOrder",
154
+ });
155
+ }
156
+ },
157
+ };
158
+ },
159
+ meta: {
160
+ docs: {
161
+ category: "Best Practices",
162
+ description: "Package properties must be declared in standard order",
163
+ recommended: true,
164
+ },
165
+ fixable: "code",
166
+ messages: {
167
+ incorrectOrder:
168
+ 'Package top-level property "{{property}}" is not ordered in the npm standard way. Run the ESLint auto-fixer to correct.',
169
+ },
170
+ schema: [
171
+ {
172
+ properties: {
173
+ order: {
174
+ anyOf: [
175
+ {
176
+ enum: ["sort-package-json"],
177
+ type: ["string"],
178
+ },
179
+ ],
180
+ },
181
+ },
182
+ type: "object",
183
+ },
184
+ ],
185
+ type: "layout",
186
+ },
187
+ };