gulp-eslint-new 1.7.0 → 1.7.2
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 +133 -58
- package/lib/eslint.d.ts +29 -25
- package/lib/gulp-eslint-new.d.ts +36 -29
- package/lib/gulp-eslint-new.js +106 -73
- package/lib/util.js +130 -94
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -4,14 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Make sure that you are using a version of Node.js [supported by ESLint 8](https://eslint.org/docs/user-guide/getting-started#prerequisites).
|
|
8
|
+
|
|
9
|
+
To install gulp-eslint-new, [use](https://docs.npmjs.com/cli/install) [npm](https://docs.npmjs.com/about-npm):
|
|
8
10
|
|
|
9
11
|
```console
|
|
10
12
|
npm i -D gulp-eslint-new
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
gulp-eslint-new will install the latest version of ESLint 8, unless another one is found.
|
|
14
|
-
To use a particular version of ESLint 8,
|
|
15
|
+
gulp-eslint-new will also install the latest version of ESLint 8, unless another one is found.
|
|
16
|
+
To use a particular version of ESLint 8, install it by yourself.
|
|
15
17
|
For example, to use ESLint 8.8.0:
|
|
16
18
|
|
|
17
19
|
```console
|
|
@@ -36,38 +38,36 @@ const gulpESLintNew = require('gulp-eslint-new');
|
|
|
36
38
|
|
|
37
39
|
// Define the default gulp task.
|
|
38
40
|
exports.default =
|
|
39
|
-
() =>
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
() =>
|
|
42
|
+
src(['scripts/*.js']) // Read files.
|
|
43
|
+
.pipe(gulpESLintNew({ fix: true })) // Lint files, create fixes.
|
|
44
|
+
.pipe(gulpESLintNew.fix()) // Fix files if necessary.
|
|
45
|
+
.pipe(gulpESLintNew.format()) // Output lint results to the console.
|
|
46
|
+
.pipe(gulpESLintNew.failAfterError()); // Exit with an error if problems are found.
|
|
44
47
|
```
|
|
45
48
|
|
|
46
49
|
Or use the plugin API to do things like:
|
|
47
50
|
|
|
48
51
|
```javascript
|
|
49
52
|
gulp.src(['**/*.js', '!node_modules/**'])
|
|
50
|
-
|
|
53
|
+
.pipe
|
|
54
|
+
(
|
|
55
|
+
gulpESLintNew
|
|
56
|
+
(
|
|
51
57
|
{
|
|
52
|
-
overrideConfig:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
globals: {
|
|
60
|
-
chrome: 'readonly',
|
|
61
|
-
},
|
|
62
|
-
plugins: ['jquery'],
|
|
63
|
-
rules: {
|
|
64
|
-
'strict': 'error',
|
|
65
|
-
},
|
|
58
|
+
overrideConfig:
|
|
59
|
+
{
|
|
60
|
+
env: { browser: true, commonjs: true, jquery: true },
|
|
61
|
+
extends: ['eslint:recommended', 'plugin:jquery/slim'],
|
|
62
|
+
globals: { chrome: 'readonly' },
|
|
63
|
+
plugins: ['jquery'],
|
|
64
|
+
rules: { 'strict': 'error' },
|
|
66
65
|
},
|
|
67
66
|
warnIgnored: true,
|
|
68
67
|
},
|
|
69
|
-
)
|
|
70
|
-
|
|
68
|
+
),
|
|
69
|
+
)
|
|
70
|
+
.pipe(gulpESLintNew.formatEach('compact', process.stderr));
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
For additional examples, look through the [example directory](https://github.com/origin-1/gulp-eslint-new/tree/main/example).
|
|
@@ -76,18 +76,44 @@ For additional examples, look through the [example directory](https://github.com
|
|
|
76
76
|
|
|
77
77
|
### `gulpESLintNew()`
|
|
78
78
|
|
|
79
|
-
|
|
79
|
+
Run ESLint with default settings. A [configuration file](https://eslint.org/docs/user-guide/configure/configuration-files) may be resolved relative to each linted file.
|
|
80
80
|
|
|
81
81
|
### `gulpESLintNew(options)`
|
|
82
82
|
|
|
83
83
|
Param type: `Record<string, unknown>`
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
Run ESLint with the specified options.
|
|
86
|
+
All supported options are listed below.
|
|
87
|
+
See the linked content for details about each option.
|
|
88
|
+
|
|
89
|
+
**General options**
|
|
90
|
+
* [`configType`](#optionsconfigtype)
|
|
91
|
+
* [`cwd`](#optionscwd)
|
|
92
|
+
|
|
93
|
+
**File enumeration options**
|
|
94
|
+
* [`ignore`](#optionsignore)
|
|
95
|
+
* [`ignorePath`](#optionsignorepath)
|
|
96
|
+
|
|
97
|
+
**Linting options**
|
|
98
|
+
* [`allowInlineConfig`][linting options]
|
|
99
|
+
* [`baseConfig`][linting options]
|
|
100
|
+
* [`overrideConfig`][linting options]
|
|
101
|
+
* [`overrideConfigFile`][linting options]
|
|
102
|
+
* [`plugins`][linting options]
|
|
103
|
+
* [`reportUnusedDisableDirectives`][linting options]
|
|
104
|
+
* [`resolvePluginsRelativeTo`][linting options]
|
|
105
|
+
* [`rulePaths`][linting options]
|
|
106
|
+
* [`useEslintrc`][linting options]
|
|
89
107
|
|
|
90
|
-
|
|
108
|
+
**Autofix options**
|
|
109
|
+
* [`fix`](#optionsfix)
|
|
110
|
+
* [`fixTypes`](#optionsfixtypes)
|
|
111
|
+
|
|
112
|
+
**Reporting options**
|
|
113
|
+
* [`quiet`](#optionsquiet)
|
|
114
|
+
* [`warnIgnored`](#optionswarnignored)
|
|
115
|
+
|
|
116
|
+
#### General Options
|
|
91
117
|
|
|
92
118
|
##### `options.configType`
|
|
93
119
|
|
|
@@ -113,6 +139,8 @@ The working directory is where ESLint will look for a `.eslintignore` file by de
|
|
|
113
139
|
It is also the base directory for any relative paths specified in the options (e.g. `overrideConfigFile`, `resolvePluginsRelativeTo`, `rulePaths`, `overrideConfig.extends`, etc.).
|
|
114
140
|
The location of the files to be linted is not related to the working directory.
|
|
115
141
|
|
|
142
|
+
#### File Enumeration Options
|
|
143
|
+
|
|
116
144
|
##### `options.ignore`
|
|
117
145
|
|
|
118
146
|
Type: `boolean`
|
|
@@ -125,6 +153,25 @@ Type: `string`
|
|
|
125
153
|
|
|
126
154
|
The path to a file ESLint uses instead of `.eslintignore` in the current working directory.
|
|
127
155
|
|
|
156
|
+
#### Autofix Options
|
|
157
|
+
|
|
158
|
+
##### `options.fix`
|
|
159
|
+
|
|
160
|
+
Type: `boolean | (message: LintMessage) => boolean`
|
|
161
|
+
|
|
162
|
+
Set to `true` or a function to generate fixes when possible, or set to `false` to explicitly disable autofixing.
|
|
163
|
+
If a predicate function is present, it will be invoked once for each lint message, and only the lint messages for which the function returned `true` will be reported.
|
|
164
|
+
|
|
165
|
+
**See the [Autofix](#autofix) section for more information and examples.**
|
|
166
|
+
|
|
167
|
+
##### `options.fixTypes`
|
|
168
|
+
|
|
169
|
+
Type: `("directive" | "problem" | "suggestion" | "layout")[]`
|
|
170
|
+
|
|
171
|
+
The types of fixes to apply. Default is all types.
|
|
172
|
+
|
|
173
|
+
#### Reporting Options
|
|
174
|
+
|
|
128
175
|
##### `options.quiet`
|
|
129
176
|
|
|
130
177
|
Type: `boolean`
|
|
@@ -179,19 +226,30 @@ Call a function for each ESLint file result. No returned value is expected. If a
|
|
|
179
226
|
|
|
180
227
|
```javascript
|
|
181
228
|
gulp.src(['**/*.js', '!node_modules/**'])
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
229
|
+
.pipe(gulpESLintNew())
|
|
230
|
+
.pipe
|
|
231
|
+
(
|
|
232
|
+
gulpESLintNew.result
|
|
233
|
+
(
|
|
234
|
+
result =>
|
|
235
|
+
{
|
|
185
236
|
// Called for each ESLint result.
|
|
186
237
|
console.log(`ESLint result: ${result.filePath}`);
|
|
187
238
|
console.log(`# Messages: ${result.messages.length}`);
|
|
188
|
-
console.log
|
|
189
|
-
|
|
190
|
-
|
|
239
|
+
console.log
|
|
240
|
+
(
|
|
241
|
+
`# Warnings: ${result.warningCount} (${
|
|
242
|
+
result.fixableWarningCount} fixable)`,
|
|
243
|
+
);
|
|
244
|
+
console.log
|
|
245
|
+
(
|
|
246
|
+
`# Errors: ${result.errorCount} (${
|
|
191
247
|
result.fixableErrorCount} fixable, ${
|
|
192
|
-
result.fatalErrorCount} fatal)
|
|
248
|
+
result.fatalErrorCount} fatal)`,
|
|
249
|
+
);
|
|
193
250
|
},
|
|
194
|
-
)
|
|
251
|
+
),
|
|
252
|
+
);
|
|
195
253
|
```
|
|
196
254
|
|
|
197
255
|
Param Type: `(result: Object, callback: Function) => void`
|
|
@@ -235,18 +293,29 @@ The results list has additional properties that indicate the number of messages
|
|
|
235
293
|
|
|
236
294
|
```javascript
|
|
237
295
|
gulp.src(['**/*.js', '!node_modules/**'])
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
296
|
+
.pipe(gulpESLintNew())
|
|
297
|
+
.pipe
|
|
298
|
+
(
|
|
299
|
+
gulpESLintNew.results
|
|
300
|
+
(
|
|
301
|
+
results =>
|
|
302
|
+
{
|
|
241
303
|
// Called once for all ESLint results.
|
|
242
304
|
console.log(`Total Results: ${results.length}`);
|
|
243
|
-
console.log
|
|
244
|
-
|
|
245
|
-
|
|
305
|
+
console.log
|
|
306
|
+
(
|
|
307
|
+
`Total Warnings: ${results.warningCount} (${
|
|
308
|
+
results.fixableWarningCount} fixable)`,
|
|
309
|
+
);
|
|
310
|
+
console.log
|
|
311
|
+
(
|
|
312
|
+
`Total Errors: ${results.errorCount} (${
|
|
246
313
|
results.fixableErrorCount} fixable, ${
|
|
247
|
-
results.fatalErrorCount} fatal)
|
|
314
|
+
results.fatalErrorCount} fatal)`,
|
|
315
|
+
);
|
|
248
316
|
},
|
|
249
|
-
)
|
|
317
|
+
),
|
|
318
|
+
);
|
|
250
319
|
```
|
|
251
320
|
|
|
252
321
|
Param type: `(results: Object[], callback: Function) => void`
|
|
@@ -264,8 +333,8 @@ Stop a task/stream if an ESLint error has been reported for any file.
|
|
|
264
333
|
```javascript
|
|
265
334
|
// Cause the stream to stop (fail) without processing more files.
|
|
266
335
|
gulp.src(['**/*.js', '!node_modules/**'])
|
|
267
|
-
|
|
268
|
-
|
|
336
|
+
.pipe(gulpESLintNew())
|
|
337
|
+
.pipe(gulpESLintNew.failOnError());
|
|
269
338
|
```
|
|
270
339
|
|
|
271
340
|
### `gulpESLintNew.failAfterError()`
|
|
@@ -276,17 +345,19 @@ Stop a task/stream if an ESLint error has been reported for any file, but wait f
|
|
|
276
345
|
// Cause the stream to stop (fail) when the stream ends if any ESLint error(s)
|
|
277
346
|
// occurred.
|
|
278
347
|
gulp.src(['**/*.js', '!node_modules/**'])
|
|
279
|
-
|
|
280
|
-
|
|
348
|
+
.pipe(gulpESLintNew())
|
|
349
|
+
.pipe(gulpESLintNew.failAfterError());
|
|
281
350
|
```
|
|
282
351
|
|
|
283
352
|
### `gulpESLintNew.format(formatter, writer)`
|
|
284
353
|
|
|
354
|
+
`formatter` param type: `string | Object | Function | undefined`
|
|
355
|
+
|
|
356
|
+
`writer` param type: `NodeJS.WritableStream | Function | undefined`
|
|
357
|
+
|
|
285
358
|
Format all linted files once.
|
|
286
359
|
This should be used in the stream after piping through `gulpESLintNew`; otherwise, this will find no ESLint results to format.
|
|
287
360
|
|
|
288
|
-
`formatter` param type: `string | Object | Function | undefined`
|
|
289
|
-
|
|
290
361
|
The `formatter` argument determines the [ESLint formatter](https://eslint.org/docs/user-guide/formatters/) used to format linting results.
|
|
291
362
|
If a `string` is provided, a formatter module by that name or path will be resolved.
|
|
292
363
|
The resolved formatter will be either one of the built-in ESLint formatters, or a formatter exported by a module with the specified path (located relative to the ESLint working directory), or a formatter exported by a package installed as a dependency (the prefix "eslint-formatter-" in the package name can be omitted).
|
|
@@ -305,8 +376,6 @@ gulpESLintNew.format('checkstyle')
|
|
|
305
376
|
gulpESLintNew.format('pretty')
|
|
306
377
|
```
|
|
307
378
|
|
|
308
|
-
`writer` param type: `NodeJS.WritableStream | Function | undefined`
|
|
309
|
-
|
|
310
379
|
The `writer` argument may be a writable stream, `Function`, or `undefined`.
|
|
311
380
|
As a writable stream, the formatter output will be written to the stream.
|
|
312
381
|
If `undefined`, the formatter output will be written to [gulp's log](https://github.com/gulpjs/fancy-log#logmsg).
|
|
@@ -322,6 +391,10 @@ gulpESLintNew.format('junit', process.stdout)
|
|
|
322
391
|
|
|
323
392
|
### `gulpESLintNew.formatEach(formatter, writer)`
|
|
324
393
|
|
|
394
|
+
`formatter` param type: `string | Object | Function | undefined`
|
|
395
|
+
|
|
396
|
+
`writer` param type: `NodeJS.WritableStream | Function | undefined`
|
|
397
|
+
|
|
325
398
|
Format each linted file individually.
|
|
326
399
|
This should be used in the stream after piping through `gulpESLintNew`; otherwise, this will find no ESLint results to format.
|
|
327
400
|
|
|
@@ -332,7 +405,8 @@ The arguments for `gulpESLintNew.formatEach` are the same as the arguments for [
|
|
|
332
405
|
Overwrite files with the fixed content provided by ESLint.
|
|
333
406
|
This should be used in conjunction with the option `fix` in [`gulpESLintNew(options)`](#gulpeslintnewoptions).
|
|
334
407
|
Files without a fix and files that were not processed by ESLint will be left untouched.
|
|
335
|
-
|
|
408
|
+
|
|
409
|
+
**See the [Autofix](#autofix) section for more information and examples.**
|
|
336
410
|
|
|
337
411
|
## Autofix
|
|
338
412
|
|
|
@@ -342,8 +416,8 @@ To enable autofix with gulp-eslint-new, set the option `fix` to `true` in [`gulp
|
|
|
342
416
|
|
|
343
417
|
```javascript
|
|
344
418
|
gulp.src(['**/*.{js,ts}', '!node_modules/**'])
|
|
345
|
-
|
|
346
|
-
|
|
419
|
+
.pipe(gulpESLintNew({ fix: true }))
|
|
420
|
+
.pipe(gulpESLintNew.fix());
|
|
347
421
|
```
|
|
348
422
|
|
|
349
423
|
See also the [autofix examples](https://github.com/origin-1/gulp-eslint-new/blob/main/example/fix.js).
|
|
@@ -360,5 +434,6 @@ This is available to streams that follow the initial gulp-eslint-new stream.
|
|
|
360
434
|
The functions [`gulpESLintNew.result`](#gulpeslintnewresultaction) and [`gulpESLintNew.results`](#gulpeslintnewresultsaction) are made available to support extensions and custom handling of ESLint results.
|
|
361
435
|
|
|
362
436
|
[gulp-eslint]: https://github.com/adametry/gulp-eslint
|
|
437
|
+
[linting options]: https://eslint.org/docs/developer-guide/nodejs-api#linting
|
|
363
438
|
[npm badge]: https://badge.fury.io/js/gulp-eslint-new.svg
|
|
364
439
|
[npm URL]: https://www.npmjs.com/package/gulp-eslint-new
|
package/lib/eslint.d.ts
CHANGED
|
@@ -1,22 +1,24 @@
|
|
|
1
|
-
import { ESLint, Linter } from 'eslint';
|
|
1
|
+
import type { ESLint, Linter } from 'eslint';
|
|
2
2
|
|
|
3
3
|
type ConfigData = Linter.Config;
|
|
4
4
|
|
|
5
5
|
type ESLintOptions = ESLint.Options;
|
|
6
6
|
|
|
7
|
-
interface FlatConfig
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
interface FlatConfig
|
|
8
|
+
{
|
|
9
|
+
files?: string[];
|
|
10
|
+
ignores?: string[];
|
|
11
|
+
languageOptions?: LanguageOptions;
|
|
12
|
+
linterOptions?:
|
|
13
|
+
{
|
|
14
|
+
noInlineConfig?: boolean;
|
|
15
|
+
reportUnusedDisableDirectives?: boolean;
|
|
14
16
|
};
|
|
15
|
-
name?:
|
|
16
|
-
plugins?:
|
|
17
|
-
processor?:
|
|
18
|
-
rules?:
|
|
19
|
-
settings?:
|
|
17
|
+
name?: string;
|
|
18
|
+
plugins?: Record<string, Plugin>;
|
|
19
|
+
processor?: string | Linter.Processor;
|
|
20
|
+
rules?: Linter.RulesRecord;
|
|
21
|
+
settings?: Record<string, unknown>;
|
|
20
22
|
}
|
|
21
23
|
|
|
22
24
|
type FormatterContext = ESLint.LintResultData & ResultsMeta;
|
|
@@ -26,26 +28,28 @@ type FormatterFunction =
|
|
|
26
28
|
|
|
27
29
|
type GlobalConf = boolean | 'off' | 'readable' | 'readonly' | 'writable' | 'writeable';
|
|
28
30
|
|
|
29
|
-
interface LanguageOptions
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
interface LanguageOptions
|
|
32
|
+
{
|
|
33
|
+
ecmaVersion?: number | 'latest';
|
|
34
|
+
globals?: Record<string, GlobalConf>;
|
|
35
|
+
parser?: string | Linter.ParserModule;
|
|
36
|
+
parserOptions?: Linter.ParserOptions;
|
|
37
|
+
sourceType?: 'script' | 'module' | 'commonjs';
|
|
35
38
|
}
|
|
36
39
|
|
|
37
40
|
type LintMessage = Linter.LintMessage;
|
|
38
41
|
|
|
39
42
|
type LintResult = ESLint.LintResult;
|
|
40
43
|
|
|
41
|
-
interface LoadedFormatter
|
|
42
|
-
|
|
43
|
-
}
|
|
44
|
+
interface LoadedFormatter
|
|
45
|
+
{ format(results: ESLint.LintResult[], resultsMeta: ResultsMeta): string | Promise<string>; }
|
|
44
46
|
|
|
45
|
-
type Plugin = ESLint.Plugin & { parsers?: Record<string, Linter.ParserModule> | undefined };
|
|
47
|
+
type Plugin = ESLint.Plugin & { parsers?: Record<string, Linter.ParserModule> | undefined; };
|
|
46
48
|
|
|
47
|
-
interface ResultsMeta
|
|
48
|
-
|
|
49
|
+
interface ResultsMeta
|
|
50
|
+
{
|
|
51
|
+
maxWarningsExceeded?:
|
|
52
|
+
{
|
|
49
53
|
foundWarnings: number;
|
|
50
54
|
maxWarnings: number;
|
|
51
55
|
};
|
package/lib/gulp-eslint-new.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type
|
|
2
|
+
{
|
|
2
3
|
ConfigData,
|
|
3
4
|
ESLintOptions,
|
|
4
5
|
FlatConfig,
|
|
@@ -7,18 +8,20 @@ import {
|
|
|
7
8
|
LintMessage,
|
|
8
9
|
LintResult,
|
|
9
10
|
LoadedFormatter,
|
|
10
|
-
ResultsMeta,
|
|
11
11
|
Plugin,
|
|
12
|
+
ResultsMeta,
|
|
12
13
|
}
|
|
13
|
-
|
|
14
|
-
import
|
|
15
|
-
import { TransformCallback }
|
|
14
|
+
from './eslint';
|
|
15
|
+
import 'node';
|
|
16
|
+
import type { TransformCallback } from 'stream';
|
|
17
|
+
|
|
18
|
+
type Awaitable<T = unknown> = T | Promise<T>;
|
|
16
19
|
|
|
17
|
-
export { FormatterContext, FormatterFunction };
|
|
20
|
+
export type { FormatterContext, FormatterFunction };
|
|
18
21
|
|
|
19
22
|
export type GulpESLintOptions =
|
|
20
|
-
(GulpESLintrcOptions & { configType?: 'eslintrc' | undefined }) |
|
|
21
|
-
(GulpFlatESLintOptions & { configType: 'flat' });
|
|
23
|
+
(GulpESLintrcOptions & { configType?: 'eslintrc' | undefined; }) |
|
|
24
|
+
(GulpFlatESLintOptions & { configType: 'flat'; });
|
|
22
25
|
|
|
23
26
|
export type GulpESLintResult = LintResult;
|
|
24
27
|
|
|
@@ -33,19 +36,19 @@ GulpESLintResult[] &
|
|
|
33
36
|
fixableWarningCount: number;
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
export type GulpESLintWriter = (str: string) =>
|
|
39
|
+
export type GulpESLintWriter = (str: string) => Awaitable;
|
|
37
40
|
|
|
38
41
|
type GulpESLintrcOptions
|
|
39
42
|
=
|
|
40
43
|
Omit<
|
|
41
|
-
ESLintOptions,
|
|
42
|
-
| 'cache'
|
|
43
|
-
| 'cacheLocation'
|
|
44
|
-
| 'cacheStrategy'
|
|
45
|
-
| 'errorOnUnmatchedPattern'
|
|
46
|
-
| 'extensions'
|
|
47
|
-
| 'globInputPaths'
|
|
48
|
-
| 'plugins'
|
|
44
|
+
ESLintOptions,
|
|
45
|
+
| 'cache'
|
|
46
|
+
| 'cacheLocation'
|
|
47
|
+
| 'cacheStrategy'
|
|
48
|
+
| 'errorOnUnmatchedPattern'
|
|
49
|
+
| 'extensions'
|
|
50
|
+
| 'globInputPaths'
|
|
51
|
+
| 'plugins'
|
|
49
52
|
> &
|
|
50
53
|
{
|
|
51
54
|
/** @deprecated Use `overrideConfigFile` instead. */
|
|
@@ -97,13 +100,13 @@ ESLintOptions,
|
|
|
97
100
|
type GulpFlatESLintOptions
|
|
98
101
|
=
|
|
99
102
|
Pick<
|
|
100
|
-
ESLintOptions,
|
|
101
|
-
| 'allowInlineConfig'
|
|
102
|
-
| 'cwd'
|
|
103
|
-
| 'fix'
|
|
104
|
-
| 'fixTypes'
|
|
105
|
-
| 'ignore'
|
|
106
|
-
| 'reportUnusedDisableDirectives'
|
|
103
|
+
ESLintOptions,
|
|
104
|
+
| 'allowInlineConfig'
|
|
105
|
+
| 'cwd'
|
|
106
|
+
| 'fix'
|
|
107
|
+
| 'fixTypes'
|
|
108
|
+
| 'ignore'
|
|
109
|
+
| 'reportUnusedDisableDirectives'
|
|
107
110
|
> &
|
|
108
111
|
{
|
|
109
112
|
baseConfig?: FlatConfig | undefined;
|
|
@@ -124,11 +127,12 @@ ESLintOptions,
|
|
|
124
127
|
|
|
125
128
|
type LintResultStreamFunction<Type> =
|
|
126
129
|
((action: (value: Type, callback: TransformCallback) => void) => NodeJS.ReadWriteStream) &
|
|
127
|
-
((action: (value: Type) =>
|
|
130
|
+
((action: (value: Type) => Awaitable) => NodeJS.ReadWriteStream);
|
|
128
131
|
|
|
129
|
-
export { LoadedFormatter, ResultsMeta };
|
|
132
|
+
export type { LoadedFormatter, ResultsMeta };
|
|
130
133
|
|
|
131
|
-
declare const gulpESLintNew:
|
|
134
|
+
declare const gulpESLintNew:
|
|
135
|
+
{
|
|
132
136
|
/**
|
|
133
137
|
* Append ESLint result to each file.
|
|
134
138
|
*
|
|
@@ -187,7 +191,8 @@ declare const gulpESLintNew: {
|
|
|
187
191
|
* Defaults to gulp's [fancy-log](https://github.com/gulpjs/fancy-log#readme).
|
|
188
192
|
* @returns gulp file stream.
|
|
189
193
|
*/
|
|
190
|
-
formatEach
|
|
194
|
+
formatEach
|
|
195
|
+
(
|
|
191
196
|
formatter?: string | LoadedFormatter | FormatterFunction,
|
|
192
197
|
writer?: GulpESLintWriter | NodeJS.WritableStream
|
|
193
198
|
): NodeJS.ReadWriteStream;
|
|
@@ -204,7 +209,8 @@ declare const gulpESLintNew: {
|
|
|
204
209
|
* Defaults to gulp's [fancy-log](https://github.com/gulpjs/fancy-log#readme).
|
|
205
210
|
* @returns gulp file stream.
|
|
206
211
|
*/
|
|
207
|
-
format
|
|
212
|
+
format
|
|
213
|
+
(
|
|
208
214
|
formatter?: string | LoadedFormatter | FormatterFunction,
|
|
209
215
|
writer?: GulpESLintWriter | NodeJS.WritableStream
|
|
210
216
|
): NodeJS.ReadWriteStream;
|
|
@@ -216,4 +222,5 @@ declare const gulpESLintNew: {
|
|
|
216
222
|
*/
|
|
217
223
|
fix(): NodeJS.ReadWriteStream;
|
|
218
224
|
};
|
|
225
|
+
|
|
219
226
|
export default gulpESLintNew;
|
package/lib/gulp-eslint-new.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const
|
|
4
|
+
{
|
|
4
5
|
GULP_DEST_KEY,
|
|
5
6
|
GULP_WARN_KEY,
|
|
6
7
|
createIgnoreResult,
|
|
@@ -17,30 +18,32 @@ const {
|
|
|
17
18
|
} = require('#util');
|
|
18
19
|
const { promisify } = require('util');
|
|
19
20
|
|
|
20
|
-
function wrapAction(action)
|
|
21
|
-
|
|
21
|
+
function wrapAction(action)
|
|
22
|
+
{
|
|
23
|
+
if (typeof action !== 'function')
|
|
22
24
|
throw TypeError('Argument is not a function');
|
|
23
|
-
|
|
24
|
-
if (action.length > 1) {
|
|
25
|
+
if (action.length > 1)
|
|
25
26
|
action = promisify(action);
|
|
26
|
-
}
|
|
27
27
|
return action;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
const createResultStream =
|
|
31
|
-
action =>
|
|
31
|
+
action =>
|
|
32
|
+
{
|
|
32
33
|
action = wrapAction(action);
|
|
33
|
-
return createTransform
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
return createTransform
|
|
35
|
+
(
|
|
36
|
+
async ({ eslint: result }) =>
|
|
37
|
+
{
|
|
38
|
+
if (result)
|
|
36
39
|
await action(result);
|
|
37
|
-
}
|
|
38
40
|
},
|
|
39
41
|
);
|
|
40
42
|
};
|
|
41
43
|
|
|
42
44
|
const createResultsStream =
|
|
43
|
-
action =>
|
|
45
|
+
action =>
|
|
46
|
+
{
|
|
44
47
|
action = wrapAction(action);
|
|
45
48
|
const results = [];
|
|
46
49
|
results.errorCount = 0;
|
|
@@ -48,9 +51,12 @@ action => {
|
|
|
48
51
|
results.fixableErrorCount = 0;
|
|
49
52
|
results.fixableWarningCount = 0;
|
|
50
53
|
results.fatalErrorCount = 0;
|
|
51
|
-
return createTransform
|
|
52
|
-
|
|
53
|
-
|
|
54
|
+
return createTransform
|
|
55
|
+
(
|
|
56
|
+
({ eslint: result }) =>
|
|
57
|
+
{
|
|
58
|
+
if (result)
|
|
59
|
+
{
|
|
54
60
|
results.push(result);
|
|
55
61
|
// Collect total error/warning count.
|
|
56
62
|
results.errorCount += result.errorCount;
|
|
@@ -60,64 +66,68 @@ action => {
|
|
|
60
66
|
results.fatalErrorCount += result.fatalErrorCount;
|
|
61
67
|
}
|
|
62
68
|
},
|
|
63
|
-
async () =>
|
|
69
|
+
async () =>
|
|
70
|
+
{
|
|
64
71
|
await action(results);
|
|
65
72
|
},
|
|
66
73
|
);
|
|
67
74
|
};
|
|
68
75
|
|
|
69
|
-
function getESLintInfo(file)
|
|
76
|
+
function getESLintInfo(file)
|
|
77
|
+
{
|
|
70
78
|
const eslintInfo = file._eslintInfo;
|
|
71
|
-
if (eslintInfo != null)
|
|
79
|
+
if (eslintInfo != null)
|
|
72
80
|
return eslintInfo;
|
|
73
|
-
}
|
|
74
81
|
throw createPluginError({ fileName: file.path, message: 'ESLint information not available' });
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
const warn =
|
|
78
85
|
(message, gulpWarn = require('fancy-log').warn) =>
|
|
79
|
-
|
|
86
|
+
gulpWarn(`\x1b[1;37m\x1b[40mgulp-eslint-new\x1b[0m \x1b[30m\x1b[43mWARN\x1b[0m\n${message}`);
|
|
80
87
|
|
|
81
|
-
function formatMigratedOptionWarningLine({ oldName, newName, formatChanged })
|
|
88
|
+
function formatMigratedOptionWarningLine({ oldName, newName, formatChanged })
|
|
89
|
+
{
|
|
82
90
|
let line = ` • ${oldName} → ${newName}`;
|
|
83
|
-
if (formatChanged)
|
|
91
|
+
if (formatChanged)
|
|
84
92
|
line += ' (format changed)';
|
|
85
|
-
}
|
|
86
93
|
return line;
|
|
87
94
|
}
|
|
88
95
|
|
|
89
|
-
async function lintFile(eslintInfo, file, quiet, warnIgnored)
|
|
90
|
-
|
|
96
|
+
async function lintFile(eslintInfo, file, quiet, warnIgnored)
|
|
97
|
+
{
|
|
98
|
+
if (file.isNull())
|
|
91
99
|
return;
|
|
92
|
-
|
|
93
|
-
if (file.isStream()) {
|
|
100
|
+
if (file.isStream())
|
|
94
101
|
throw 'gulp-eslint-new doesn\'t support Vinyl files with Stream contents.';
|
|
95
|
-
}
|
|
96
102
|
const { eslint } = eslintInfo;
|
|
97
103
|
// The "path" property of a Vinyl file should be always an absolute path.
|
|
98
104
|
// See https://gulpjs.com/docs/en/api/vinyl/#instance-properties.
|
|
99
105
|
const filePath = file.path;
|
|
100
106
|
let result;
|
|
101
|
-
if (await eslint.isPathIgnored(filePath))
|
|
107
|
+
if (await eslint.isPathIgnored(filePath))
|
|
108
|
+
{
|
|
102
109
|
// Note: ESLint doesn't adjust file paths relative to an ancestory .eslintignore path.
|
|
103
110
|
// E.g., If ../.eslintignore has "foo/*.js", ESLint will ignore ./foo/*.js, instead of
|
|
104
111
|
// ../foo/*.js.
|
|
105
|
-
if (!warnIgnored)
|
|
112
|
+
if (!warnIgnored)
|
|
106
113
|
return;
|
|
107
|
-
}
|
|
108
114
|
// Warn that gulp.src is needlessly reading files that ESLint ignores.
|
|
109
115
|
result = createIgnoreResult(filePath, eslintInfo.cwd, eslint.constructor.version);
|
|
110
|
-
}
|
|
116
|
+
}
|
|
117
|
+
else
|
|
118
|
+
{
|
|
111
119
|
[result] = await eslint.lintText(file.contents.toString(), { filePath });
|
|
112
120
|
// Note: Fixes are applied as part of `lintText`.
|
|
113
121
|
// Any applied fix messages have been removed from the result.
|
|
114
|
-
if (quiet)
|
|
122
|
+
if (quiet)
|
|
123
|
+
{
|
|
115
124
|
// Ignore some messages.
|
|
116
125
|
const filter = typeof quiet === 'function' ? quiet : isErrorMessage;
|
|
117
126
|
result = filterResult(result, filter);
|
|
118
127
|
}
|
|
119
128
|
// Update the fixed output; otherwise, fixable messages are simply ignored.
|
|
120
|
-
if (hasOwn(result, 'output'))
|
|
129
|
+
if (hasOwn(result, 'output'))
|
|
130
|
+
{
|
|
121
131
|
file.contents = Buffer.from(result.output);
|
|
122
132
|
result.fixed = true;
|
|
123
133
|
}
|
|
@@ -127,21 +137,22 @@ async function lintFile(eslintInfo, file, quiet, warnIgnored) {
|
|
|
127
137
|
}
|
|
128
138
|
|
|
129
139
|
module.exports = exports =
|
|
130
|
-
options =>
|
|
140
|
+
options =>
|
|
141
|
+
{
|
|
131
142
|
const { ESLint, eslintOptions, gulpWarn, migratedOptions, quiet, warnIgnored } =
|
|
132
143
|
organizeOptions(options);
|
|
133
|
-
if (eslintOptions.cwd === undefined)
|
|
144
|
+
if (eslintOptions.cwd === undefined)
|
|
134
145
|
eslintOptions.cwd = process.cwd();
|
|
135
|
-
}
|
|
136
146
|
{
|
|
137
147
|
const migratedOptionCount = migratedOptions.length;
|
|
138
|
-
if (migratedOptionCount)
|
|
148
|
+
if (migratedOptionCount)
|
|
149
|
+
{
|
|
139
150
|
const migratedOptionWarningText =
|
|
140
151
|
migratedOptions.map(formatMigratedOptionWarningLine).join('\n');
|
|
141
152
|
const messageIntro =
|
|
142
153
|
migratedOptionCount > 1 ?
|
|
143
|
-
|
|
144
|
-
|
|
154
|
+
'The following top-level options passed to gulpESLintNew() have been migrated' :
|
|
155
|
+
'The following top-level option passed to gulpESLintNew() has been migrated';
|
|
145
156
|
const message =
|
|
146
157
|
`${messageIntro}:\n${migratedOptionWarningText}\nSee ${makeNPMLink('legacy-options')
|
|
147
158
|
} for more information.`;
|
|
@@ -158,16 +169,20 @@ exports.result = createResultStream;
|
|
|
158
169
|
|
|
159
170
|
exports.results = createResultsStream;
|
|
160
171
|
|
|
161
|
-
function failOnErrorAction(result)
|
|
172
|
+
function failOnErrorAction(result)
|
|
173
|
+
{
|
|
162
174
|
const { messages } = result;
|
|
163
|
-
if (messages)
|
|
175
|
+
if (messages)
|
|
176
|
+
{
|
|
164
177
|
const error = messages.find(isErrorMessage);
|
|
165
|
-
if (error)
|
|
166
|
-
|
|
178
|
+
if (error)
|
|
179
|
+
{
|
|
180
|
+
throw createPluginError
|
|
181
|
+
(
|
|
167
182
|
{
|
|
168
|
-
name:
|
|
169
|
-
fileName:
|
|
170
|
-
message:
|
|
183
|
+
name: 'ESLintError',
|
|
184
|
+
fileName: result.filePath,
|
|
185
|
+
message: error.message,
|
|
171
186
|
lineNumber: error.line,
|
|
172
187
|
},
|
|
173
188
|
);
|
|
@@ -177,12 +192,15 @@ function failOnErrorAction(result) {
|
|
|
177
192
|
|
|
178
193
|
exports.failOnError = () => createResultStream(failOnErrorAction);
|
|
179
194
|
|
|
180
|
-
function failAfterErrorAction({ errorCount })
|
|
181
|
-
|
|
182
|
-
|
|
195
|
+
function failAfterErrorAction({ errorCount })
|
|
196
|
+
{
|
|
197
|
+
if (errorCount)
|
|
198
|
+
{
|
|
199
|
+
throw createPluginError
|
|
200
|
+
(
|
|
183
201
|
{
|
|
184
|
-
name:
|
|
185
|
-
message:
|
|
202
|
+
name: 'ESLintError',
|
|
203
|
+
message: `Failed with ${errorCount} ${errorCount === 1 ? 'error' : 'errors'}`,
|
|
186
204
|
},
|
|
187
205
|
);
|
|
188
206
|
}
|
|
@@ -191,17 +209,22 @@ function failAfterErrorAction({ errorCount }) {
|
|
|
191
209
|
exports.failAfterError = () => createResultsStream(failAfterErrorAction);
|
|
192
210
|
|
|
193
211
|
exports.formatEach =
|
|
194
|
-
(formatter, writer) =>
|
|
212
|
+
(formatter, writer) =>
|
|
213
|
+
{
|
|
195
214
|
writer = resolveWriter(writer);
|
|
196
215
|
const eslintToFormatterMap = new Map();
|
|
197
|
-
return createTransform
|
|
198
|
-
|
|
216
|
+
return createTransform
|
|
217
|
+
(
|
|
218
|
+
async file =>
|
|
219
|
+
{
|
|
199
220
|
const result = file.eslint;
|
|
200
|
-
if (result)
|
|
221
|
+
if (result)
|
|
222
|
+
{
|
|
201
223
|
const eslintInfo = getESLintInfo(file);
|
|
202
224
|
const { eslint } = eslintInfo;
|
|
203
225
|
let formatterObj = eslintToFormatterMap.get(eslint);
|
|
204
|
-
if (!formatterObj)
|
|
226
|
+
if (!formatterObj)
|
|
227
|
+
{
|
|
205
228
|
formatterObj = await resolveFormatter(eslintInfo, formatter);
|
|
206
229
|
eslintToFormatterMap.set(eslint, formatterObj);
|
|
207
230
|
}
|
|
@@ -213,32 +236,38 @@ exports.formatEach =
|
|
|
213
236
|
|
|
214
237
|
const ERROR_MULTIPLE_ESLINT_INSTANCES =
|
|
215
238
|
{
|
|
216
|
-
name:
|
|
217
|
-
message:
|
|
239
|
+
name: 'ESLintError',
|
|
240
|
+
message: 'The files in the stream were not processed by the same instance of ESLint',
|
|
218
241
|
};
|
|
219
242
|
|
|
220
243
|
exports.format =
|
|
221
|
-
(formatter, writer) =>
|
|
244
|
+
(formatter, writer) =>
|
|
245
|
+
{
|
|
222
246
|
writer = resolveWriter(writer);
|
|
223
247
|
const results = [];
|
|
224
248
|
let commonInfo;
|
|
225
|
-
return createTransform
|
|
226
|
-
|
|
249
|
+
return createTransform
|
|
250
|
+
(
|
|
251
|
+
file =>
|
|
252
|
+
{
|
|
227
253
|
const result = file.eslint;
|
|
228
|
-
if (result)
|
|
254
|
+
if (result)
|
|
255
|
+
{
|
|
229
256
|
const eslintInfo = getESLintInfo(file);
|
|
230
|
-
if (commonInfo == null)
|
|
257
|
+
if (commonInfo == null)
|
|
231
258
|
commonInfo = eslintInfo;
|
|
232
|
-
|
|
233
|
-
|
|
259
|
+
else
|
|
260
|
+
{
|
|
261
|
+
if (eslintInfo !== commonInfo)
|
|
234
262
|
throw createPluginError(ERROR_MULTIPLE_ESLINT_INSTANCES);
|
|
235
|
-
}
|
|
236
263
|
}
|
|
237
264
|
results.push(result);
|
|
238
265
|
}
|
|
239
266
|
},
|
|
240
|
-
async () =>
|
|
241
|
-
|
|
267
|
+
async () =>
|
|
268
|
+
{
|
|
269
|
+
if (results.length)
|
|
270
|
+
{
|
|
242
271
|
const formatterObj = await resolveFormatter(commonInfo, formatter);
|
|
243
272
|
await writeResults(results, formatterObj, writer);
|
|
244
273
|
}
|
|
@@ -248,15 +277,19 @@ exports.format =
|
|
|
248
277
|
|
|
249
278
|
const getBase = ({ base }) => base;
|
|
250
279
|
exports.fix =
|
|
251
|
-
({ [GULP_DEST_KEY]: gulpDest = require('vinyl-fs').dest, [GULP_WARN_KEY]: gulpWarn } = { }) =>
|
|
280
|
+
({ [GULP_DEST_KEY]: gulpDest = require('vinyl-fs').dest, [GULP_WARN_KEY]: gulpWarn } = { }) =>
|
|
281
|
+
{
|
|
252
282
|
const ternaryStream = require('ternary-stream');
|
|
253
283
|
let warned = false;
|
|
254
284
|
const isFixed =
|
|
255
|
-
file =>
|
|
285
|
+
file =>
|
|
286
|
+
{
|
|
256
287
|
const result = file.eslint;
|
|
257
|
-
if (result)
|
|
288
|
+
if (result)
|
|
289
|
+
{
|
|
258
290
|
const eslintInfo = getESLintInfo(file);
|
|
259
|
-
if (eslintInfo.fix == null && !warned)
|
|
291
|
+
if (eslintInfo.fix == null && !warned)
|
|
292
|
+
{
|
|
260
293
|
warned = true;
|
|
261
294
|
const message =
|
|
262
295
|
'gulpESLintNew.fix() received a file that was linted without the option "fix".\n' +
|
package/lib/util.js
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
* @param {LintResultData} [data]
|
|
16
16
|
* @returns {string | Promise<string>}
|
|
17
17
|
*/
|
|
18
|
+
|
|
18
19
|
const { relative } = require('path');
|
|
19
20
|
const { Transform } = require('stream');
|
|
20
21
|
|
|
@@ -22,27 +23,26 @@ const ESLINT_KEY = Symbol('ESLint');
|
|
|
22
23
|
const GULP_DEST_KEY = Symbol('require("vinyl-fs").dest');
|
|
23
24
|
const GULP_WARN_KEY = Symbol('require("fancy-log").warn');
|
|
24
25
|
|
|
25
|
-
function compareResultsByFilePath({ filePath: filePath1 }, { filePath: filePath2 })
|
|
26
|
-
|
|
26
|
+
function compareResultsByFilePath({ filePath: filePath1 }, { filePath: filePath2 })
|
|
27
|
+
{
|
|
28
|
+
if (filePath1 > filePath2)
|
|
27
29
|
return 1;
|
|
28
|
-
|
|
29
|
-
if (filePath1 < filePath2) {
|
|
30
|
+
if (filePath1 < filePath2)
|
|
30
31
|
return -1;
|
|
31
|
-
}
|
|
32
32
|
return 0;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const PLUGIN_ERROR_OPTIONS = { showStack: true };
|
|
36
36
|
|
|
37
|
-
function createPluginError(error)
|
|
37
|
+
function createPluginError(error)
|
|
38
|
+
{
|
|
38
39
|
const PluginError = require('plugin-error');
|
|
39
|
-
if (error instanceof PluginError)
|
|
40
|
+
if (error instanceof PluginError)
|
|
40
41
|
return error;
|
|
41
|
-
|
|
42
|
-
if (error == null) {
|
|
42
|
+
if (error == null)
|
|
43
43
|
error = 'Unknown Error';
|
|
44
|
-
|
|
45
|
-
return
|
|
44
|
+
const pluginError = PluginError('gulp-eslint-new', error, PLUGIN_ERROR_OPTIONS);
|
|
45
|
+
return pluginError;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const { defineProperty } = Object;
|
|
@@ -111,19 +111,25 @@ const isInNodeModulesRegExp = /(?<![^/\\])node_modules[/\\]/u;
|
|
|
111
111
|
* @returns {LintResult} Result with warning by ignore settings.
|
|
112
112
|
*/
|
|
113
113
|
exports.createIgnoreResult =
|
|
114
|
-
(filePath, baseDir, eslintVersion) =>
|
|
114
|
+
(filePath, baseDir, eslintVersion) =>
|
|
115
|
+
{
|
|
115
116
|
const { ltr } = require('semver');
|
|
116
117
|
let message;
|
|
117
118
|
const relativePath = relative(baseDir, filePath);
|
|
118
|
-
if (isHiddenRegExp.test(relativePath))
|
|
119
|
+
if (isHiddenRegExp.test(relativePath))
|
|
120
|
+
{
|
|
119
121
|
message =
|
|
120
122
|
'File ignored by default. Use a negated ignore pattern (like ' +
|
|
121
123
|
'"!<relative/path/to/filename>") to override.';
|
|
122
|
-
}
|
|
124
|
+
}
|
|
125
|
+
else if (isInNodeModulesRegExp.test(relativePath))
|
|
126
|
+
{
|
|
123
127
|
message =
|
|
124
128
|
'File ignored by default. Use a negated ignore pattern like "!node_modules/*" to ' +
|
|
125
129
|
'override.';
|
|
126
|
-
}
|
|
130
|
+
}
|
|
131
|
+
else
|
|
132
|
+
{
|
|
127
133
|
message =
|
|
128
134
|
'File ignored because of a matching ignore pattern. Set "ignore" option to false to ' +
|
|
129
135
|
'override.';
|
|
@@ -131,26 +137,30 @@ exports.createIgnoreResult =
|
|
|
131
137
|
const result =
|
|
132
138
|
{
|
|
133
139
|
filePath,
|
|
134
|
-
messages:
|
|
135
|
-
errorCount:
|
|
136
|
-
warningCount:
|
|
137
|
-
fixableErrorCount:
|
|
138
|
-
fixableWarningCount:
|
|
139
|
-
fatalErrorCount:
|
|
140
|
+
messages: [{ fatal: false, severity: 1, message }],
|
|
141
|
+
errorCount: 0,
|
|
142
|
+
warningCount: 1,
|
|
143
|
+
fixableErrorCount: 0,
|
|
144
|
+
fixableWarningCount: 0,
|
|
145
|
+
fatalErrorCount: 0,
|
|
140
146
|
};
|
|
141
|
-
if (!ltr(eslintVersion, '8.8.0'))
|
|
147
|
+
if (!ltr(eslintVersion, '8.8.0'))
|
|
142
148
|
result.suppressedMessages = [];
|
|
143
|
-
}
|
|
144
149
|
return result;
|
|
145
150
|
};
|
|
146
151
|
|
|
147
152
|
exports.createPluginError = createPluginError;
|
|
148
153
|
|
|
149
|
-
async function awaitHandler(handler, data, done)
|
|
150
|
-
|
|
154
|
+
async function awaitHandler(handler, data, done)
|
|
155
|
+
{
|
|
156
|
+
try
|
|
157
|
+
{
|
|
151
158
|
await handler();
|
|
152
|
-
}
|
|
153
|
-
|
|
159
|
+
}
|
|
160
|
+
catch (error)
|
|
161
|
+
{
|
|
162
|
+
const pluginError = createPluginError(error);
|
|
163
|
+
done(pluginError);
|
|
154
164
|
return;
|
|
155
165
|
}
|
|
156
166
|
done(null, data);
|
|
@@ -173,29 +183,33 @@ async function awaitHandler(handler, data, done) {
|
|
|
173
183
|
* @returns {Transform} A transform stream.
|
|
174
184
|
*/
|
|
175
185
|
exports.createTransform =
|
|
176
|
-
(handleFile, handleFinal) =>
|
|
186
|
+
(handleFile, handleFinal) =>
|
|
187
|
+
{
|
|
177
188
|
const transform = (file, enc, done) => void awaitHandler(() => handleFile(file), file, done);
|
|
178
189
|
const final = handleFinal ? done => void awaitHandler(handleFinal, null, done) : undefined;
|
|
179
|
-
return new Transform({ objectMode: true, transform, final });
|
|
190
|
+
return new Transform({ autoDestroy: false, objectMode: true, transform, final });
|
|
180
191
|
};
|
|
181
192
|
|
|
193
|
+
/**
|
|
194
|
+
* @callback CountMessagePredicate
|
|
195
|
+
* @param {LintMessage} message - ESLint message.
|
|
196
|
+
* @returns {boolean} `true` or `false`, depending on the input.
|
|
197
|
+
*/
|
|
198
|
+
|
|
182
199
|
/**
|
|
183
200
|
* Count the number of messages for which a predicate function returns `true`.
|
|
184
201
|
*
|
|
185
202
|
* @param {LintMessage[]} messages - ESLint messages to count.
|
|
186
203
|
* @param {CountMessagePredicate} predicate - Function to call for each message.
|
|
187
204
|
* @returns {number} The number of messages for which the predicate function returns `true`.
|
|
188
|
-
*
|
|
189
|
-
* @callback CountMessagePredicate
|
|
190
|
-
* @param {LintMessage} message - ESLint message.
|
|
191
|
-
* @returns {boolean} `true` or `false`, depending on the input.
|
|
192
205
|
*/
|
|
193
|
-
function countMessages(messages, predicate)
|
|
206
|
+
function countMessages(messages, predicate)
|
|
207
|
+
{
|
|
194
208
|
let count = 0;
|
|
195
|
-
for (const message of messages)
|
|
196
|
-
|
|
209
|
+
for (const message of messages)
|
|
210
|
+
{
|
|
211
|
+
if (predicate(message))
|
|
197
212
|
++count;
|
|
198
|
-
}
|
|
199
213
|
}
|
|
200
214
|
return count;
|
|
201
215
|
}
|
|
@@ -208,7 +222,8 @@ function countMessages(messages, predicate) {
|
|
|
208
222
|
* @returns {LintResult} A filtered ESLint result.
|
|
209
223
|
*/
|
|
210
224
|
exports.filterResult =
|
|
211
|
-
(result, filter) =>
|
|
225
|
+
(result, filter) =>
|
|
226
|
+
{
|
|
212
227
|
const { messages, ...newResult } = result;
|
|
213
228
|
const newMessages = messages.filter(filter, result);
|
|
214
229
|
newResult.messages = newMessages;
|
|
@@ -227,7 +242,8 @@ exports.isErrorMessage = isErrorMessage;
|
|
|
227
242
|
exports.isWarningMessage = isWarningMessage;
|
|
228
243
|
|
|
229
244
|
const makeNPMLink =
|
|
230
|
-
anchor =>
|
|
245
|
+
anchor =>
|
|
246
|
+
{
|
|
231
247
|
const { version } = require('gulp-eslint-new/package.json');
|
|
232
248
|
const npmLink = `https://www.npmjs.com/package/gulp-eslint-new/v/${version}#${anchor}`;
|
|
233
249
|
return npmLink;
|
|
@@ -235,7 +251,8 @@ anchor => {
|
|
|
235
251
|
|
|
236
252
|
exports.makeNPMLink = makeNPMLink;
|
|
237
253
|
|
|
238
|
-
const FORBIDDEN_OPTIONS =
|
|
254
|
+
const FORBIDDEN_OPTIONS =
|
|
255
|
+
[
|
|
239
256
|
'cache',
|
|
240
257
|
'cacheFile',
|
|
241
258
|
'cacheLocation',
|
|
@@ -247,8 +264,10 @@ const FORBIDDEN_OPTIONS = [
|
|
|
247
264
|
|
|
248
265
|
const requireESLint = (ESLint = require('eslint').ESLint) => ESLint;
|
|
249
266
|
|
|
250
|
-
function requireFlatESLint(ESLint = require('eslint/use-at-your-own-risk').FlatESLint)
|
|
251
|
-
|
|
267
|
+
function requireFlatESLint(ESLint = require('eslint/use-at-your-own-risk').FlatESLint)
|
|
268
|
+
{
|
|
269
|
+
if (ESLint == null)
|
|
270
|
+
{
|
|
252
271
|
const message =
|
|
253
272
|
'The version of ESLint you are using does not support flat config. ' +
|
|
254
273
|
'To use flat config, upgrade to ESLint 8.21 or later.';
|
|
@@ -261,34 +280,38 @@ function requireFlatESLint(ESLint = require('eslint/use-at-your-own-risk').FlatE
|
|
|
261
280
|
* Throws an error about invalid options passed to gulp-eslint-new.
|
|
262
281
|
*
|
|
263
282
|
* @param {string} message - The error message.
|
|
264
|
-
* @throws An error with code "ESLINT_INVALID_OPTIONS" and the specified message.
|
|
283
|
+
* @throws An error with code `"ESLINT_INVALID_OPTIONS"` and the specified message.
|
|
265
284
|
*/
|
|
266
|
-
function throwInvalidOptionError(message)
|
|
285
|
+
function throwInvalidOptionError(message)
|
|
286
|
+
{
|
|
267
287
|
const error = Error(message);
|
|
268
288
|
Error.captureStackTrace(error, throwInvalidOptionError);
|
|
269
289
|
error.code = 'ESLINT_INVALID_OPTIONS';
|
|
270
290
|
throw error;
|
|
271
291
|
}
|
|
272
292
|
|
|
293
|
+
// Adapted from https://github.com/eslint/eslint/blob/v6.8.0/lib/cli-engine/cli-engine.js#L455-L480.
|
|
273
294
|
/**
|
|
274
295
|
* Convert a string array to a boolean map.
|
|
275
296
|
*
|
|
276
|
-
* @param {string[] | null}
|
|
297
|
+
* @param {string[] | null} strs - The strings to be mapped.
|
|
277
298
|
* @param {boolean} defaultValue - The default value for each property.
|
|
278
299
|
* @param {string} displayName - The property name which is used in error message.
|
|
279
|
-
* @returns {
|
|
300
|
+
* @returns {Object.<string, boolean> | undefined} A boolean map or `undefined`.
|
|
280
301
|
*/
|
|
281
|
-
function toBooleanMap(keys, defaultValue, displayName)
|
|
282
|
-
|
|
302
|
+
function toBooleanMap(keys, defaultValue, displayName)
|
|
303
|
+
{
|
|
304
|
+
if (keys && !Array.isArray(keys))
|
|
283
305
|
throwInvalidOptionError(`Option ${displayName} must be an array`);
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
return keys.reduce
|
|
287
|
-
|
|
306
|
+
if (keys && keys.length > 0)
|
|
307
|
+
{
|
|
308
|
+
return keys.reduce
|
|
309
|
+
(
|
|
310
|
+
(map, def) =>
|
|
311
|
+
{
|
|
288
312
|
const [key, value] = def.split(':');
|
|
289
|
-
if (key !== '__proto__')
|
|
313
|
+
if (key !== '__proto__')
|
|
290
314
|
map[key] = value === undefined ? defaultValue : value === 'true';
|
|
291
|
-
}
|
|
292
315
|
return map;
|
|
293
316
|
},
|
|
294
317
|
{ },
|
|
@@ -299,36 +322,38 @@ function toBooleanMap(keys, defaultValue, displayName) {
|
|
|
299
322
|
/**
|
|
300
323
|
* Organize, migrate and partially validate the options passed to gulp-eslint-new.
|
|
301
324
|
*
|
|
302
|
-
* @param {
|
|
325
|
+
* @param {Object.<string | symbol, unknown>} [options] - Options to organize.
|
|
303
326
|
* @returns {OrganizedOptions} Organized options.
|
|
304
327
|
*
|
|
305
328
|
* @typedef {Object} OrganizedOptions
|
|
306
329
|
* @property {Function} [ESLint]
|
|
307
|
-
* @property {
|
|
330
|
+
* @property {Object.<string, unknown>} eslintOptions
|
|
308
331
|
* @property {Function} [gulpWarn]
|
|
309
332
|
* @property {Object[]} migratedOptions
|
|
310
333
|
* @property {boolean | undefined} [quiet]
|
|
311
334
|
* @property {boolean | undefined} [warnIgnored]
|
|
312
335
|
*/
|
|
313
336
|
exports.organizeOptions =
|
|
314
|
-
(options = { }) =>
|
|
337
|
+
(options = { }) =>
|
|
338
|
+
{
|
|
315
339
|
const migratedOptions = [];
|
|
316
|
-
if (typeof options === 'string')
|
|
340
|
+
if (typeof options === 'string')
|
|
341
|
+
{
|
|
317
342
|
const organizedOptions =
|
|
318
343
|
{
|
|
319
|
-
ESLint:
|
|
320
|
-
eslintOptions:
|
|
344
|
+
ESLint: requireESLint(),
|
|
345
|
+
eslintOptions: { overrideConfigFile: options },
|
|
321
346
|
migratedOptions,
|
|
322
347
|
};
|
|
323
348
|
return organizedOptions;
|
|
324
349
|
}
|
|
325
350
|
{
|
|
326
351
|
const invalidOptions = FORBIDDEN_OPTIONS.filter(option => hasOwn(options, option));
|
|
327
|
-
if (invalidOptions.length)
|
|
352
|
+
if (invalidOptions.length)
|
|
328
353
|
throwInvalidOptionError(`Invalid options: ${invalidOptions.join(', ')}`);
|
|
329
|
-
}
|
|
330
354
|
}
|
|
331
|
-
const
|
|
355
|
+
const
|
|
356
|
+
{
|
|
332
357
|
[ESLINT_KEY]: rawESLint,
|
|
333
358
|
[GULP_WARN_KEY]: gulpWarn,
|
|
334
359
|
configType,
|
|
@@ -337,30 +362,32 @@ exports.organizeOptions =
|
|
|
337
362
|
...eslintOptions
|
|
338
363
|
} =
|
|
339
364
|
options;
|
|
340
|
-
if (configType != null && configType !== 'eslintrc' && configType !== 'flat')
|
|
365
|
+
if (configType != null && configType !== 'eslintrc' && configType !== 'flat')
|
|
341
366
|
throwInvalidOptionError('Option configType must be one of "eslintrc", "flat", or null');
|
|
342
|
-
}
|
|
343
367
|
const useEslintrcConfig = configType !== 'flat';
|
|
344
368
|
const ESLint =
|
|
345
|
-
|
|
369
|
+
(useEslintrcConfig ? requireESLint : requireFlatESLint)(rawESLint);
|
|
346
370
|
const organizedOptions =
|
|
347
371
|
{ ESLint, eslintOptions, gulpWarn, migratedOptions, quiet, warnIgnored };
|
|
348
|
-
if (useEslintrcConfig)
|
|
372
|
+
if (useEslintrcConfig)
|
|
373
|
+
{
|
|
349
374
|
let { overrideConfig } = eslintOptions;
|
|
350
|
-
if (overrideConfig != null && typeof overrideConfig !== 'object')
|
|
375
|
+
if (overrideConfig != null && typeof overrideConfig !== 'object')
|
|
351
376
|
throwInvalidOptionError('Option overrideConfig must be an object or null');
|
|
352
|
-
}
|
|
353
377
|
overrideConfig = eslintOptions.overrideConfig =
|
|
354
378
|
overrideConfig != null ? { ...overrideConfig } : { };
|
|
355
379
|
const migrateOption =
|
|
356
|
-
function
|
|
380
|
+
function
|
|
381
|
+
(
|
|
357
382
|
oldName,
|
|
358
383
|
newName = oldName,
|
|
359
384
|
newOptions = overrideConfig,
|
|
360
385
|
needsMigration = hasOwn(eslintOptions, oldName),
|
|
361
386
|
convert,
|
|
362
|
-
)
|
|
363
|
-
|
|
387
|
+
)
|
|
388
|
+
{
|
|
389
|
+
if (needsMigration)
|
|
390
|
+
{
|
|
364
391
|
const value = eslintOptions[oldName];
|
|
365
392
|
delete eslintOptions[oldName];
|
|
366
393
|
{
|
|
@@ -374,7 +401,8 @@ exports.organizeOptions =
|
|
|
374
401
|
}
|
|
375
402
|
};
|
|
376
403
|
migrateOption('configFile', 'overrideConfigFile', eslintOptions);
|
|
377
|
-
migrateOption
|
|
404
|
+
migrateOption
|
|
405
|
+
(
|
|
378
406
|
'envs',
|
|
379
407
|
'env',
|
|
380
408
|
undefined,
|
|
@@ -382,7 +410,8 @@ exports.organizeOptions =
|
|
|
382
410
|
envs => toBooleanMap(envs, true, 'envs'),
|
|
383
411
|
);
|
|
384
412
|
migrateOption('extends');
|
|
385
|
-
migrateOption
|
|
413
|
+
migrateOption
|
|
414
|
+
(
|
|
386
415
|
'globals',
|
|
387
416
|
undefined,
|
|
388
417
|
undefined,
|
|
@@ -413,30 +442,36 @@ exports.organizeOptions =
|
|
|
413
442
|
* @returns {Promise<LoadedFormatter>} An ESLint formatter.
|
|
414
443
|
*/
|
|
415
444
|
exports.resolveFormatter =
|
|
416
|
-
async ({ cwd, eslint }, formatter) =>
|
|
417
|
-
|
|
445
|
+
async ({ cwd, eslint }, formatter) =>
|
|
446
|
+
{
|
|
447
|
+
if (formatter === undefined)
|
|
448
|
+
{
|
|
418
449
|
const { format } = await eslint.loadFormatter();
|
|
419
450
|
return {
|
|
420
451
|
format: results =>
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
452
|
+
format(results)
|
|
453
|
+
.replace
|
|
454
|
+
(
|
|
455
|
+
/ with the `--fix` option\.(?=(\u001b\[\d+m|\n)+$)/,
|
|
456
|
+
` - see ${makeNPMLink('autofix')}`,
|
|
457
|
+
),
|
|
426
458
|
};
|
|
427
459
|
}
|
|
428
|
-
if (isObject(formatter) && typeof formatter.format === 'function')
|
|
460
|
+
if (isObject(formatter) && typeof formatter.format === 'function')
|
|
429
461
|
return formatter;
|
|
430
|
-
|
|
431
|
-
|
|
462
|
+
if (typeof formatter === 'function')
|
|
463
|
+
{
|
|
432
464
|
return {
|
|
433
|
-
format: results =>
|
|
465
|
+
format: results =>
|
|
466
|
+
{
|
|
434
467
|
results.sort(compareResultsByFilePath);
|
|
435
|
-
return formatter
|
|
468
|
+
return formatter
|
|
469
|
+
(
|
|
436
470
|
results,
|
|
437
471
|
{
|
|
438
472
|
cwd,
|
|
439
|
-
get rulesMeta()
|
|
473
|
+
get rulesMeta()
|
|
474
|
+
{
|
|
440
475
|
const rulesMeta = eslint.getRulesMetaForResults(results);
|
|
441
476
|
defineProperty(this, 'rulesMeta', { value: rulesMeta });
|
|
442
477
|
return rulesMeta;
|
|
@@ -458,12 +493,13 @@ async ({ cwd, eslint }, formatter) => {
|
|
|
458
493
|
* @returns {GulpESLintWriter} A function that writes formatted messages.
|
|
459
494
|
*/
|
|
460
495
|
exports.resolveWriter =
|
|
461
|
-
(writer = require('fancy-log')) =>
|
|
462
|
-
|
|
496
|
+
(writer = require('fancy-log')) =>
|
|
497
|
+
{
|
|
498
|
+
if (isObject(writer))
|
|
499
|
+
{
|
|
463
500
|
const { write } = writer;
|
|
464
|
-
if (typeof write === 'function')
|
|
501
|
+
if (typeof write === 'function')
|
|
465
502
|
writer = write.bind(writer);
|
|
466
|
-
}
|
|
467
503
|
}
|
|
468
504
|
return writer;
|
|
469
505
|
};
|
|
@@ -481,9 +517,9 @@ exports.resolveWriter =
|
|
|
481
517
|
* A function used to write formatted ESLint messages.
|
|
482
518
|
*/
|
|
483
519
|
exports.writeResults =
|
|
484
|
-
async (results, formatterObj, writer) =>
|
|
520
|
+
async (results, formatterObj, writer) =>
|
|
521
|
+
{
|
|
485
522
|
const message = await formatterObj.format(results, { });
|
|
486
|
-
if (writer && message != null && message !== '')
|
|
523
|
+
if (writer && message != null && message !== '')
|
|
487
524
|
await writer(message);
|
|
488
|
-
}
|
|
489
525
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gulp-eslint-new",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.2",
|
|
4
4
|
"description": "A gulp plugin to lint code with ESLint 8",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"gulpplugin",
|
|
@@ -33,38 +33,38 @@
|
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "npm install && gulp",
|
|
35
35
|
"coverage": "gulp test",
|
|
36
|
-
"lint": "eslint .",
|
|
36
|
+
"lint": "eslint . --format compact",
|
|
37
37
|
"test": "mocha --check-leaks test/*.spec.js",
|
|
38
38
|
"ts-test": "tsc --project test/tsconfig.json"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@types/eslint": "^8.
|
|
41
|
+
"@types/eslint": "^8.21.0",
|
|
42
42
|
"@types/node": ">=12",
|
|
43
43
|
"eslint": "8",
|
|
44
44
|
"fancy-log": "^2.0.0",
|
|
45
|
-
"plugin-error": "^2.0.
|
|
45
|
+
"plugin-error": "^2.0.1",
|
|
46
46
|
"semver": "^7.3.8",
|
|
47
47
|
"ternary-stream": "^3.0.0",
|
|
48
48
|
"vinyl-fs": "^3.0.3"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"@typescript-eslint/parser": "^5.
|
|
51
|
+
"@origin-1/eslint-config": "^0.10.0",
|
|
52
|
+
"@typescript-eslint/parser": "^5.51.0",
|
|
53
53
|
"c8js": "^0.3.0",
|
|
54
54
|
"eslint-8.0": "npm:eslint@8.0",
|
|
55
55
|
"eslint-8.21": "npm:eslint@8.21",
|
|
56
56
|
"eslint-8.x": "npm:eslint@8.x",
|
|
57
|
-
"eslint-formatter-~formatter": "file:test/formatter",
|
|
58
57
|
"eslint-config-~shareable": "file:test/config",
|
|
58
|
+
"eslint-formatter-~formatter": "file:test/formatter",
|
|
59
59
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
60
60
|
"eslint-plugin-tsdoc": "^0.2.17",
|
|
61
61
|
"gulp": "^4.0.2",
|
|
62
62
|
"mocha": "^9.2.2",
|
|
63
|
-
"typescript": "^4.
|
|
63
|
+
"typescript": "^4.9.5",
|
|
64
64
|
"vinyl": "^3.0.0"
|
|
65
65
|
},
|
|
66
66
|
"engines": {
|
|
67
|
-
"node": "12
|
|
67
|
+
"node": "^12.20 || ^14.13 || >=16"
|
|
68
68
|
},
|
|
69
69
|
"exports": {
|
|
70
70
|
".": "./lib/gulp-eslint-new.js",
|