eslint 7.11.0 → 7.14.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 +54 -0
- package/README.md +6 -5
- package/bin/eslint.js +1 -1
- package/lib/cli-engine/cli-engine.js +26 -7
- package/lib/cli-engine/file-enumerator.js +12 -3
- package/lib/linter/report-translator.js +13 -9
- package/lib/linter/timing.js +23 -2
- package/lib/rules/constructor-super.js +11 -0
- package/lib/rules/index.js +1 -0
- package/lib/rules/no-constant-condition.js +42 -20
- package/lib/rules/no-irregular-whitespace.js +7 -9
- package/lib/rules/no-nonoctal-decimal-escape.js +147 -0
- package/lib/rules/no-prototype-builtins.js +4 -4
- package/lib/rules/no-script-url.js +21 -7
- package/lib/rules/no-useless-constructor.js +8 -0
- package/lib/rules/prefer-destructuring.js +19 -1
- package/lib/rules/prefer-template.js +14 -22
- package/lib/rules/quotes.js +5 -2
- package/lib/rules/space-before-blocks.js +34 -9
- package/lib/rules/utils/ast-utils.js +22 -7
- package/lib/rules/yoda.js +33 -23
- package/package.json +2 -2
- package/lib/cli-engine/cascading-config-array-factory.js +0 -502
- package/lib/cli-engine/config-array/config-array.js +0 -536
- package/lib/cli-engine/config-array/config-dependency.js +0 -128
- package/lib/cli-engine/config-array/extracted-config.js +0 -158
- package/lib/cli-engine/config-array/ignore-pattern.js +0 -249
- package/lib/cli-engine/config-array/index.js +0 -32
- package/lib/cli-engine/config-array/override-tester.js +0 -235
- package/lib/cli-engine/config-array-factory.js +0 -1092
@@ -1,158 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* STOP!!! DO NOT MODIFY.
|
3
|
-
*
|
4
|
-
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
-
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
-
* unchanged in order for this work to proceed.
|
7
|
-
*
|
8
|
-
* If you think you need to change this file, please contact @nzakas first.
|
9
|
-
*
|
10
|
-
* Thanks in advance for your cooperation.
|
11
|
-
*/
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @fileoverview `ExtractedConfig` class.
|
15
|
-
*
|
16
|
-
* `ExtractedConfig` class expresses a final configuration for a specific file.
|
17
|
-
*
|
18
|
-
* It provides one method.
|
19
|
-
*
|
20
|
-
* - `toCompatibleObjectAsConfigFileContent()`
|
21
|
-
* Convert this configuration to the compatible object as the content of
|
22
|
-
* config files. It converts the loaded parser and plugins to strings.
|
23
|
-
* `CLIEngine#getConfigForFile(filePath)` method uses this method.
|
24
|
-
*
|
25
|
-
* `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
|
26
|
-
*
|
27
|
-
* @author Toru Nagashima <https://github.com/mysticatea>
|
28
|
-
*/
|
29
|
-
"use strict";
|
30
|
-
|
31
|
-
const { IgnorePattern } = require("./ignore-pattern");
|
32
|
-
|
33
|
-
// For VSCode intellisense
|
34
|
-
/** @typedef {import("../../shared/types").ConfigData} ConfigData */
|
35
|
-
/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
|
36
|
-
/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
|
37
|
-
/** @typedef {import("./config-dependency").DependentParser} DependentParser */
|
38
|
-
/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
|
39
|
-
|
40
|
-
/**
|
41
|
-
* Check if `xs` starts with `ys`.
|
42
|
-
* @template T
|
43
|
-
* @param {T[]} xs The array to check.
|
44
|
-
* @param {T[]} ys The array that may be the first part of `xs`.
|
45
|
-
* @returns {boolean} `true` if `xs` starts with `ys`.
|
46
|
-
*/
|
47
|
-
function startsWith(xs, ys) {
|
48
|
-
return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
|
49
|
-
}
|
50
|
-
|
51
|
-
/**
|
52
|
-
* The class for extracted config data.
|
53
|
-
*/
|
54
|
-
class ExtractedConfig {
|
55
|
-
constructor() {
|
56
|
-
|
57
|
-
/**
|
58
|
-
* The config name what `noInlineConfig` setting came from.
|
59
|
-
* @type {string}
|
60
|
-
*/
|
61
|
-
this.configNameOfNoInlineConfig = "";
|
62
|
-
|
63
|
-
/**
|
64
|
-
* Environments.
|
65
|
-
* @type {Record<string, boolean>}
|
66
|
-
*/
|
67
|
-
this.env = {};
|
68
|
-
|
69
|
-
/**
|
70
|
-
* Global variables.
|
71
|
-
* @type {Record<string, GlobalConf>}
|
72
|
-
*/
|
73
|
-
this.globals = {};
|
74
|
-
|
75
|
-
/**
|
76
|
-
* The glob patterns that ignore to lint.
|
77
|
-
* @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
|
78
|
-
*/
|
79
|
-
this.ignores = void 0;
|
80
|
-
|
81
|
-
/**
|
82
|
-
* The flag that disables directive comments.
|
83
|
-
* @type {boolean|undefined}
|
84
|
-
*/
|
85
|
-
this.noInlineConfig = void 0;
|
86
|
-
|
87
|
-
/**
|
88
|
-
* Parser definition.
|
89
|
-
* @type {DependentParser|null}
|
90
|
-
*/
|
91
|
-
this.parser = null;
|
92
|
-
|
93
|
-
/**
|
94
|
-
* Options for the parser.
|
95
|
-
* @type {Object}
|
96
|
-
*/
|
97
|
-
this.parserOptions = {};
|
98
|
-
|
99
|
-
/**
|
100
|
-
* Plugin definitions.
|
101
|
-
* @type {Record<string, DependentPlugin>}
|
102
|
-
*/
|
103
|
-
this.plugins = {};
|
104
|
-
|
105
|
-
/**
|
106
|
-
* Processor ID.
|
107
|
-
* @type {string|null}
|
108
|
-
*/
|
109
|
-
this.processor = null;
|
110
|
-
|
111
|
-
/**
|
112
|
-
* The flag that reports unused `eslint-disable` directive comments.
|
113
|
-
* @type {boolean|undefined}
|
114
|
-
*/
|
115
|
-
this.reportUnusedDisableDirectives = void 0;
|
116
|
-
|
117
|
-
/**
|
118
|
-
* Rule settings.
|
119
|
-
* @type {Record<string, [SeverityConf, ...any[]]>}
|
120
|
-
*/
|
121
|
-
this.rules = {};
|
122
|
-
|
123
|
-
/**
|
124
|
-
* Shared settings.
|
125
|
-
* @type {Object}
|
126
|
-
*/
|
127
|
-
this.settings = {};
|
128
|
-
}
|
129
|
-
|
130
|
-
/**
|
131
|
-
* Convert this config to the compatible object as a config file content.
|
132
|
-
* @returns {ConfigData} The converted object.
|
133
|
-
*/
|
134
|
-
toCompatibleObjectAsConfigFileContent() {
|
135
|
-
const {
|
136
|
-
/* eslint-disable no-unused-vars */
|
137
|
-
configNameOfNoInlineConfig: _ignore1,
|
138
|
-
processor: _ignore2,
|
139
|
-
/* eslint-enable no-unused-vars */
|
140
|
-
ignores,
|
141
|
-
...config
|
142
|
-
} = this;
|
143
|
-
|
144
|
-
config.parser = config.parser && config.parser.filePath;
|
145
|
-
config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
|
146
|
-
config.ignorePatterns = ignores ? ignores.patterns : [];
|
147
|
-
|
148
|
-
// Strip the default patterns from `ignorePatterns`.
|
149
|
-
if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
|
150
|
-
config.ignorePatterns =
|
151
|
-
config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
|
152
|
-
}
|
153
|
-
|
154
|
-
return config;
|
155
|
-
}
|
156
|
-
}
|
157
|
-
|
158
|
-
module.exports = { ExtractedConfig };
|
@@ -1,249 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* STOP!!! DO NOT MODIFY.
|
3
|
-
*
|
4
|
-
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
-
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
-
* unchanged in order for this work to proceed.
|
7
|
-
*
|
8
|
-
* If you think you need to change this file, please contact @nzakas first.
|
9
|
-
*
|
10
|
-
* Thanks in advance for your cooperation.
|
11
|
-
*/
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @fileoverview `IgnorePattern` class.
|
15
|
-
*
|
16
|
-
* `IgnorePattern` class has the set of glob patterns and the base path.
|
17
|
-
*
|
18
|
-
* It provides two static methods.
|
19
|
-
*
|
20
|
-
* - `IgnorePattern.createDefaultIgnore(cwd)`
|
21
|
-
* Create the default predicate function.
|
22
|
-
* - `IgnorePattern.createIgnore(ignorePatterns)`
|
23
|
-
* Create the predicate function from multiple `IgnorePattern` objects.
|
24
|
-
*
|
25
|
-
* It provides two properties and a method.
|
26
|
-
*
|
27
|
-
* - `patterns`
|
28
|
-
* The glob patterns that ignore to lint.
|
29
|
-
* - `basePath`
|
30
|
-
* The base path of the glob patterns. If absolute paths existed in the
|
31
|
-
* glob patterns, those are handled as relative paths to the base path.
|
32
|
-
* - `getPatternsRelativeTo(basePath)`
|
33
|
-
* Get `patterns` as modified for a given base path. It modifies the
|
34
|
-
* absolute paths in the patterns as prepending the difference of two base
|
35
|
-
* paths.
|
36
|
-
*
|
37
|
-
* `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
|
38
|
-
* `ignorePatterns` properties.
|
39
|
-
*
|
40
|
-
* @author Toru Nagashima <https://github.com/mysticatea>
|
41
|
-
*/
|
42
|
-
"use strict";
|
43
|
-
|
44
|
-
//------------------------------------------------------------------------------
|
45
|
-
// Requirements
|
46
|
-
//------------------------------------------------------------------------------
|
47
|
-
|
48
|
-
const assert = require("assert");
|
49
|
-
const path = require("path");
|
50
|
-
const ignore = require("ignore");
|
51
|
-
const debug = require("debug")("eslint:ignore-pattern");
|
52
|
-
|
53
|
-
/** @typedef {ReturnType<import("ignore").default>} Ignore */
|
54
|
-
|
55
|
-
//------------------------------------------------------------------------------
|
56
|
-
// Helpers
|
57
|
-
//------------------------------------------------------------------------------
|
58
|
-
|
59
|
-
/**
|
60
|
-
* Get the path to the common ancestor directory of given paths.
|
61
|
-
* @param {string[]} sourcePaths The paths to calculate the common ancestor.
|
62
|
-
* @returns {string} The path to the common ancestor directory.
|
63
|
-
*/
|
64
|
-
function getCommonAncestorPath(sourcePaths) {
|
65
|
-
let result = sourcePaths[0];
|
66
|
-
|
67
|
-
for (let i = 1; i < sourcePaths.length; ++i) {
|
68
|
-
const a = result;
|
69
|
-
const b = sourcePaths[i];
|
70
|
-
|
71
|
-
// Set the shorter one (it's the common ancestor if one includes the other).
|
72
|
-
result = a.length < b.length ? a : b;
|
73
|
-
|
74
|
-
// Set the common ancestor.
|
75
|
-
for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
|
76
|
-
if (a[j] !== b[j]) {
|
77
|
-
result = a.slice(0, lastSepPos);
|
78
|
-
break;
|
79
|
-
}
|
80
|
-
if (a[j] === path.sep) {
|
81
|
-
lastSepPos = j;
|
82
|
-
}
|
83
|
-
}
|
84
|
-
}
|
85
|
-
|
86
|
-
let resolvedResult = result || path.sep;
|
87
|
-
|
88
|
-
// if Windows common ancestor is root of drive must have trailing slash to be absolute.
|
89
|
-
if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
|
90
|
-
resolvedResult += path.sep;
|
91
|
-
}
|
92
|
-
return resolvedResult;
|
93
|
-
}
|
94
|
-
|
95
|
-
/**
|
96
|
-
* Make relative path.
|
97
|
-
* @param {string} from The source path to get relative path.
|
98
|
-
* @param {string} to The destination path to get relative path.
|
99
|
-
* @returns {string} The relative path.
|
100
|
-
*/
|
101
|
-
function relative(from, to) {
|
102
|
-
const relPath = path.relative(from, to);
|
103
|
-
|
104
|
-
if (path.sep === "/") {
|
105
|
-
return relPath;
|
106
|
-
}
|
107
|
-
return relPath.split(path.sep).join("/");
|
108
|
-
}
|
109
|
-
|
110
|
-
/**
|
111
|
-
* Get the trailing slash if existed.
|
112
|
-
* @param {string} filePath The path to check.
|
113
|
-
* @returns {string} The trailing slash if existed.
|
114
|
-
*/
|
115
|
-
function dirSuffix(filePath) {
|
116
|
-
const isDir = (
|
117
|
-
filePath.endsWith(path.sep) ||
|
118
|
-
(process.platform === "win32" && filePath.endsWith("/"))
|
119
|
-
);
|
120
|
-
|
121
|
-
return isDir ? "/" : "";
|
122
|
-
}
|
123
|
-
|
124
|
-
const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
|
125
|
-
const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
|
126
|
-
|
127
|
-
//------------------------------------------------------------------------------
|
128
|
-
// Public
|
129
|
-
//------------------------------------------------------------------------------
|
130
|
-
|
131
|
-
class IgnorePattern {
|
132
|
-
|
133
|
-
/**
|
134
|
-
* The default patterns.
|
135
|
-
* @type {string[]}
|
136
|
-
*/
|
137
|
-
static get DefaultPatterns() {
|
138
|
-
return DefaultPatterns;
|
139
|
-
}
|
140
|
-
|
141
|
-
/**
|
142
|
-
* Create the default predicate function.
|
143
|
-
* @param {string} cwd The current working directory.
|
144
|
-
* @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
145
|
-
* The preficate function.
|
146
|
-
* The first argument is an absolute path that is checked.
|
147
|
-
* The second argument is the flag to not ignore dotfiles.
|
148
|
-
* If the predicate function returned `true`, it means the path should be ignored.
|
149
|
-
*/
|
150
|
-
static createDefaultIgnore(cwd) {
|
151
|
-
return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
|
152
|
-
}
|
153
|
-
|
154
|
-
/**
|
155
|
-
* Create the predicate function from multiple `IgnorePattern` objects.
|
156
|
-
* @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
|
157
|
-
* @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
|
158
|
-
* The preficate function.
|
159
|
-
* The first argument is an absolute path that is checked.
|
160
|
-
* The second argument is the flag to not ignore dotfiles.
|
161
|
-
* If the predicate function returned `true`, it means the path should be ignored.
|
162
|
-
*/
|
163
|
-
static createIgnore(ignorePatterns) {
|
164
|
-
debug("Create with: %o", ignorePatterns);
|
165
|
-
|
166
|
-
const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
|
167
|
-
const patterns = [].concat(
|
168
|
-
...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
|
169
|
-
);
|
170
|
-
const ig = ignore().add([...DotPatterns, ...patterns]);
|
171
|
-
const dotIg = ignore().add(patterns);
|
172
|
-
|
173
|
-
debug(" processed: %o", { basePath, patterns });
|
174
|
-
|
175
|
-
return Object.assign(
|
176
|
-
(filePath, dot = false) => {
|
177
|
-
assert(path.isAbsolute(filePath), "'filePath' should be an absolute path.");
|
178
|
-
const relPathRaw = relative(basePath, filePath);
|
179
|
-
const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
|
180
|
-
const adoptedIg = dot ? dotIg : ig;
|
181
|
-
const result = relPath !== "" && adoptedIg.ignores(relPath);
|
182
|
-
|
183
|
-
debug("Check", { filePath, dot, relativePath: relPath, result });
|
184
|
-
return result;
|
185
|
-
},
|
186
|
-
{ basePath, patterns }
|
187
|
-
);
|
188
|
-
}
|
189
|
-
|
190
|
-
/**
|
191
|
-
* Initialize a new `IgnorePattern` instance.
|
192
|
-
* @param {string[]} patterns The glob patterns that ignore to lint.
|
193
|
-
* @param {string} basePath The base path of `patterns`.
|
194
|
-
*/
|
195
|
-
constructor(patterns, basePath) {
|
196
|
-
assert(path.isAbsolute(basePath), "'basePath' should be an absolute path.");
|
197
|
-
|
198
|
-
/**
|
199
|
-
* The glob patterns that ignore to lint.
|
200
|
-
* @type {string[]}
|
201
|
-
*/
|
202
|
-
this.patterns = patterns;
|
203
|
-
|
204
|
-
/**
|
205
|
-
* The base path of `patterns`.
|
206
|
-
* @type {string}
|
207
|
-
*/
|
208
|
-
this.basePath = basePath;
|
209
|
-
|
210
|
-
/**
|
211
|
-
* If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
|
212
|
-
*
|
213
|
-
* It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
|
214
|
-
* It's `false` as-is for `ignorePatterns` property in config files.
|
215
|
-
* @type {boolean}
|
216
|
-
*/
|
217
|
-
this.loose = false;
|
218
|
-
}
|
219
|
-
|
220
|
-
/**
|
221
|
-
* Get `patterns` as modified for a given base path. It modifies the
|
222
|
-
* absolute paths in the patterns as prepending the difference of two base
|
223
|
-
* paths.
|
224
|
-
* @param {string} newBasePath The base path.
|
225
|
-
* @returns {string[]} Modifired patterns.
|
226
|
-
*/
|
227
|
-
getPatternsRelativeTo(newBasePath) {
|
228
|
-
assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
|
229
|
-
const { basePath, loose, patterns } = this;
|
230
|
-
|
231
|
-
if (newBasePath === basePath) {
|
232
|
-
return patterns;
|
233
|
-
}
|
234
|
-
const prefix = `/${relative(newBasePath, basePath)}`;
|
235
|
-
|
236
|
-
return patterns.map(pattern => {
|
237
|
-
const negative = pattern.startsWith("!");
|
238
|
-
const head = negative ? "!" : "";
|
239
|
-
const body = negative ? pattern.slice(1) : pattern;
|
240
|
-
|
241
|
-
if (body.startsWith("/") || body.startsWith("../")) {
|
242
|
-
return `${head}${prefix}${body}`;
|
243
|
-
}
|
244
|
-
return loose ? pattern : `${head}${prefix}/**/${body}`;
|
245
|
-
});
|
246
|
-
}
|
247
|
-
}
|
248
|
-
|
249
|
-
module.exports = { IgnorePattern };
|
@@ -1,32 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* STOP!!! DO NOT MODIFY.
|
3
|
-
*
|
4
|
-
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
-
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
-
* unchanged in order for this work to proceed.
|
7
|
-
*
|
8
|
-
* If you think you need to change this file, please contact @nzakas first.
|
9
|
-
*
|
10
|
-
* Thanks in advance for your cooperation.
|
11
|
-
*/
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @fileoverview `ConfigArray` class.
|
15
|
-
* @author Toru Nagashima <https://github.com/mysticatea>
|
16
|
-
*/
|
17
|
-
"use strict";
|
18
|
-
|
19
|
-
const { ConfigArray, getUsedExtractedConfigs } = require("./config-array");
|
20
|
-
const { ConfigDependency } = require("./config-dependency");
|
21
|
-
const { ExtractedConfig } = require("./extracted-config");
|
22
|
-
const { IgnorePattern } = require("./ignore-pattern");
|
23
|
-
const { OverrideTester } = require("./override-tester");
|
24
|
-
|
25
|
-
module.exports = {
|
26
|
-
ConfigArray,
|
27
|
-
ConfigDependency,
|
28
|
-
ExtractedConfig,
|
29
|
-
IgnorePattern,
|
30
|
-
OverrideTester,
|
31
|
-
getUsedExtractedConfigs
|
32
|
-
};
|
@@ -1,235 +0,0 @@
|
|
1
|
-
/*
|
2
|
-
* STOP!!! DO NOT MODIFY.
|
3
|
-
*
|
4
|
-
* This file is part of the ongoing work to move the eslintrc-style config
|
5
|
-
* system into the @eslint/eslintrc package. This file needs to remain
|
6
|
-
* unchanged in order for this work to proceed.
|
7
|
-
*
|
8
|
-
* If you think you need to change this file, please contact @nzakas first.
|
9
|
-
*
|
10
|
-
* Thanks in advance for your cooperation.
|
11
|
-
*/
|
12
|
-
|
13
|
-
/**
|
14
|
-
* @fileoverview `OverrideTester` class.
|
15
|
-
*
|
16
|
-
* `OverrideTester` class handles `files` property and `excludedFiles` property
|
17
|
-
* of `overrides` config.
|
18
|
-
*
|
19
|
-
* It provides one method.
|
20
|
-
*
|
21
|
-
* - `test(filePath)`
|
22
|
-
* Test if a file path matches the pair of `files` property and
|
23
|
-
* `excludedFiles` property. The `filePath` argument must be an absolute
|
24
|
-
* path.
|
25
|
-
*
|
26
|
-
* `ConfigArrayFactory` creates `OverrideTester` objects when it processes
|
27
|
-
* `overrides` properties.
|
28
|
-
*
|
29
|
-
* @author Toru Nagashima <https://github.com/mysticatea>
|
30
|
-
*/
|
31
|
-
"use strict";
|
32
|
-
|
33
|
-
const assert = require("assert");
|
34
|
-
const path = require("path");
|
35
|
-
const util = require("util");
|
36
|
-
const { Minimatch } = require("minimatch");
|
37
|
-
const minimatchOpts = { dot: true, matchBase: true };
|
38
|
-
|
39
|
-
/**
|
40
|
-
* @typedef {Object} Pattern
|
41
|
-
* @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
|
42
|
-
* @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
|
43
|
-
*/
|
44
|
-
|
45
|
-
/**
|
46
|
-
* Normalize a given pattern to an array.
|
47
|
-
* @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
|
48
|
-
* @returns {string[]|null} Normalized patterns.
|
49
|
-
* @private
|
50
|
-
*/
|
51
|
-
function normalizePatterns(patterns) {
|
52
|
-
if (Array.isArray(patterns)) {
|
53
|
-
return patterns.filter(Boolean);
|
54
|
-
}
|
55
|
-
if (typeof patterns === "string" && patterns) {
|
56
|
-
return [patterns];
|
57
|
-
}
|
58
|
-
return [];
|
59
|
-
}
|
60
|
-
|
61
|
-
/**
|
62
|
-
* Create the matchers of given patterns.
|
63
|
-
* @param {string[]} patterns The patterns.
|
64
|
-
* @returns {InstanceType<Minimatch>[] | null} The matchers.
|
65
|
-
*/
|
66
|
-
function toMatcher(patterns) {
|
67
|
-
if (patterns.length === 0) {
|
68
|
-
return null;
|
69
|
-
}
|
70
|
-
return patterns.map(pattern => {
|
71
|
-
if (/^\.[/\\]/u.test(pattern)) {
|
72
|
-
return new Minimatch(
|
73
|
-
pattern.slice(2),
|
74
|
-
|
75
|
-
// `./*.js` should not match with `subdir/foo.js`
|
76
|
-
{ ...minimatchOpts, matchBase: false }
|
77
|
-
);
|
78
|
-
}
|
79
|
-
return new Minimatch(pattern, minimatchOpts);
|
80
|
-
});
|
81
|
-
}
|
82
|
-
|
83
|
-
/**
|
84
|
-
* Convert a given matcher to string.
|
85
|
-
* @param {Pattern} matchers The matchers.
|
86
|
-
* @returns {string} The string expression of the matcher.
|
87
|
-
*/
|
88
|
-
function patternToJson({ includes, excludes }) {
|
89
|
-
return {
|
90
|
-
includes: includes && includes.map(m => m.pattern),
|
91
|
-
excludes: excludes && excludes.map(m => m.pattern)
|
92
|
-
};
|
93
|
-
}
|
94
|
-
|
95
|
-
/**
|
96
|
-
* The class to test given paths are matched by the patterns.
|
97
|
-
*/
|
98
|
-
class OverrideTester {
|
99
|
-
|
100
|
-
/**
|
101
|
-
* Create a tester with given criteria.
|
102
|
-
* If there are no criteria, returns `null`.
|
103
|
-
* @param {string|string[]} files The glob patterns for included files.
|
104
|
-
* @param {string|string[]} excludedFiles The glob patterns for excluded files.
|
105
|
-
* @param {string} basePath The path to the base directory to test paths.
|
106
|
-
* @returns {OverrideTester|null} The created instance or `null`.
|
107
|
-
*/
|
108
|
-
static create(files, excludedFiles, basePath) {
|
109
|
-
const includePatterns = normalizePatterns(files);
|
110
|
-
const excludePatterns = normalizePatterns(excludedFiles);
|
111
|
-
let endsWithWildcard = false;
|
112
|
-
|
113
|
-
if (includePatterns.length === 0) {
|
114
|
-
return null;
|
115
|
-
}
|
116
|
-
|
117
|
-
// Rejects absolute paths or relative paths to parents.
|
118
|
-
for (const pattern of includePatterns) {
|
119
|
-
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
120
|
-
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
121
|
-
}
|
122
|
-
if (pattern.endsWith("*")) {
|
123
|
-
endsWithWildcard = true;
|
124
|
-
}
|
125
|
-
}
|
126
|
-
for (const pattern of excludePatterns) {
|
127
|
-
if (path.isAbsolute(pattern) || pattern.includes("..")) {
|
128
|
-
throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
|
129
|
-
}
|
130
|
-
}
|
131
|
-
|
132
|
-
const includes = toMatcher(includePatterns);
|
133
|
-
const excludes = toMatcher(excludePatterns);
|
134
|
-
|
135
|
-
return new OverrideTester(
|
136
|
-
[{ includes, excludes }],
|
137
|
-
basePath,
|
138
|
-
endsWithWildcard
|
139
|
-
);
|
140
|
-
}
|
141
|
-
|
142
|
-
/**
|
143
|
-
* Combine two testers by logical and.
|
144
|
-
* If either of the testers was `null`, returns the other tester.
|
145
|
-
* The `basePath` property of the two must be the same value.
|
146
|
-
* @param {OverrideTester|null} a A tester.
|
147
|
-
* @param {OverrideTester|null} b Another tester.
|
148
|
-
* @returns {OverrideTester|null} Combined tester.
|
149
|
-
*/
|
150
|
-
static and(a, b) {
|
151
|
-
if (!b) {
|
152
|
-
return a && new OverrideTester(
|
153
|
-
a.patterns,
|
154
|
-
a.basePath,
|
155
|
-
a.endsWithWildcard
|
156
|
-
);
|
157
|
-
}
|
158
|
-
if (!a) {
|
159
|
-
return new OverrideTester(
|
160
|
-
b.patterns,
|
161
|
-
b.basePath,
|
162
|
-
b.endsWithWildcard
|
163
|
-
);
|
164
|
-
}
|
165
|
-
|
166
|
-
assert.strictEqual(a.basePath, b.basePath);
|
167
|
-
return new OverrideTester(
|
168
|
-
a.patterns.concat(b.patterns),
|
169
|
-
a.basePath,
|
170
|
-
a.endsWithWildcard || b.endsWithWildcard
|
171
|
-
);
|
172
|
-
}
|
173
|
-
|
174
|
-
/**
|
175
|
-
* Initialize this instance.
|
176
|
-
* @param {Pattern[]} patterns The matchers.
|
177
|
-
* @param {string} basePath The base path.
|
178
|
-
* @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
|
179
|
-
*/
|
180
|
-
constructor(patterns, basePath, endsWithWildcard = false) {
|
181
|
-
|
182
|
-
/** @type {Pattern[]} */
|
183
|
-
this.patterns = patterns;
|
184
|
-
|
185
|
-
/** @type {string} */
|
186
|
-
this.basePath = basePath;
|
187
|
-
|
188
|
-
/** @type {boolean} */
|
189
|
-
this.endsWithWildcard = endsWithWildcard;
|
190
|
-
}
|
191
|
-
|
192
|
-
/**
|
193
|
-
* Test if a given path is matched or not.
|
194
|
-
* @param {string} filePath The absolute path to the target file.
|
195
|
-
* @returns {boolean} `true` if the path was matched.
|
196
|
-
*/
|
197
|
-
test(filePath) {
|
198
|
-
if (typeof filePath !== "string" || !path.isAbsolute(filePath)) {
|
199
|
-
throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
|
200
|
-
}
|
201
|
-
const relativePath = path.relative(this.basePath, filePath);
|
202
|
-
|
203
|
-
return this.patterns.every(({ includes, excludes }) => (
|
204
|
-
(!includes || includes.some(m => m.match(relativePath))) &&
|
205
|
-
(!excludes || !excludes.some(m => m.match(relativePath)))
|
206
|
-
));
|
207
|
-
}
|
208
|
-
|
209
|
-
// eslint-disable-next-line jsdoc/require-description
|
210
|
-
/**
|
211
|
-
* @returns {Object} a JSON compatible object.
|
212
|
-
*/
|
213
|
-
toJSON() {
|
214
|
-
if (this.patterns.length === 1) {
|
215
|
-
return {
|
216
|
-
...patternToJson(this.patterns[0]),
|
217
|
-
basePath: this.basePath
|
218
|
-
};
|
219
|
-
}
|
220
|
-
return {
|
221
|
-
AND: this.patterns.map(patternToJson),
|
222
|
-
basePath: this.basePath
|
223
|
-
};
|
224
|
-
}
|
225
|
-
|
226
|
-
// eslint-disable-next-line jsdoc/require-description
|
227
|
-
/**
|
228
|
-
* @returns {Object} an object to display by `console.log()`.
|
229
|
-
*/
|
230
|
-
[util.inspect.custom]() {
|
231
|
-
return this.toJSON();
|
232
|
-
}
|
233
|
-
}
|
234
|
-
|
235
|
-
module.exports = { OverrideTester };
|