eslint 8.19.0 → 8.22.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/README.md +3 -9
- package/lib/config/default-config.js +16 -7
- package/lib/config/flat-config-array.js +94 -14
- package/lib/config/flat-config-helpers.js +9 -1
- package/lib/eslint/eslint-helpers.js +618 -0
- package/lib/eslint/flat-eslint.js +1179 -0
- package/lib/eslint/index.js +3 -1
- package/lib/linter/linter.js +68 -4
- package/lib/rule-tester/flat-rule-tester.js +41 -38
- package/lib/rule-tester/rule-tester.js +42 -0
- package/lib/rules/comma-spacing.js +35 -41
- package/lib/rules/key-spacing.js +4 -1
- package/lib/rules/lines-around-comment.js +11 -4
- package/lib/rules/no-warning-comments.js +26 -40
- package/lib/rules/object-shorthand.js +15 -0
- package/lib/rules/sort-keys.js +43 -0
- package/lib/unsupported-api.js +4 -0
- package/package.json +15 -10
package/README.md
CHANGED
@@ -45,21 +45,15 @@ ESLint is a tool for identifying and reporting on patterns found in ECMAScript/J
|
|
45
45
|
|
46
46
|
Prerequisites: [Node.js](https://nodejs.org/) (`^12.22.0`, `^14.17.0`, or `>=16.0.0`) built with SSL support. (If you are using an official Node.js distribution, SSL is always built in.)
|
47
47
|
|
48
|
-
You can install ESLint using
|
48
|
+
You can install and configure ESLint using this command:
|
49
49
|
|
50
|
-
```
|
51
|
-
npm install eslint --save-dev
|
52
|
-
```
|
53
|
-
|
54
|
-
You should then set up a configuration file:
|
55
|
-
|
56
|
-
```sh
|
50
|
+
```shell
|
57
51
|
npm init @eslint/config
|
58
52
|
```
|
59
53
|
|
60
54
|
After that, you can run ESLint on any file or directory like this:
|
61
55
|
|
62
|
-
```
|
56
|
+
```shell
|
63
57
|
./node_modules/.bin/eslint yourfile.js
|
64
58
|
```
|
65
59
|
|
@@ -15,7 +15,6 @@ const Rules = require("../rules");
|
|
15
15
|
// Helpers
|
16
16
|
//-----------------------------------------------------------------------------
|
17
17
|
|
18
|
-
|
19
18
|
exports.defaultConfig = [
|
20
19
|
{
|
21
20
|
plugins: {
|
@@ -41,21 +40,31 @@ exports.defaultConfig = [
|
|
41
40
|
})
|
42
41
|
}
|
43
42
|
},
|
44
|
-
ignores: [
|
45
|
-
"**/node_modules/**",
|
46
|
-
".git/**"
|
47
|
-
],
|
48
43
|
languageOptions: {
|
49
|
-
ecmaVersion: "latest",
|
50
44
|
sourceType: "module",
|
45
|
+
ecmaVersion: "latest",
|
51
46
|
parser: "@/espree",
|
52
47
|
parserOptions: {}
|
53
48
|
}
|
54
49
|
},
|
50
|
+
|
51
|
+
// default ignores are listed here
|
52
|
+
{
|
53
|
+
ignores: [
|
54
|
+
"**/node_modules/**",
|
55
|
+
".git/**"
|
56
|
+
]
|
57
|
+
},
|
58
|
+
|
59
|
+
// intentionally empty config to ensure these files are globbed by default
|
60
|
+
{
|
61
|
+
files: ["**/*.js", "**/*.mjs"]
|
62
|
+
},
|
55
63
|
{
|
56
64
|
files: ["**/*.cjs"],
|
57
65
|
languageOptions: {
|
58
|
-
sourceType: "commonjs"
|
66
|
+
sourceType: "commonjs",
|
67
|
+
ecmaVersion: "latest"
|
59
68
|
}
|
60
69
|
}
|
61
70
|
];
|
@@ -36,6 +36,8 @@ function splitPluginIdentifier(identifier) {
|
|
36
36
|
};
|
37
37
|
}
|
38
38
|
|
39
|
+
const originalBaseConfig = Symbol("originalBaseConfig");
|
40
|
+
|
39
41
|
//-----------------------------------------------------------------------------
|
40
42
|
// Exports
|
41
43
|
//-----------------------------------------------------------------------------
|
@@ -48,10 +50,14 @@ class FlatConfigArray extends ConfigArray {
|
|
48
50
|
/**
|
49
51
|
* Creates a new instance.
|
50
52
|
* @param {*[]} configs An array of configuration information.
|
51
|
-
* @param {{basePath: string, baseConfig: FlatConfig}} options The options
|
53
|
+
* @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options
|
52
54
|
* to use for the config array instance.
|
53
55
|
*/
|
54
|
-
constructor(configs, {
|
56
|
+
constructor(configs, {
|
57
|
+
basePath,
|
58
|
+
shouldIgnore = true,
|
59
|
+
baseConfig = defaultConfig
|
60
|
+
} = {}) {
|
55
61
|
super(configs, {
|
56
62
|
basePath,
|
57
63
|
schema: flatConfigSchema
|
@@ -62,6 +68,22 @@ class FlatConfigArray extends ConfigArray {
|
|
62
68
|
} else {
|
63
69
|
this.unshift(baseConfig);
|
64
70
|
}
|
71
|
+
|
72
|
+
/**
|
73
|
+
* The baes config used to build the config array.
|
74
|
+
* @type {Array<FlatConfig>}
|
75
|
+
*/
|
76
|
+
this[originalBaseConfig] = baseConfig;
|
77
|
+
Object.defineProperty(this, originalBaseConfig, { writable: false });
|
78
|
+
|
79
|
+
/**
|
80
|
+
* Determines if `ignores` fields should be honored.
|
81
|
+
* If true, then all `ignores` fields are honored.
|
82
|
+
* if false, then only `ignores` fields in the baseConfig are honored.
|
83
|
+
* @type {boolean}
|
84
|
+
*/
|
85
|
+
this.shouldIgnore = shouldIgnore;
|
86
|
+
Object.defineProperty(this, "shouldIgnore", { writable: false });
|
65
87
|
}
|
66
88
|
|
67
89
|
/* eslint-disable class-methods-use-this -- Desired as instance method */
|
@@ -87,6 +109,23 @@ class FlatConfigArray extends ConfigArray {
|
|
87
109
|
return require("../../conf/eslint-all");
|
88
110
|
}
|
89
111
|
|
112
|
+
/*
|
113
|
+
* If `shouldIgnore` is false, we remove any ignore patterns specified
|
114
|
+
* in the config so long as it's not a default config and it doesn't
|
115
|
+
* have a `files` entry.
|
116
|
+
*/
|
117
|
+
if (
|
118
|
+
!this.shouldIgnore &&
|
119
|
+
!this[originalBaseConfig].includes(config) &&
|
120
|
+
config.ignores &&
|
121
|
+
!config.files
|
122
|
+
) {
|
123
|
+
/* eslint-disable-next-line no-unused-vars -- need to strip off other keys */
|
124
|
+
const { ignores, ...otherKeys } = config;
|
125
|
+
|
126
|
+
return otherKeys;
|
127
|
+
}
|
128
|
+
|
90
129
|
return config;
|
91
130
|
}
|
92
131
|
|
@@ -100,31 +139,72 @@ class FlatConfigArray extends ConfigArray {
|
|
100
139
|
[ConfigArraySymbol.finalizeConfig](config) {
|
101
140
|
|
102
141
|
const { plugins, languageOptions, processor } = config;
|
142
|
+
let parserName, processorName;
|
143
|
+
let invalidParser = false,
|
144
|
+
invalidProcessor = false;
|
103
145
|
|
104
146
|
// Check parser value
|
105
|
-
if (languageOptions && languageOptions.parser
|
106
|
-
|
147
|
+
if (languageOptions && languageOptions.parser) {
|
148
|
+
if (typeof languageOptions.parser === "string") {
|
149
|
+
const { pluginName, objectName: localParserName } = splitPluginIdentifier(languageOptions.parser);
|
107
150
|
|
108
|
-
|
109
|
-
|
110
|
-
|
151
|
+
parserName = languageOptions.parser;
|
152
|
+
|
153
|
+
if (!plugins || !plugins[pluginName] || !plugins[pluginName].parsers || !plugins[pluginName].parsers[localParserName]) {
|
154
|
+
throw new TypeError(`Key "parser": Could not find "${localParserName}" in plugin "${pluginName}".`);
|
155
|
+
}
|
111
156
|
|
112
|
-
|
157
|
+
languageOptions.parser = plugins[pluginName].parsers[localParserName];
|
158
|
+
} else {
|
159
|
+
invalidParser = true;
|
160
|
+
}
|
113
161
|
}
|
114
162
|
|
115
163
|
// Check processor value
|
116
|
-
if (processor
|
117
|
-
|
164
|
+
if (processor) {
|
165
|
+
if (typeof processor === "string") {
|
166
|
+
const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor);
|
118
167
|
|
119
|
-
|
120
|
-
|
121
|
-
|
168
|
+
processorName = processor;
|
169
|
+
|
170
|
+
if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) {
|
171
|
+
throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`);
|
172
|
+
}
|
122
173
|
|
123
|
-
|
174
|
+
config.processor = plugins[pluginName].processors[localProcessorName];
|
175
|
+
} else {
|
176
|
+
invalidProcessor = true;
|
177
|
+
}
|
124
178
|
}
|
125
179
|
|
126
180
|
ruleValidator.validate(config);
|
127
181
|
|
182
|
+
// apply special logic for serialization into JSON
|
183
|
+
/* eslint-disable object-shorthand -- shorthand would change "this" value */
|
184
|
+
Object.defineProperty(config, "toJSON", {
|
185
|
+
value: function() {
|
186
|
+
|
187
|
+
if (invalidParser) {
|
188
|
+
throw new Error("Caching is not supported when parser is an object.");
|
189
|
+
}
|
190
|
+
|
191
|
+
if (invalidProcessor) {
|
192
|
+
throw new Error("Caching is not supported when processor is an object.");
|
193
|
+
}
|
194
|
+
|
195
|
+
return {
|
196
|
+
...this,
|
197
|
+
plugins: Object.keys(plugins),
|
198
|
+
languageOptions: {
|
199
|
+
...languageOptions,
|
200
|
+
parser: parserName
|
201
|
+
},
|
202
|
+
processor: processorName
|
203
|
+
};
|
204
|
+
}
|
205
|
+
});
|
206
|
+
/* eslint-enable object-shorthand -- ok to enable now */
|
207
|
+
|
128
208
|
return config;
|
129
209
|
}
|
130
210
|
/* eslint-enable class-methods-use-this -- Desired as instance method */
|
@@ -20,7 +20,14 @@ function parseRuleId(ruleId) {
|
|
20
20
|
|
21
21
|
// distinguish between core rules and plugin rules
|
22
22
|
if (ruleId.includes("/")) {
|
23
|
-
|
23
|
+
|
24
|
+
// mimic scoped npm packages
|
25
|
+
if (ruleId.startsWith("@")) {
|
26
|
+
pluginName = ruleId.slice(0, ruleId.lastIndexOf("/"));
|
27
|
+
} else {
|
28
|
+
pluginName = ruleId.slice(0, ruleId.indexOf("/"));
|
29
|
+
}
|
30
|
+
|
24
31
|
ruleName = ruleId.slice(pluginName.length + 1);
|
25
32
|
} else {
|
26
33
|
pluginName = "@";
|
@@ -47,6 +54,7 @@ function getRuleFromConfig(ruleId, config) {
|
|
47
54
|
const plugin = config.plugins && config.plugins[pluginName];
|
48
55
|
let rule = plugin && plugin.rules && plugin.rules[ruleName];
|
49
56
|
|
57
|
+
|
50
58
|
// normalize function rules into objects
|
51
59
|
if (rule && typeof rule === "function") {
|
52
60
|
rule = {
|