xo 0.44.0 → 0.46.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/config/plugins.cjs +18 -16
- package/index.js +59 -39
- package/lib/constants.js +0 -8
- package/lib/options-manager.js +68 -33
- package/package.json +27 -26
- package/readme.md +18 -9
package/config/plugins.cjs
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module.exports = {
|
|
4
4
|
// Repeated here from eslint-config-xo in case some plugins set something different
|
|
5
5
|
parserOptions: {
|
|
6
|
-
ecmaVersion:
|
|
6
|
+
ecmaVersion: 'latest',
|
|
7
7
|
sourceType: 'module',
|
|
8
8
|
ecmaFeatures: {
|
|
9
9
|
jsx: true,
|
|
@@ -14,7 +14,8 @@ module.exports = {
|
|
|
14
14
|
'no-use-extend-native',
|
|
15
15
|
'ava',
|
|
16
16
|
'unicorn',
|
|
17
|
-
'
|
|
17
|
+
// Disabled as the plugin doesn't support ESLint 8 yet.
|
|
18
|
+
// 'promise',
|
|
18
19
|
'import',
|
|
19
20
|
'node',
|
|
20
21
|
'eslint-comments',
|
|
@@ -173,17 +174,19 @@ module.exports = {
|
|
|
173
174
|
// TODO: Temporarily disabled as the rule is buggy.
|
|
174
175
|
'function-call-argument-newline': 'off',
|
|
175
176
|
|
|
176
|
-
'
|
|
177
|
-
'promise/
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
'promise/no-
|
|
185
|
-
'promise/
|
|
186
|
-
'promise/
|
|
177
|
+
// Disabled as the plugin doesn't support ESLint 8 yet.
|
|
178
|
+
// 'promise/param-names': 'error',
|
|
179
|
+
// 'promise/no-return-wrap': [
|
|
180
|
+
// 'error',
|
|
181
|
+
// {
|
|
182
|
+
// allowReject: true,
|
|
183
|
+
// },
|
|
184
|
+
// ],
|
|
185
|
+
// 'promise/no-new-statics': 'error',
|
|
186
|
+
// 'promise/no-return-in-finally': 'error',
|
|
187
|
+
// 'promise/valid-params': 'error',
|
|
188
|
+
// 'promise/prefer-await-to-then': 'error',
|
|
189
|
+
|
|
187
190
|
'import/default': 'error',
|
|
188
191
|
'import/export': 'error',
|
|
189
192
|
'import/extensions': [
|
|
@@ -200,9 +203,8 @@ module.exports = {
|
|
|
200
203
|
],
|
|
201
204
|
'import/first': 'error',
|
|
202
205
|
|
|
203
|
-
//
|
|
204
|
-
|
|
205
|
-
// 'import/named': 'error',
|
|
206
|
+
// Enabled, but disabled on TypeScript (https://github.com/xojs/xo/issues/576)
|
|
207
|
+
'import/named': 'error',
|
|
206
208
|
|
|
207
209
|
'import/namespace': [
|
|
208
210
|
'error',
|
package/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
2
|
import {ESLint} from 'eslint';
|
|
3
3
|
import {globby, isGitIgnoredSync} from 'globby';
|
|
4
|
-
import {isEqual} from 'lodash-es';
|
|
4
|
+
import {isEqual, groupBy} from 'lodash-es';
|
|
5
5
|
import micromatch from 'micromatch';
|
|
6
6
|
import arrify from 'arrify';
|
|
7
7
|
import slash from 'slash';
|
|
@@ -12,30 +12,6 @@ import {
|
|
|
12
12
|
} from './lib/options-manager.js';
|
|
13
13
|
import {mergeReports, processReport, getIgnoredReport} from './lib/report.js';
|
|
14
14
|
|
|
15
|
-
const runEslint = async (lint, options) => {
|
|
16
|
-
const {filePath, eslintOptions, isQuiet} = options;
|
|
17
|
-
const {cwd, baseConfig: {ignorePatterns}} = eslintOptions;
|
|
18
|
-
|
|
19
|
-
if (
|
|
20
|
-
filePath
|
|
21
|
-
&& (
|
|
22
|
-
micromatch.isMatch(path.relative(cwd, filePath), ignorePatterns)
|
|
23
|
-
|| isGitIgnoredSync({cwd, ignore: ignorePatterns})(filePath)
|
|
24
|
-
)
|
|
25
|
-
) {
|
|
26
|
-
return getIgnoredReport(filePath);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const eslint = new ESLint(eslintOptions);
|
|
30
|
-
|
|
31
|
-
if (filePath && await eslint.isPathIgnored(filePath)) {
|
|
32
|
-
return getIgnoredReport(filePath);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const report = await lint(eslint);
|
|
36
|
-
return processReport(report, {isQuiet});
|
|
37
|
-
};
|
|
38
|
-
|
|
39
15
|
const globFiles = async (patterns, options) => {
|
|
40
16
|
const {ignores, extensions, cwd} = (await mergeWithFileConfig(options)).options;
|
|
41
17
|
|
|
@@ -59,32 +35,76 @@ const getConfig = async options => {
|
|
|
59
35
|
|
|
60
36
|
const lintText = async (string, options) => {
|
|
61
37
|
options = await parseOptions(options);
|
|
62
|
-
const {filePath, warnIgnored, eslintOptions} = options;
|
|
63
|
-
const {ignorePatterns} = eslintOptions
|
|
38
|
+
const {filePath, warnIgnored, eslintOptions, isQuiet} = options;
|
|
39
|
+
const {cwd, baseConfig: {ignorePatterns}} = eslintOptions;
|
|
64
40
|
|
|
65
41
|
if (typeof filePath !== 'string' && !isEqual(getIgnores({}), ignorePatterns)) {
|
|
66
42
|
throw new Error('The `ignores` option requires the `filePath` option to be defined.');
|
|
67
43
|
}
|
|
68
44
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
45
|
+
if (
|
|
46
|
+
filePath
|
|
47
|
+
&& (
|
|
48
|
+
micromatch.isMatch(path.relative(cwd, filePath), ignorePatterns)
|
|
49
|
+
|| isGitIgnoredSync({cwd, ignore: ignorePatterns})(filePath)
|
|
50
|
+
)
|
|
51
|
+
) {
|
|
52
|
+
return getIgnoredReport(filePath);
|
|
53
|
+
}
|
|
74
54
|
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
await
|
|
78
|
-
);
|
|
55
|
+
const eslint = new ESLint(eslintOptions);
|
|
56
|
+
|
|
57
|
+
if (filePath && await eslint.isPathIgnored(filePath)) {
|
|
58
|
+
return getIgnoredReport(filePath);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const report = await eslint.lintText(string, {filePath, warnIgnored});
|
|
62
|
+
return processReport(report, {isQuiet});
|
|
63
|
+
};
|
|
79
64
|
|
|
80
65
|
const lintFiles = async (patterns, options) => {
|
|
81
66
|
const files = await globFiles(patterns, options);
|
|
82
67
|
|
|
83
|
-
const
|
|
84
|
-
files.map(filePath =>
|
|
68
|
+
const allOptions = await Promise.all(
|
|
69
|
+
files.map(filePath => parseOptions({...options, filePath})),
|
|
85
70
|
);
|
|
86
71
|
|
|
87
|
-
|
|
72
|
+
// Files with same `xoConfigPath` can lint together
|
|
73
|
+
// https://github.com/xojs/xo/issues/599
|
|
74
|
+
const groups = groupBy(allOptions, 'eslintConfigId');
|
|
75
|
+
|
|
76
|
+
const reports = await Promise.all(
|
|
77
|
+
Object.values(groups)
|
|
78
|
+
.map(async filesWithOptions => {
|
|
79
|
+
const options = filesWithOptions[0];
|
|
80
|
+
const eslint = new ESLint(options.eslintOptions);
|
|
81
|
+
const files = [];
|
|
82
|
+
|
|
83
|
+
for (const options of filesWithOptions) {
|
|
84
|
+
const {filePath, eslintOptions} = options;
|
|
85
|
+
const {cwd, baseConfig: {ignorePatterns}} = eslintOptions;
|
|
86
|
+
if (filePath
|
|
87
|
+
&& (
|
|
88
|
+
micromatch.isMatch(path.relative(cwd, filePath), ignorePatterns)
|
|
89
|
+
|| isGitIgnoredSync({cwd, ignore: ignorePatterns})(filePath)
|
|
90
|
+
)) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// eslint-disable-next-line no-await-in-loop
|
|
95
|
+
if ((await eslint.isPathIgnored(filePath))) {
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
files.push(filePath);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const report = await eslint.lintFiles(files);
|
|
103
|
+
|
|
104
|
+
return processReport(report, {isQuiet: options.isQuiet});
|
|
105
|
+
}));
|
|
106
|
+
|
|
107
|
+
const report = mergeReports(reports);
|
|
88
108
|
|
|
89
109
|
return report;
|
|
90
110
|
};
|
package/lib/constants.js
CHANGED
|
@@ -106,13 +106,6 @@ const ENGINE_RULES = {
|
|
|
106
106
|
},
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
const PRETTIER_CONFIG_OVERRIDE = {
|
|
110
|
-
'eslint-plugin-babel': 'prettier/babel',
|
|
111
|
-
'eslint-plugin-flowtype': 'prettier/flowtype',
|
|
112
|
-
'eslint-plugin-standard': 'prettier/standard',
|
|
113
|
-
'eslint-plugin-vue': 'prettier/vue',
|
|
114
|
-
};
|
|
115
|
-
|
|
116
109
|
const MODULE_NAME = 'xo';
|
|
117
110
|
|
|
118
111
|
const CONFIG_FILES = [
|
|
@@ -144,7 +137,6 @@ export {
|
|
|
144
137
|
DEFAULT_EXTENSION,
|
|
145
138
|
TYPESCRIPT_EXTENSION,
|
|
146
139
|
ENGINE_RULES,
|
|
147
|
-
PRETTIER_CONFIG_OVERRIDE,
|
|
148
140
|
MODULE_NAME,
|
|
149
141
|
CONFIG_FILES,
|
|
150
142
|
MERGE_OPTIONS_CONCAT,
|
package/lib/options-manager.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
+
import {existsSync, promises as fs} from 'node:fs';
|
|
1
2
|
import process from 'node:process';
|
|
2
3
|
import os from 'node:os';
|
|
3
4
|
import path from 'node:path';
|
|
4
|
-
import fsExtra from 'fs-extra';
|
|
5
5
|
import arrify from 'arrify';
|
|
6
6
|
import {mergeWith, flow, pick} from 'lodash-es';
|
|
7
|
-
import
|
|
8
|
-
import findUp from 'find-up';
|
|
7
|
+
import {findUpSync} from 'find-up';
|
|
9
8
|
import findCacheDir from 'find-cache-dir';
|
|
10
9
|
import prettier from 'prettier';
|
|
11
10
|
import semver from 'semver';
|
|
@@ -22,7 +21,6 @@ import {
|
|
|
22
21
|
DEFAULT_EXTENSION,
|
|
23
22
|
TYPESCRIPT_EXTENSION,
|
|
24
23
|
ENGINE_RULES,
|
|
25
|
-
PRETTIER_CONFIG_OVERRIDE,
|
|
26
24
|
MODULE_NAME,
|
|
27
25
|
CONFIG_FILES,
|
|
28
26
|
MERGE_OPTIONS_CONCAT,
|
|
@@ -52,6 +50,7 @@ const DEFAULT_CONFIG = {
|
|
|
52
50
|
cache: true,
|
|
53
51
|
cacheLocation: path.join(cacheLocation(), 'xo-cache.json'),
|
|
54
52
|
globInputPaths: false,
|
|
53
|
+
resolvePluginsRelativeTo: __dirname,
|
|
55
54
|
baseConfig: {
|
|
56
55
|
extends: [
|
|
57
56
|
resolveLocalConfig('xo'),
|
|
@@ -117,22 +116,57 @@ const mergeWithFileConfig = async options => {
|
|
|
117
116
|
options = mergeOptions(options, xoOptions, enginesOptions);
|
|
118
117
|
options.cwd = xoConfigPath && path.dirname(xoConfigPath) !== options.cwd ? path.resolve(options.cwd, path.dirname(xoConfigPath)) : options.cwd;
|
|
119
118
|
|
|
119
|
+
// Very simple way to ensure eslint is ran minimal times across
|
|
120
|
+
// all linted files, once for each unique configuration - xo config path + override hash + tsconfig path
|
|
121
|
+
let eslintConfigId = xoConfigPath;
|
|
120
122
|
if (options.filePath) {
|
|
121
|
-
|
|
123
|
+
const overrides = applyOverrides(options.filePath, options);
|
|
124
|
+
options = overrides.options;
|
|
125
|
+
|
|
126
|
+
if (overrides.hash) {
|
|
127
|
+
eslintConfigId += overrides.hash;
|
|
128
|
+
}
|
|
122
129
|
}
|
|
123
130
|
|
|
124
131
|
const prettierOptions = options.prettier ? await prettier.resolveConfig(searchPath, {editorconfig: true}) || {} : {};
|
|
125
132
|
|
|
126
133
|
if (options.filePath && isTypescript(options.filePath)) {
|
|
127
|
-
|
|
128
|
-
|
|
134
|
+
// We can skip looking up the tsconfig if we have it defined
|
|
135
|
+
// in our parser options already. Otherwise we can look it up and create it as normal
|
|
136
|
+
const {project: tsConfigProjectPath, tsconfigRootDir} = options.parserOptions || {};
|
|
137
|
+
|
|
138
|
+
let tsConfig;
|
|
139
|
+
let tsConfigPath;
|
|
140
|
+
if (tsConfigProjectPath) {
|
|
141
|
+
tsConfigPath = path.resolve(options.cwd, tsConfigProjectPath);
|
|
142
|
+
tsConfig = await json.load(tsConfigPath);
|
|
143
|
+
} else {
|
|
144
|
+
const tsConfigExplorer = cosmiconfig([], {
|
|
145
|
+
searchPlaces: ['tsconfig.json'],
|
|
146
|
+
loaders: {'.json': (_, content) => JSON5.parse(content)},
|
|
147
|
+
stopDir: tsconfigRootDir,
|
|
148
|
+
});
|
|
149
|
+
const searchResults = (await tsConfigExplorer.search(options.filePath)) || {};
|
|
150
|
+
tsConfigPath = searchResults.filepath;
|
|
151
|
+
tsConfig = searchResults.config;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (tsConfigPath) {
|
|
155
|
+
options.tsConfigPath = tsConfigPath;
|
|
156
|
+
eslintConfigId += tsConfigPath;
|
|
157
|
+
} else {
|
|
158
|
+
const {path: tsConfigCachePath, hash: tsConfigHash} = await getTsConfigCachePath([eslintConfigId], tsConfigPath, options.cwd);
|
|
159
|
+
eslintConfigId += tsConfigHash;
|
|
160
|
+
options.tsConfigPath = tsConfigCachePath;
|
|
161
|
+
const config = makeTSConfig(tsConfig, tsConfigPath, [options.filePath]);
|
|
162
|
+
await fs.mkdir(path.dirname(options.tsConfigPath), {recursive: true});
|
|
163
|
+
await fs.writeFile(options.tsConfigPath, JSON.stringify(config));
|
|
164
|
+
}
|
|
129
165
|
|
|
130
|
-
options.tsConfigPath = await getTsConfigCachePath([options.filePath], options.tsConfigPath, options.cwd);
|
|
131
166
|
options.ts = true;
|
|
132
|
-
await fsExtra.outputJson(options.tsConfigPath, makeTSConfig(tsConfig, tsConfigPath, [options.filePath]));
|
|
133
167
|
}
|
|
134
168
|
|
|
135
|
-
return {options, prettierOptions};
|
|
169
|
+
return {options, prettierOptions, eslintConfigId};
|
|
136
170
|
};
|
|
137
171
|
|
|
138
172
|
/**
|
|
@@ -141,10 +175,14 @@ Hashing based on https://github.com/eslint/eslint/blob/cf38d0d939b62f3670cdd59f0
|
|
|
141
175
|
*/
|
|
142
176
|
const getTsConfigCachePath = async (files, tsConfigPath, cwd) => {
|
|
143
177
|
const {version} = await json.load('../package.json');
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
178
|
+
const tsConfigHash = murmur(`${version}_${nodeVersion}_${stringify({files: files.sort(), tsConfigPath})}`).result().toString(36);
|
|
179
|
+
return {
|
|
180
|
+
path: path.join(
|
|
181
|
+
cacheLocation(cwd),
|
|
182
|
+
`tsconfig.${tsConfigHash}.json`,
|
|
183
|
+
),
|
|
184
|
+
hash: tsConfigHash,
|
|
185
|
+
};
|
|
148
186
|
};
|
|
149
187
|
|
|
150
188
|
const makeTSConfig = (tsConfig, tsConfigPath, files) => {
|
|
@@ -207,7 +245,7 @@ const mergeOptions = (options, xoOptions = {}, enginesOptions = {}) => {
|
|
|
207
245
|
...options,
|
|
208
246
|
});
|
|
209
247
|
|
|
210
|
-
mergedOptions.extensions = DEFAULT_EXTENSION
|
|
248
|
+
mergedOptions.extensions = [...DEFAULT_EXTENSION, ...(mergedOptions.extensions || [])];
|
|
211
249
|
mergedOptions.ignores = getIgnores(mergedOptions);
|
|
212
250
|
|
|
213
251
|
return mergedOptions;
|
|
@@ -350,6 +388,10 @@ const buildXOConfig = options => config => {
|
|
|
350
388
|
|
|
351
389
|
// Does not work when the TS definition exports a default const.
|
|
352
390
|
config.baseConfig.rules['import/default'] = 'off';
|
|
391
|
+
|
|
392
|
+
// Disabled as it doesn't work with TypeScript.
|
|
393
|
+
// This issue and some others: https://github.com/benmosher/eslint-plugin-import/issues/1341
|
|
394
|
+
config.baseConfig.rules['import/named'] = 'off';
|
|
353
395
|
}
|
|
354
396
|
|
|
355
397
|
config.baseConfig.settings['import/resolver'] = gatherImportResolvers(options);
|
|
@@ -361,7 +403,7 @@ const buildExtendsConfig = options => config => {
|
|
|
361
403
|
if (options.extends && options.extends.length > 0) {
|
|
362
404
|
const configs = options.extends.map(name => {
|
|
363
405
|
// Don't do anything if it's a filepath
|
|
364
|
-
if (
|
|
406
|
+
if (existsSync(name)) {
|
|
365
407
|
return name;
|
|
366
408
|
}
|
|
367
409
|
|
|
@@ -390,19 +432,11 @@ const buildPrettierConfig = (options, prettierConfig) => config => {
|
|
|
390
432
|
// The prettier plugin uses Prettier to format the code with `--fix`
|
|
391
433
|
config.baseConfig.plugins.push('prettier');
|
|
392
434
|
|
|
393
|
-
// The prettier
|
|
394
|
-
config.baseConfig.extends.push('prettier');
|
|
435
|
+
// The prettier plugin overrides ESLint stylistic rules that are handled by Prettier
|
|
436
|
+
config.baseConfig.extends.push('plugin:prettier/recommended');
|
|
395
437
|
|
|
396
438
|
// The `prettier/prettier` rule reports errors if the code is not formatted in accordance to Prettier
|
|
397
439
|
config.baseConfig.rules['prettier/prettier'] = ['error', mergeWithPrettierConfig(options, prettierConfig)];
|
|
398
|
-
|
|
399
|
-
// If the user has the React, Flowtype, or Standard plugin, add the corresponding Prettier rule overrides
|
|
400
|
-
// See https://github.com/prettier/eslint-config-prettier for the list of plugins overrrides
|
|
401
|
-
for (const [plugin, prettierConfig] of Object.entries(PRETTIER_CONFIG_OVERRIDE)) {
|
|
402
|
-
if (options.cwd && resolveFrom.silent(plugin, options.cwd)) {
|
|
403
|
-
config.baseConfig.extends.push(prettierConfig);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
440
|
}
|
|
407
441
|
|
|
408
442
|
return config;
|
|
@@ -428,7 +462,7 @@ const mergeWithPrettierConfig = (options, prettierOptions) => {
|
|
|
428
462
|
{
|
|
429
463
|
singleQuote: true,
|
|
430
464
|
bracketSpacing: false,
|
|
431
|
-
|
|
465
|
+
bracketSameLine: false,
|
|
432
466
|
trailingComma: 'all',
|
|
433
467
|
tabWidth: normalizeSpaces(options),
|
|
434
468
|
useTabs: !options.space,
|
|
@@ -441,7 +475,7 @@ const mergeWithPrettierConfig = (options, prettierOptions) => {
|
|
|
441
475
|
|
|
442
476
|
const buildTSConfig = options => config => {
|
|
443
477
|
if (options.ts) {
|
|
444
|
-
config.baseConfig.extends.push('xo-typescript');
|
|
478
|
+
config.baseConfig.extends.push(require.resolve('eslint-config-xo-typescript'));
|
|
445
479
|
config.baseConfig.parser = require.resolve('@typescript-eslint/parser');
|
|
446
480
|
config.baseConfig.parserOptions = {
|
|
447
481
|
...config.baseConfig.parserOptions,
|
|
@@ -487,11 +521,11 @@ const findApplicableOverrides = (path, overrides) => {
|
|
|
487
521
|
const applicable = [];
|
|
488
522
|
|
|
489
523
|
for (const override of overrides) {
|
|
490
|
-
hash <<= 1;
|
|
524
|
+
hash <<= 1; // eslint-disable-line no-bitwise
|
|
491
525
|
|
|
492
526
|
if (micromatch.isMatch(path, override.files)) {
|
|
493
527
|
applicable.push(override);
|
|
494
|
-
hash |= 1;
|
|
528
|
+
hash |= 1; // eslint-disable-line no-bitwise
|
|
495
529
|
}
|
|
496
530
|
}
|
|
497
531
|
|
|
@@ -501,7 +535,7 @@ const findApplicableOverrides = (path, overrides) => {
|
|
|
501
535
|
};
|
|
502
536
|
};
|
|
503
537
|
|
|
504
|
-
const getIgnores = ({ignores}) => DEFAULT_IGNORES
|
|
538
|
+
const getIgnores = ({ignores}) => [...DEFAULT_IGNORES, ...(ignores || [])];
|
|
505
539
|
|
|
506
540
|
const gatherImportResolvers = options => {
|
|
507
541
|
let resolvers = {};
|
|
@@ -521,7 +555,7 @@ const gatherImportResolvers = options => {
|
|
|
521
555
|
webpackResolverSettings = options.webpack === true ? {} : options.webpack;
|
|
522
556
|
} else if (!(options.webpack === false || resolvers.webpack)) {
|
|
523
557
|
// If a webpack config file exists, add the import resolver automatically
|
|
524
|
-
const webpackConfigPath =
|
|
558
|
+
const webpackConfigPath = findUpSync('webpack.config.js', {cwd: options.cwd});
|
|
525
559
|
if (webpackConfigPath) {
|
|
526
560
|
webpackResolverSettings = {config: webpackConfigPath};
|
|
527
561
|
}
|
|
@@ -542,13 +576,14 @@ const gatherImportResolvers = options => {
|
|
|
542
576
|
|
|
543
577
|
const parseOptions = async options => {
|
|
544
578
|
options = normalizeOptions(options);
|
|
545
|
-
const {options: foundOptions, prettierOptions} = await mergeWithFileConfig(options);
|
|
579
|
+
const {options: foundOptions, prettierOptions, eslintConfigId} = await mergeWithFileConfig(options);
|
|
546
580
|
const {filePath, warnIgnored, ...eslintOptions} = buildConfig(foundOptions, prettierOptions);
|
|
547
581
|
return {
|
|
548
582
|
filePath,
|
|
549
583
|
warnIgnored,
|
|
550
584
|
isQuiet: options.quiet,
|
|
551
585
|
eslintOptions,
|
|
586
|
+
eslintConfigId,
|
|
552
587
|
};
|
|
553
588
|
};
|
|
554
589
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xo",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.2",
|
|
4
4
|
"description": "JavaScript/TypeScript linter (ESLint wrapper) with great defaults",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "xojs/xo",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"node": ">=12.20"
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
|
+
"test:clean": "find ./test -type d -name 'node_modules' -prune -not -path ./test/fixtures/project/node_modules -exec rm -rf '{}' +",
|
|
19
20
|
"test": "node cli.js && nyc ava"
|
|
20
21
|
},
|
|
21
22
|
"files": [
|
|
@@ -51,59 +52,59 @@
|
|
|
51
52
|
"javascript",
|
|
52
53
|
"typescript"
|
|
53
54
|
],
|
|
55
|
+
"bundledDependencies": [
|
|
56
|
+
"@typescript-eslint/eslint-plugin",
|
|
57
|
+
"@typescript-eslint/parser",
|
|
58
|
+
"eslint-config-xo-typescript"
|
|
59
|
+
],
|
|
54
60
|
"dependencies": {
|
|
55
|
-
"@eslint/eslintrc": "^1.0.
|
|
56
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
57
|
-
"@typescript-eslint/parser": "^
|
|
61
|
+
"@eslint/eslintrc": "^1.0.3",
|
|
62
|
+
"@typescript-eslint/eslint-plugin": "^5.2.0",
|
|
63
|
+
"@typescript-eslint/parser": "^5.2.0",
|
|
58
64
|
"arrify": "^3.0.0",
|
|
59
|
-
"cosmiconfig": "^7.0.
|
|
60
|
-
"debug": "^4.3.2",
|
|
65
|
+
"cosmiconfig": "^7.0.1",
|
|
61
66
|
"define-lazy-prop": "^3.0.0",
|
|
62
|
-
"eslint": "^
|
|
67
|
+
"eslint": "^8.1.0",
|
|
63
68
|
"eslint-config-prettier": "^8.3.0",
|
|
64
|
-
"eslint-config-xo": "^0.
|
|
65
|
-
"eslint-config-xo-typescript": "^0.
|
|
69
|
+
"eslint-config-xo": "^0.39.0",
|
|
70
|
+
"eslint-config-xo-typescript": "^0.47.1",
|
|
66
71
|
"eslint-formatter-pretty": "^4.1.0",
|
|
67
|
-
"eslint-import-resolver-webpack": "^0.13.
|
|
68
|
-
"eslint-plugin-ava": "^
|
|
72
|
+
"eslint-import-resolver-webpack": "^0.13.2",
|
|
73
|
+
"eslint-plugin-ava": "^13.1.0",
|
|
69
74
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
70
|
-
"eslint-plugin-import": "^2.
|
|
75
|
+
"eslint-plugin-import": "^2.25.2",
|
|
71
76
|
"eslint-plugin-no-use-extend-native": "^0.5.0",
|
|
72
77
|
"eslint-plugin-node": "^11.1.0",
|
|
73
|
-
"eslint-plugin-prettier": "^
|
|
74
|
-
"eslint-plugin-
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"find-
|
|
78
|
-
"find-up": "^5.0.0",
|
|
79
|
-
"fs-extra": "^10.0.0",
|
|
78
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
79
|
+
"eslint-plugin-unicorn": "^37.0.1",
|
|
80
|
+
"esm-utils": "^2.0.0",
|
|
81
|
+
"find-cache-dir": "^3.3.2",
|
|
82
|
+
"find-up": "^6.2.0",
|
|
80
83
|
"get-stdin": "^9.0.0",
|
|
81
|
-
"globby": "^12.0.
|
|
84
|
+
"globby": "^12.0.2",
|
|
82
85
|
"imurmurhash": "^0.1.4",
|
|
83
|
-
"is-path-inside": "^4.0.0",
|
|
84
86
|
"json-stable-stringify-without-jsonify": "^1.0.1",
|
|
85
87
|
"json5": "^2.2.0",
|
|
86
88
|
"lodash-es": "^4.17.21",
|
|
87
89
|
"meow": "^10.1.1",
|
|
88
90
|
"micromatch": "^4.0.4",
|
|
89
91
|
"open-editor": "^3.0.0",
|
|
90
|
-
"
|
|
91
|
-
"prettier": "^2.3.2",
|
|
92
|
+
"prettier": "^2.4.1",
|
|
92
93
|
"semver": "^7.3.5",
|
|
93
94
|
"slash": "^4.0.0",
|
|
94
95
|
"to-absolute-glob": "^2.0.2",
|
|
95
|
-
"typescript": "^4.
|
|
96
|
+
"typescript": "^4.4.4"
|
|
96
97
|
},
|
|
97
98
|
"devDependencies": {
|
|
98
99
|
"ava": "^3.15.0",
|
|
99
100
|
"eslint-config-xo-react": "^0.25.0",
|
|
100
|
-
"eslint-plugin-react": "^7.
|
|
101
|
+
"eslint-plugin-react": "^7.26.1",
|
|
101
102
|
"eslint-plugin-react-hooks": "^4.2.0",
|
|
102
103
|
"execa": "^5.1.1",
|
|
103
104
|
"nyc": "^15.1.0",
|
|
104
105
|
"proxyquire": "^2.1.3",
|
|
105
106
|
"temp-write": "^5.0.0",
|
|
106
|
-
"webpack": "^5.
|
|
107
|
+
"webpack": "^5.60.0"
|
|
107
108
|
},
|
|
108
109
|
"xo": {
|
|
109
110
|
"ignores": [
|
package/readme.md
CHANGED
|
@@ -169,14 +169,14 @@ module.exports = {
|
|
|
169
169
|
};
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
[Globals](https://eslint.org/docs/user-guide/configuring#specifying-globals) and [rules](https://eslint.org/docs/user-guide/configuring#configuring-rules) can be configured inline in files.
|
|
172
|
+
[Globals](https://eslint.org/docs/user-guide/configuring/language-options#specifying-globals) and [rules](https://eslint.org/docs/user-guide/configuring/rules#configuring-rules) can be configured inline in files.
|
|
173
173
|
|
|
174
174
|
### envs
|
|
175
175
|
|
|
176
176
|
Type: `string[]`\
|
|
177
177
|
Default: `['es2021', 'node']`
|
|
178
178
|
|
|
179
|
-
Which [environments](https://eslint.org/docs/user-guide/configuring#specifying-environments) your code is designed to run in. Each environment brings with it a certain set of predefined global variables.
|
|
179
|
+
Which [environments](https://eslint.org/docs/user-guide/configuring/language-options#specifying-environments) your code is designed to run in. Each environment brings with it a certain set of predefined global variables.
|
|
180
180
|
|
|
181
181
|
### globals
|
|
182
182
|
|
|
@@ -188,7 +188,7 @@ Additional global variables your code accesses during execution.
|
|
|
188
188
|
|
|
189
189
|
Type: `string[]`
|
|
190
190
|
|
|
191
|
-
Some [paths](lib/options-manager.js) are ignored by default, including paths in `.gitignore` and [.eslintignore](https://eslint.org/docs/user-guide/configuring#eslintignore). Additional ignores can be added here.
|
|
191
|
+
Some [paths](lib/options-manager.js) are ignored by default, including paths in `.gitignore` and [.eslintignore](https://eslint.org/docs/user-guide/configuring/ignoring-code#the-eslintignore-file). Additional ignores can be added here.
|
|
192
192
|
|
|
193
193
|
### space
|
|
194
194
|
|
|
@@ -221,14 +221,23 @@ Default: `false`
|
|
|
221
221
|
|
|
222
222
|
Format code with [Prettier](https://github.com/prettier/prettier).
|
|
223
223
|
|
|
224
|
-
|
|
224
|
+
[Prettier options](https://prettier.io/docs/en/options.html) will be based on your [Prettier config](https://prettier.io/docs/en/configuration.html). XO will then **merge** your options with its own defaults:
|
|
225
225
|
- [semi](https://prettier.io/docs/en/options.html#semicolons): based on [semicolon](#semicolon) option
|
|
226
226
|
- [useTabs](https://prettier.io/docs/en/options.html#tabs): based on [space](#space) option
|
|
227
227
|
- [tabWidth](https://prettier.io/docs/en/options.html#tab-width): based on [space](#space) option
|
|
228
228
|
- [trailingComma](https://prettier.io/docs/en/options.html#trailing-commas): `all`
|
|
229
229
|
- [singleQuote](https://prettier.io/docs/en/options.html#quotes): `true`
|
|
230
230
|
- [bracketSpacing](https://prettier.io/docs/en/options.html#bracket-spacing): `false`
|
|
231
|
-
|
|
231
|
+
|
|
232
|
+
To stick with Prettier's defaults, add this to your Prettier config:
|
|
233
|
+
|
|
234
|
+
```js
|
|
235
|
+
module.exports = {
|
|
236
|
+
trailingComma: 'es5',
|
|
237
|
+
singleQuote: false,
|
|
238
|
+
bracketSpacing: true,
|
|
239
|
+
};
|
|
240
|
+
```
|
|
232
241
|
|
|
233
242
|
If contradicting options are set for both Prettier and XO an error will be thrown.
|
|
234
243
|
|
|
@@ -245,13 +254,13 @@ If set to `false`, no rules specific to a Node.js version will be enabled.
|
|
|
245
254
|
|
|
246
255
|
Type: `string[]`
|
|
247
256
|
|
|
248
|
-
Include third-party [plugins](https://eslint.org/docs/user-guide/configuring
|
|
257
|
+
Include third-party [plugins](https://eslint.org/docs/user-guide/configuring/plugins#configuring-plugins).
|
|
249
258
|
|
|
250
259
|
### extends
|
|
251
260
|
|
|
252
261
|
Type: `string | string[]`
|
|
253
262
|
|
|
254
|
-
Use one or more [shareable configs](https://eslint.org/docs/developer-guide/shareable-configs
|
|
263
|
+
Use one or more [shareable configs](https://eslint.org/docs/developer-guide/shareable-configs) or [plugin configs](https://eslint.org/docs/user-guide/configuring/configuration-files#using-a-configuration-from-a-plugin) to override any of the default rules (like `rules` above).
|
|
255
264
|
|
|
256
265
|
### extensions
|
|
257
266
|
|
|
@@ -263,7 +272,7 @@ Allow more extensions to be linted besides `.js`, `.jsx`, `.mjs`, and `.cjs`. Ma
|
|
|
263
272
|
|
|
264
273
|
Type: `object`
|
|
265
274
|
|
|
266
|
-
[Shared ESLint settings](https://eslint.org/docs/user-guide/configuring#adding-shared-settings) exposed to rules.
|
|
275
|
+
[Shared ESLint settings](https://eslint.org/docs/user-guide/configuring/configuration-files#adding-shared-settings) exposed to rules.
|
|
267
276
|
|
|
268
277
|
### parser
|
|
269
278
|
|
|
@@ -275,7 +284,7 @@ ESLint parser. For example, [`@babel/eslint-parser`](https://github.com/babel/ba
|
|
|
275
284
|
|
|
276
285
|
Type: `string`
|
|
277
286
|
|
|
278
|
-
[ESLint processor.](https://eslint.org/docs/user-guide/configuring#specifying-processor)
|
|
287
|
+
[ESLint processor.](https://eslint.org/docs/user-guide/configuring/plugins#specifying-processor)
|
|
279
288
|
|
|
280
289
|
### webpack
|
|
281
290
|
|