source: imaps-frontend/node_modules/@eslint/eslintrc/dist/eslintrc.cjs@ d565449

main
Last change on this file since d565449 was d565449, checked in by stefan toskovski <stefantoska84@…>, 4 weeks ago

Update repo after prototype presentation

  • Property mode set to 100644
File size: 144.3 KB
Line 
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var debugOrig = require('debug');
6var fs = require('fs');
7var importFresh = require('import-fresh');
8var Module = require('module');
9var path = require('path');
10var stripComments = require('strip-json-comments');
11var assert = require('assert');
12var ignore = require('ignore');
13var util = require('util');
14var minimatch = require('minimatch');
15var Ajv = require('ajv');
16var globals = require('globals');
17var os = require('os');
18
19function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
20
21var debugOrig__default = /*#__PURE__*/_interopDefaultLegacy(debugOrig);
22var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
23var importFresh__default = /*#__PURE__*/_interopDefaultLegacy(importFresh);
24var Module__default = /*#__PURE__*/_interopDefaultLegacy(Module);
25var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
26var stripComments__default = /*#__PURE__*/_interopDefaultLegacy(stripComments);
27var assert__default = /*#__PURE__*/_interopDefaultLegacy(assert);
28var ignore__default = /*#__PURE__*/_interopDefaultLegacy(ignore);
29var util__default = /*#__PURE__*/_interopDefaultLegacy(util);
30var minimatch__default = /*#__PURE__*/_interopDefaultLegacy(minimatch);
31var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
32var globals__default = /*#__PURE__*/_interopDefaultLegacy(globals);
33var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
34
35/**
36 * @fileoverview `IgnorePattern` class.
37 *
38 * `IgnorePattern` class has the set of glob patterns and the base path.
39 *
40 * It provides two static methods.
41 *
42 * - `IgnorePattern.createDefaultIgnore(cwd)`
43 * Create the default predicate function.
44 * - `IgnorePattern.createIgnore(ignorePatterns)`
45 * Create the predicate function from multiple `IgnorePattern` objects.
46 *
47 * It provides two properties and a method.
48 *
49 * - `patterns`
50 * The glob patterns that ignore to lint.
51 * - `basePath`
52 * The base path of the glob patterns. If absolute paths existed in the
53 * glob patterns, those are handled as relative paths to the base path.
54 * - `getPatternsRelativeTo(basePath)`
55 * Get `patterns` as modified for a given base path. It modifies the
56 * absolute paths in the patterns as prepending the difference of two base
57 * paths.
58 *
59 * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
60 * `ignorePatterns` properties.
61 *
62 * @author Toru Nagashima <https://github.com/mysticatea>
63 */
64
65const debug$3 = debugOrig__default["default"]("eslintrc:ignore-pattern");
66
67/** @typedef {ReturnType<import("ignore").default>} Ignore */
68
69//------------------------------------------------------------------------------
70// Helpers
71//------------------------------------------------------------------------------
72
73/**
74 * Get the path to the common ancestor directory of given paths.
75 * @param {string[]} sourcePaths The paths to calculate the common ancestor.
76 * @returns {string} The path to the common ancestor directory.
77 */
78function getCommonAncestorPath(sourcePaths) {
79 let result = sourcePaths[0];
80
81 for (let i = 1; i < sourcePaths.length; ++i) {
82 const a = result;
83 const b = sourcePaths[i];
84
85 // Set the shorter one (it's the common ancestor if one includes the other).
86 result = a.length < b.length ? a : b;
87
88 // Set the common ancestor.
89 for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
90 if (a[j] !== b[j]) {
91 result = a.slice(0, lastSepPos);
92 break;
93 }
94 if (a[j] === path__default["default"].sep) {
95 lastSepPos = j;
96 }
97 }
98 }
99
100 let resolvedResult = result || path__default["default"].sep;
101
102 // if Windows common ancestor is root of drive must have trailing slash to be absolute.
103 if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
104 resolvedResult += path__default["default"].sep;
105 }
106 return resolvedResult;
107}
108
109/**
110 * Make relative path.
111 * @param {string} from The source path to get relative path.
112 * @param {string} to The destination path to get relative path.
113 * @returns {string} The relative path.
114 */
115function relative(from, to) {
116 const relPath = path__default["default"].relative(from, to);
117
118 if (path__default["default"].sep === "/") {
119 return relPath;
120 }
121 return relPath.split(path__default["default"].sep).join("/");
122}
123
124/**
125 * Get the trailing slash if existed.
126 * @param {string} filePath The path to check.
127 * @returns {string} The trailing slash if existed.
128 */
129function dirSuffix(filePath) {
130 const isDir = (
131 filePath.endsWith(path__default["default"].sep) ||
132 (process.platform === "win32" && filePath.endsWith("/"))
133 );
134
135 return isDir ? "/" : "";
136}
137
138const DefaultPatterns = Object.freeze(["/**/node_modules/*"]);
139const DotPatterns = Object.freeze([".*", "!.eslintrc.*", "!../"]);
140
141//------------------------------------------------------------------------------
142// Public
143//------------------------------------------------------------------------------
144
145class IgnorePattern {
146
147 /**
148 * The default patterns.
149 * @type {string[]}
150 */
151 static get DefaultPatterns() {
152 return DefaultPatterns;
153 }
154
155 /**
156 * Create the default predicate function.
157 * @param {string} cwd The current working directory.
158 * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
159 * The preficate function.
160 * The first argument is an absolute path that is checked.
161 * The second argument is the flag to not ignore dotfiles.
162 * If the predicate function returned `true`, it means the path should be ignored.
163 */
164 static createDefaultIgnore(cwd) {
165 return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
166 }
167
168 /**
169 * Create the predicate function from multiple `IgnorePattern` objects.
170 * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
171 * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
172 * The preficate function.
173 * The first argument is an absolute path that is checked.
174 * The second argument is the flag to not ignore dotfiles.
175 * If the predicate function returned `true`, it means the path should be ignored.
176 */
177 static createIgnore(ignorePatterns) {
178 debug$3("Create with: %o", ignorePatterns);
179
180 const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
181 const patterns = [].concat(
182 ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
183 );
184 const ig = ignore__default["default"]({ allowRelativePaths: true }).add([...DotPatterns, ...patterns]);
185 const dotIg = ignore__default["default"]({ allowRelativePaths: true }).add(patterns);
186
187 debug$3(" processed: %o", { basePath, patterns });
188
189 return Object.assign(
190 (filePath, dot = false) => {
191 assert__default["default"](path__default["default"].isAbsolute(filePath), "'filePath' should be an absolute path.");
192 const relPathRaw = relative(basePath, filePath);
193 const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
194 const adoptedIg = dot ? dotIg : ig;
195 const result = relPath !== "" && adoptedIg.ignores(relPath);
196
197 debug$3("Check", { filePath, dot, relativePath: relPath, result });
198 return result;
199 },
200 { basePath, patterns }
201 );
202 }
203
204 /**
205 * Initialize a new `IgnorePattern` instance.
206 * @param {string[]} patterns The glob patterns that ignore to lint.
207 * @param {string} basePath The base path of `patterns`.
208 */
209 constructor(patterns, basePath) {
210 assert__default["default"](path__default["default"].isAbsolute(basePath), "'basePath' should be an absolute path.");
211
212 /**
213 * The glob patterns that ignore to lint.
214 * @type {string[]}
215 */
216 this.patterns = patterns;
217
218 /**
219 * The base path of `patterns`.
220 * @type {string}
221 */
222 this.basePath = basePath;
223
224 /**
225 * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
226 *
227 * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
228 * It's `false` as-is for `ignorePatterns` property in config files.
229 * @type {boolean}
230 */
231 this.loose = false;
232 }
233
234 /**
235 * Get `patterns` as modified for a given base path. It modifies the
236 * absolute paths in the patterns as prepending the difference of two base
237 * paths.
238 * @param {string} newBasePath The base path.
239 * @returns {string[]} Modifired patterns.
240 */
241 getPatternsRelativeTo(newBasePath) {
242 assert__default["default"](path__default["default"].isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
243 const { basePath, loose, patterns } = this;
244
245 if (newBasePath === basePath) {
246 return patterns;
247 }
248 const prefix = `/${relative(newBasePath, basePath)}`;
249
250 return patterns.map(pattern => {
251 const negative = pattern.startsWith("!");
252 const head = negative ? "!" : "";
253 const body = negative ? pattern.slice(1) : pattern;
254
255 if (body.startsWith("/") || body.startsWith("../")) {
256 return `${head}${prefix}${body}`;
257 }
258 return loose ? pattern : `${head}${prefix}/**/${body}`;
259 });
260 }
261}
262
263/**
264 * @fileoverview `ExtractedConfig` class.
265 *
266 * `ExtractedConfig` class expresses a final configuration for a specific file.
267 *
268 * It provides one method.
269 *
270 * - `toCompatibleObjectAsConfigFileContent()`
271 * Convert this configuration to the compatible object as the content of
272 * config files. It converts the loaded parser and plugins to strings.
273 * `CLIEngine#getConfigForFile(filePath)` method uses this method.
274 *
275 * `ConfigArray#extractConfig(filePath)` creates a `ExtractedConfig` instance.
276 *
277 * @author Toru Nagashima <https://github.com/mysticatea>
278 */
279
280// For VSCode intellisense
281/** @typedef {import("../../shared/types").ConfigData} ConfigData */
282/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
283/** @typedef {import("../../shared/types").SeverityConf} SeverityConf */
284/** @typedef {import("./config-dependency").DependentParser} DependentParser */
285/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
286
287/**
288 * Check if `xs` starts with `ys`.
289 * @template T
290 * @param {T[]} xs The array to check.
291 * @param {T[]} ys The array that may be the first part of `xs`.
292 * @returns {boolean} `true` if `xs` starts with `ys`.
293 */
294function startsWith(xs, ys) {
295 return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
296}
297
298/**
299 * The class for extracted config data.
300 */
301class ExtractedConfig {
302 constructor() {
303
304 /**
305 * The config name what `noInlineConfig` setting came from.
306 * @type {string}
307 */
308 this.configNameOfNoInlineConfig = "";
309
310 /**
311 * Environments.
312 * @type {Record<string, boolean>}
313 */
314 this.env = {};
315
316 /**
317 * Global variables.
318 * @type {Record<string, GlobalConf>}
319 */
320 this.globals = {};
321
322 /**
323 * The glob patterns that ignore to lint.
324 * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
325 */
326 this.ignores = void 0;
327
328 /**
329 * The flag that disables directive comments.
330 * @type {boolean|undefined}
331 */
332 this.noInlineConfig = void 0;
333
334 /**
335 * Parser definition.
336 * @type {DependentParser|null}
337 */
338 this.parser = null;
339
340 /**
341 * Options for the parser.
342 * @type {Object}
343 */
344 this.parserOptions = {};
345
346 /**
347 * Plugin definitions.
348 * @type {Record<string, DependentPlugin>}
349 */
350 this.plugins = {};
351
352 /**
353 * Processor ID.
354 * @type {string|null}
355 */
356 this.processor = null;
357
358 /**
359 * The flag that reports unused `eslint-disable` directive comments.
360 * @type {boolean|undefined}
361 */
362 this.reportUnusedDisableDirectives = void 0;
363
364 /**
365 * Rule settings.
366 * @type {Record<string, [SeverityConf, ...any[]]>}
367 */
368 this.rules = {};
369
370 /**
371 * Shared settings.
372 * @type {Object}
373 */
374 this.settings = {};
375 }
376
377 /**
378 * Convert this config to the compatible object as a config file content.
379 * @returns {ConfigData} The converted object.
380 */
381 toCompatibleObjectAsConfigFileContent() {
382 const {
383 /* eslint-disable no-unused-vars */
384 configNameOfNoInlineConfig: _ignore1,
385 processor: _ignore2,
386 /* eslint-enable no-unused-vars */
387 ignores,
388 ...config
389 } = this;
390
391 config.parser = config.parser && config.parser.filePath;
392 config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
393 config.ignorePatterns = ignores ? ignores.patterns : [];
394
395 // Strip the default patterns from `ignorePatterns`.
396 if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
397 config.ignorePatterns =
398 config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
399 }
400
401 return config;
402 }
403}
404
405/**
406 * @fileoverview `ConfigArray` class.
407 *
408 * `ConfigArray` class expresses the full of a configuration. It has the entry
409 * config file, base config files that were extended, loaded parsers, and loaded
410 * plugins.
411 *
412 * `ConfigArray` class provides three properties and two methods.
413 *
414 * - `pluginEnvironments`
415 * - `pluginProcessors`
416 * - `pluginRules`
417 * The `Map` objects that contain the members of all plugins that this
418 * config array contains. Those map objects don't have mutation methods.
419 * Those keys are the member ID such as `pluginId/memberName`.
420 * - `isRoot()`
421 * If `true` then this configuration has `root:true` property.
422 * - `extractConfig(filePath)`
423 * Extract the final configuration for a given file. This means merging
424 * every config array element which that `criteria` property matched. The
425 * `filePath` argument must be an absolute path.
426 *
427 * `ConfigArrayFactory` provides the loading logic of config files.
428 *
429 * @author Toru Nagashima <https://github.com/mysticatea>
430 */
431
432//------------------------------------------------------------------------------
433// Helpers
434//------------------------------------------------------------------------------
435
436// Define types for VSCode IntelliSense.
437/** @typedef {import("../../shared/types").Environment} Environment */
438/** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
439/** @typedef {import("../../shared/types").RuleConf} RuleConf */
440/** @typedef {import("../../shared/types").Rule} Rule */
441/** @typedef {import("../../shared/types").Plugin} Plugin */
442/** @typedef {import("../../shared/types").Processor} Processor */
443/** @typedef {import("./config-dependency").DependentParser} DependentParser */
444/** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
445/** @typedef {import("./override-tester")["OverrideTester"]} OverrideTester */
446
447/**
448 * @typedef {Object} ConfigArrayElement
449 * @property {string} name The name of this config element.
450 * @property {string} filePath The path to the source file of this config element.
451 * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
452 * @property {Record<string, boolean>|undefined} env The environment settings.
453 * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
454 * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
455 * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
456 * @property {DependentParser|undefined} parser The parser loader.
457 * @property {Object|undefined} parserOptions The parser options.
458 * @property {Record<string, DependentPlugin>|undefined} plugins The plugin loaders.
459 * @property {string|undefined} processor The processor name to refer plugin's processor.
460 * @property {boolean|undefined} reportUnusedDisableDirectives The flag to report unused `eslint-disable` comments.
461 * @property {boolean|undefined} root The flag to express root.
462 * @property {Record<string, RuleConf>|undefined} rules The rule settings
463 * @property {Object|undefined} settings The shared settings.
464 * @property {"config" | "ignore" | "implicit-processor"} type The element type.
465 */
466
467/**
468 * @typedef {Object} ConfigArrayInternalSlots
469 * @property {Map<string, ExtractedConfig>} cache The cache to extract configs.
470 * @property {ReadonlyMap<string, Environment>|null} envMap The map from environment ID to environment definition.
471 * @property {ReadonlyMap<string, Processor>|null} processorMap The map from processor ID to environment definition.
472 * @property {ReadonlyMap<string, Rule>|null} ruleMap The map from rule ID to rule definition.
473 */
474
475/** @type {WeakMap<ConfigArray, ConfigArrayInternalSlots>} */
476const internalSlotsMap$2 = new class extends WeakMap {
477 get(key) {
478 let value = super.get(key);
479
480 if (!value) {
481 value = {
482 cache: new Map(),
483 envMap: null,
484 processorMap: null,
485 ruleMap: null
486 };
487 super.set(key, value);
488 }
489
490 return value;
491 }
492}();
493
494/**
495 * Get the indices which are matched to a given file.
496 * @param {ConfigArrayElement[]} elements The elements.
497 * @param {string} filePath The path to a target file.
498 * @returns {number[]} The indices.
499 */
500function getMatchedIndices(elements, filePath) {
501 const indices = [];
502
503 for (let i = elements.length - 1; i >= 0; --i) {
504 const element = elements[i];
505
506 if (!element.criteria || (filePath && element.criteria.test(filePath))) {
507 indices.push(i);
508 }
509 }
510
511 return indices;
512}
513
514/**
515 * Check if a value is a non-null object.
516 * @param {any} x The value to check.
517 * @returns {boolean} `true` if the value is a non-null object.
518 */
519function isNonNullObject(x) {
520 return typeof x === "object" && x !== null;
521}
522
523/**
524 * Merge two objects.
525 *
526 * Assign every property values of `y` to `x` if `x` doesn't have the property.
527 * If `x`'s property value is an object, it does recursive.
528 * @param {Object} target The destination to merge
529 * @param {Object|undefined} source The source to merge.
530 * @returns {void}
531 */
532function mergeWithoutOverwrite(target, source) {
533 if (!isNonNullObject(source)) {
534 return;
535 }
536
537 for (const key of Object.keys(source)) {
538 if (key === "__proto__") {
539 continue;
540 }
541
542 if (isNonNullObject(target[key])) {
543 mergeWithoutOverwrite(target[key], source[key]);
544 } else if (target[key] === void 0) {
545 if (isNonNullObject(source[key])) {
546 target[key] = Array.isArray(source[key]) ? [] : {};
547 mergeWithoutOverwrite(target[key], source[key]);
548 } else if (source[key] !== void 0) {
549 target[key] = source[key];
550 }
551 }
552 }
553}
554
555/**
556 * The error for plugin conflicts.
557 */
558class PluginConflictError extends Error {
559
560 /**
561 * Initialize this error object.
562 * @param {string} pluginId The plugin ID.
563 * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
564 */
565 constructor(pluginId, plugins) {
566 super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
567 this.messageTemplate = "plugin-conflict";
568 this.messageData = { pluginId, plugins };
569 }
570}
571
572/**
573 * Merge plugins.
574 * `target`'s definition is prior to `source`'s.
575 * @param {Record<string, DependentPlugin>} target The destination to merge
576 * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
577 * @returns {void}
578 */
579function mergePlugins(target, source) {
580 if (!isNonNullObject(source)) {
581 return;
582 }
583
584 for (const key of Object.keys(source)) {
585 if (key === "__proto__") {
586 continue;
587 }
588 const targetValue = target[key];
589 const sourceValue = source[key];
590
591 // Adopt the plugin which was found at first.
592 if (targetValue === void 0) {
593 if (sourceValue.error) {
594 throw sourceValue.error;
595 }
596 target[key] = sourceValue;
597 } else if (sourceValue.filePath !== targetValue.filePath) {
598 throw new PluginConflictError(key, [
599 {
600 filePath: targetValue.filePath,
601 importerName: targetValue.importerName
602 },
603 {
604 filePath: sourceValue.filePath,
605 importerName: sourceValue.importerName
606 }
607 ]);
608 }
609 }
610}
611
612/**
613 * Merge rule configs.
614 * `target`'s definition is prior to `source`'s.
615 * @param {Record<string, Array>} target The destination to merge
616 * @param {Record<string, RuleConf>|undefined} source The source to merge.
617 * @returns {void}
618 */
619function mergeRuleConfigs(target, source) {
620 if (!isNonNullObject(source)) {
621 return;
622 }
623
624 for (const key of Object.keys(source)) {
625 if (key === "__proto__") {
626 continue;
627 }
628 const targetDef = target[key];
629 const sourceDef = source[key];
630
631 // Adopt the rule config which was found at first.
632 if (targetDef === void 0) {
633 if (Array.isArray(sourceDef)) {
634 target[key] = [...sourceDef];
635 } else {
636 target[key] = [sourceDef];
637 }
638
639 /*
640 * If the first found rule config is severity only and the current rule
641 * config has options, merge the severity and the options.
642 */
643 } else if (
644 targetDef.length === 1 &&
645 Array.isArray(sourceDef) &&
646 sourceDef.length >= 2
647 ) {
648 targetDef.push(...sourceDef.slice(1));
649 }
650 }
651}
652
653/**
654 * Create the extracted config.
655 * @param {ConfigArray} instance The config elements.
656 * @param {number[]} indices The indices to use.
657 * @returns {ExtractedConfig} The extracted config.
658 */
659function createConfig(instance, indices) {
660 const config = new ExtractedConfig();
661 const ignorePatterns = [];
662
663 // Merge elements.
664 for (const index of indices) {
665 const element = instance[index];
666
667 // Adopt the parser which was found at first.
668 if (!config.parser && element.parser) {
669 if (element.parser.error) {
670 throw element.parser.error;
671 }
672 config.parser = element.parser;
673 }
674
675 // Adopt the processor which was found at first.
676 if (!config.processor && element.processor) {
677 config.processor = element.processor;
678 }
679
680 // Adopt the noInlineConfig which was found at first.
681 if (config.noInlineConfig === void 0 && element.noInlineConfig !== void 0) {
682 config.noInlineConfig = element.noInlineConfig;
683 config.configNameOfNoInlineConfig = element.name;
684 }
685
686 // Adopt the reportUnusedDisableDirectives which was found at first.
687 if (config.reportUnusedDisableDirectives === void 0 && element.reportUnusedDisableDirectives !== void 0) {
688 config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
689 }
690
691 // Collect ignorePatterns
692 if (element.ignorePattern) {
693 ignorePatterns.push(element.ignorePattern);
694 }
695
696 // Merge others.
697 mergeWithoutOverwrite(config.env, element.env);
698 mergeWithoutOverwrite(config.globals, element.globals);
699 mergeWithoutOverwrite(config.parserOptions, element.parserOptions);
700 mergeWithoutOverwrite(config.settings, element.settings);
701 mergePlugins(config.plugins, element.plugins);
702 mergeRuleConfigs(config.rules, element.rules);
703 }
704
705 // Create the predicate function for ignore patterns.
706 if (ignorePatterns.length > 0) {
707 config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
708 }
709
710 return config;
711}
712
713/**
714 * Collect definitions.
715 * @template T, U
716 * @param {string} pluginId The plugin ID for prefix.
717 * @param {Record<string,T>} defs The definitions to collect.
718 * @param {Map<string, U>} map The map to output.
719 * @param {function(T): U} [normalize] The normalize function for each value.
720 * @returns {void}
721 */
722function collect(pluginId, defs, map, normalize) {
723 if (defs) {
724 const prefix = pluginId && `${pluginId}/`;
725
726 for (const [key, value] of Object.entries(defs)) {
727 map.set(
728 `${prefix}${key}`,
729 normalize ? normalize(value) : value
730 );
731 }
732 }
733}
734
735/**
736 * Normalize a rule definition.
737 * @param {Function|Rule} rule The rule definition to normalize.
738 * @returns {Rule} The normalized rule definition.
739 */
740function normalizePluginRule(rule) {
741 return typeof rule === "function" ? { create: rule } : rule;
742}
743
744/**
745 * Delete the mutation methods from a given map.
746 * @param {Map<any, any>} map The map object to delete.
747 * @returns {void}
748 */
749function deleteMutationMethods(map) {
750 Object.defineProperties(map, {
751 clear: { configurable: true, value: void 0 },
752 delete: { configurable: true, value: void 0 },
753 set: { configurable: true, value: void 0 }
754 });
755}
756
757/**
758 * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
759 * @param {ConfigArrayElement[]} elements The config elements.
760 * @param {ConfigArrayInternalSlots} slots The internal slots.
761 * @returns {void}
762 */
763function initPluginMemberMaps(elements, slots) {
764 const processed = new Set();
765
766 slots.envMap = new Map();
767 slots.processorMap = new Map();
768 slots.ruleMap = new Map();
769
770 for (const element of elements) {
771 if (!element.plugins) {
772 continue;
773 }
774
775 for (const [pluginId, value] of Object.entries(element.plugins)) {
776 const plugin = value.definition;
777
778 if (!plugin || processed.has(pluginId)) {
779 continue;
780 }
781 processed.add(pluginId);
782
783 collect(pluginId, plugin.environments, slots.envMap);
784 collect(pluginId, plugin.processors, slots.processorMap);
785 collect(pluginId, plugin.rules, slots.ruleMap, normalizePluginRule);
786 }
787 }
788
789 deleteMutationMethods(slots.envMap);
790 deleteMutationMethods(slots.processorMap);
791 deleteMutationMethods(slots.ruleMap);
792}
793
794/**
795 * Create `envMap`, `processorMap`, `ruleMap` with the plugins in the config array.
796 * @param {ConfigArray} instance The config elements.
797 * @returns {ConfigArrayInternalSlots} The extracted config.
798 */
799function ensurePluginMemberMaps(instance) {
800 const slots = internalSlotsMap$2.get(instance);
801
802 if (!slots.ruleMap) {
803 initPluginMemberMaps(instance, slots);
804 }
805
806 return slots;
807}
808
809//------------------------------------------------------------------------------
810// Public Interface
811//------------------------------------------------------------------------------
812
813/**
814 * The Config Array.
815 *
816 * `ConfigArray` instance contains all settings, parsers, and plugins.
817 * You need to call `ConfigArray#extractConfig(filePath)` method in order to
818 * extract, merge and get only the config data which is related to an arbitrary
819 * file.
820 * @extends {Array<ConfigArrayElement>}
821 */
822class ConfigArray extends Array {
823
824 /**
825 * Get the plugin environments.
826 * The returned map cannot be mutated.
827 * @type {ReadonlyMap<string, Environment>} The plugin environments.
828 */
829 get pluginEnvironments() {
830 return ensurePluginMemberMaps(this).envMap;
831 }
832
833 /**
834 * Get the plugin processors.
835 * The returned map cannot be mutated.
836 * @type {ReadonlyMap<string, Processor>} The plugin processors.
837 */
838 get pluginProcessors() {
839 return ensurePluginMemberMaps(this).processorMap;
840 }
841
842 /**
843 * Get the plugin rules.
844 * The returned map cannot be mutated.
845 * @returns {ReadonlyMap<string, Rule>} The plugin rules.
846 */
847 get pluginRules() {
848 return ensurePluginMemberMaps(this).ruleMap;
849 }
850
851 /**
852 * Check if this config has `root` flag.
853 * @returns {boolean} `true` if this config array is root.
854 */
855 isRoot() {
856 for (let i = this.length - 1; i >= 0; --i) {
857 const root = this[i].root;
858
859 if (typeof root === "boolean") {
860 return root;
861 }
862 }
863 return false;
864 }
865
866 /**
867 * Extract the config data which is related to a given file.
868 * @param {string} filePath The absolute path to the target file.
869 * @returns {ExtractedConfig} The extracted config data.
870 */
871 extractConfig(filePath) {
872 const { cache } = internalSlotsMap$2.get(this);
873 const indices = getMatchedIndices(this, filePath);
874 const cacheKey = indices.join(",");
875
876 if (!cache.has(cacheKey)) {
877 cache.set(cacheKey, createConfig(this, indices));
878 }
879
880 return cache.get(cacheKey);
881 }
882
883 /**
884 * Check if a given path is an additional lint target.
885 * @param {string} filePath The absolute path to the target file.
886 * @returns {boolean} `true` if the file is an additional lint target.
887 */
888 isAdditionalTargetPath(filePath) {
889 for (const { criteria, type } of this) {
890 if (
891 type === "config" &&
892 criteria &&
893 !criteria.endsWithWildcard &&
894 criteria.test(filePath)
895 ) {
896 return true;
897 }
898 }
899 return false;
900 }
901}
902
903/**
904 * Get the used extracted configs.
905 * CLIEngine will use this method to collect used deprecated rules.
906 * @param {ConfigArray} instance The config array object to get.
907 * @returns {ExtractedConfig[]} The used extracted configs.
908 * @private
909 */
910function getUsedExtractedConfigs(instance) {
911 const { cache } = internalSlotsMap$2.get(instance);
912
913 return Array.from(cache.values());
914}
915
916/**
917 * @fileoverview `ConfigDependency` class.
918 *
919 * `ConfigDependency` class expresses a loaded parser or plugin.
920 *
921 * If the parser or plugin was loaded successfully, it has `definition` property
922 * and `filePath` property. Otherwise, it has `error` property.
923 *
924 * When `JSON.stringify()` converted a `ConfigDependency` object to a JSON, it
925 * omits `definition` property.
926 *
927 * `ConfigArrayFactory` creates `ConfigDependency` objects when it loads parsers
928 * or plugins.
929 *
930 * @author Toru Nagashima <https://github.com/mysticatea>
931 */
932
933/**
934 * The class is to store parsers or plugins.
935 * This class hides the loaded object from `JSON.stringify()` and `console.log`.
936 * @template T
937 */
938class ConfigDependency {
939
940 /**
941 * Initialize this instance.
942 * @param {Object} data The dependency data.
943 * @param {T} [data.definition] The dependency if the loading succeeded.
944 * @param {T} [data.original] The original, non-normalized dependency if the loading succeeded.
945 * @param {Error} [data.error] The error object if the loading failed.
946 * @param {string} [data.filePath] The actual path to the dependency if the loading succeeded.
947 * @param {string} data.id The ID of this dependency.
948 * @param {string} data.importerName The name of the config file which loads this dependency.
949 * @param {string} data.importerPath The path to the config file which loads this dependency.
950 */
951 constructor({
952 definition = null,
953 original = null,
954 error = null,
955 filePath = null,
956 id,
957 importerName,
958 importerPath
959 }) {
960
961 /**
962 * The loaded dependency if the loading succeeded.
963 * @type {T|null}
964 */
965 this.definition = definition;
966
967 /**
968 * The original dependency as loaded directly from disk if the loading succeeded.
969 * @type {T|null}
970 */
971 this.original = original;
972
973 /**
974 * The error object if the loading failed.
975 * @type {Error|null}
976 */
977 this.error = error;
978
979 /**
980 * The loaded dependency if the loading succeeded.
981 * @type {string|null}
982 */
983 this.filePath = filePath;
984
985 /**
986 * The ID of this dependency.
987 * @type {string}
988 */
989 this.id = id;
990
991 /**
992 * The name of the config file which loads this dependency.
993 * @type {string}
994 */
995 this.importerName = importerName;
996
997 /**
998 * The path to the config file which loads this dependency.
999 * @type {string}
1000 */
1001 this.importerPath = importerPath;
1002 }
1003
1004 // eslint-disable-next-line jsdoc/require-description
1005 /**
1006 * @returns {Object} a JSON compatible object.
1007 */
1008 toJSON() {
1009 const obj = this[util__default["default"].inspect.custom]();
1010
1011 // Display `error.message` (`Error#message` is unenumerable).
1012 if (obj.error instanceof Error) {
1013 obj.error = { ...obj.error, message: obj.error.message };
1014 }
1015
1016 return obj;
1017 }
1018
1019 // eslint-disable-next-line jsdoc/require-description
1020 /**
1021 * @returns {Object} an object to display by `console.log()`.
1022 */
1023 [util__default["default"].inspect.custom]() {
1024 const {
1025 definition: _ignore1, // eslint-disable-line no-unused-vars
1026 original: _ignore2, // eslint-disable-line no-unused-vars
1027 ...obj
1028 } = this;
1029
1030 return obj;
1031 }
1032}
1033
1034/**
1035 * @fileoverview `OverrideTester` class.
1036 *
1037 * `OverrideTester` class handles `files` property and `excludedFiles` property
1038 * of `overrides` config.
1039 *
1040 * It provides one method.
1041 *
1042 * - `test(filePath)`
1043 * Test if a file path matches the pair of `files` property and
1044 * `excludedFiles` property. The `filePath` argument must be an absolute
1045 * path.
1046 *
1047 * `ConfigArrayFactory` creates `OverrideTester` objects when it processes
1048 * `overrides` properties.
1049 *
1050 * @author Toru Nagashima <https://github.com/mysticatea>
1051 */
1052
1053const { Minimatch } = minimatch__default["default"];
1054
1055const minimatchOpts = { dot: true, matchBase: true };
1056
1057/**
1058 * @typedef {Object} Pattern
1059 * @property {InstanceType<Minimatch>[] | null} includes The positive matchers.
1060 * @property {InstanceType<Minimatch>[] | null} excludes The negative matchers.
1061 */
1062
1063/**
1064 * Normalize a given pattern to an array.
1065 * @param {string|string[]|undefined} patterns A glob pattern or an array of glob patterns.
1066 * @returns {string[]|null} Normalized patterns.
1067 * @private
1068 */
1069function normalizePatterns(patterns) {
1070 if (Array.isArray(patterns)) {
1071 return patterns.filter(Boolean);
1072 }
1073 if (typeof patterns === "string" && patterns) {
1074 return [patterns];
1075 }
1076 return [];
1077}
1078
1079/**
1080 * Create the matchers of given patterns.
1081 * @param {string[]} patterns The patterns.
1082 * @returns {InstanceType<Minimatch>[] | null} The matchers.
1083 */
1084function toMatcher(patterns) {
1085 if (patterns.length === 0) {
1086 return null;
1087 }
1088 return patterns.map(pattern => {
1089 if (/^\.[/\\]/u.test(pattern)) {
1090 return new Minimatch(
1091 pattern.slice(2),
1092
1093 // `./*.js` should not match with `subdir/foo.js`
1094 { ...minimatchOpts, matchBase: false }
1095 );
1096 }
1097 return new Minimatch(pattern, minimatchOpts);
1098 });
1099}
1100
1101/**
1102 * Convert a given matcher to string.
1103 * @param {Pattern} matchers The matchers.
1104 * @returns {string} The string expression of the matcher.
1105 */
1106function patternToJson({ includes, excludes }) {
1107 return {
1108 includes: includes && includes.map(m => m.pattern),
1109 excludes: excludes && excludes.map(m => m.pattern)
1110 };
1111}
1112
1113/**
1114 * The class to test given paths are matched by the patterns.
1115 */
1116class OverrideTester {
1117
1118 /**
1119 * Create a tester with given criteria.
1120 * If there are no criteria, returns `null`.
1121 * @param {string|string[]} files The glob patterns for included files.
1122 * @param {string|string[]} excludedFiles The glob patterns for excluded files.
1123 * @param {string} basePath The path to the base directory to test paths.
1124 * @returns {OverrideTester|null} The created instance or `null`.
1125 */
1126 static create(files, excludedFiles, basePath) {
1127 const includePatterns = normalizePatterns(files);
1128 const excludePatterns = normalizePatterns(excludedFiles);
1129 let endsWithWildcard = false;
1130
1131 if (includePatterns.length === 0) {
1132 return null;
1133 }
1134
1135 // Rejects absolute paths or relative paths to parents.
1136 for (const pattern of includePatterns) {
1137 if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
1138 throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
1139 }
1140 if (pattern.endsWith("*")) {
1141 endsWithWildcard = true;
1142 }
1143 }
1144 for (const pattern of excludePatterns) {
1145 if (path__default["default"].isAbsolute(pattern) || pattern.includes("..")) {
1146 throw new Error(`Invalid override pattern (expected relative path not containing '..'): ${pattern}`);
1147 }
1148 }
1149
1150 const includes = toMatcher(includePatterns);
1151 const excludes = toMatcher(excludePatterns);
1152
1153 return new OverrideTester(
1154 [{ includes, excludes }],
1155 basePath,
1156 endsWithWildcard
1157 );
1158 }
1159
1160 /**
1161 * Combine two testers by logical and.
1162 * If either of the testers was `null`, returns the other tester.
1163 * The `basePath` property of the two must be the same value.
1164 * @param {OverrideTester|null} a A tester.
1165 * @param {OverrideTester|null} b Another tester.
1166 * @returns {OverrideTester|null} Combined tester.
1167 */
1168 static and(a, b) {
1169 if (!b) {
1170 return a && new OverrideTester(
1171 a.patterns,
1172 a.basePath,
1173 a.endsWithWildcard
1174 );
1175 }
1176 if (!a) {
1177 return new OverrideTester(
1178 b.patterns,
1179 b.basePath,
1180 b.endsWithWildcard
1181 );
1182 }
1183
1184 assert__default["default"].strictEqual(a.basePath, b.basePath);
1185 return new OverrideTester(
1186 a.patterns.concat(b.patterns),
1187 a.basePath,
1188 a.endsWithWildcard || b.endsWithWildcard
1189 );
1190 }
1191
1192 /**
1193 * Initialize this instance.
1194 * @param {Pattern[]} patterns The matchers.
1195 * @param {string} basePath The base path.
1196 * @param {boolean} endsWithWildcard If `true` then a pattern ends with `*`.
1197 */
1198 constructor(patterns, basePath, endsWithWildcard = false) {
1199
1200 /** @type {Pattern[]} */
1201 this.patterns = patterns;
1202
1203 /** @type {string} */
1204 this.basePath = basePath;
1205
1206 /** @type {boolean} */
1207 this.endsWithWildcard = endsWithWildcard;
1208 }
1209
1210 /**
1211 * Test if a given path is matched or not.
1212 * @param {string} filePath The absolute path to the target file.
1213 * @returns {boolean} `true` if the path was matched.
1214 */
1215 test(filePath) {
1216 if (typeof filePath !== "string" || !path__default["default"].isAbsolute(filePath)) {
1217 throw new Error(`'filePath' should be an absolute path, but got ${filePath}.`);
1218 }
1219 const relativePath = path__default["default"].relative(this.basePath, filePath);
1220
1221 return this.patterns.every(({ includes, excludes }) => (
1222 (!includes || includes.some(m => m.match(relativePath))) &&
1223 (!excludes || !excludes.some(m => m.match(relativePath)))
1224 ));
1225 }
1226
1227 // eslint-disable-next-line jsdoc/require-description
1228 /**
1229 * @returns {Object} a JSON compatible object.
1230 */
1231 toJSON() {
1232 if (this.patterns.length === 1) {
1233 return {
1234 ...patternToJson(this.patterns[0]),
1235 basePath: this.basePath
1236 };
1237 }
1238 return {
1239 AND: this.patterns.map(patternToJson),
1240 basePath: this.basePath
1241 };
1242 }
1243
1244 // eslint-disable-next-line jsdoc/require-description
1245 /**
1246 * @returns {Object} an object to display by `console.log()`.
1247 */
1248 [util__default["default"].inspect.custom]() {
1249 return this.toJSON();
1250 }
1251}
1252
1253/**
1254 * @fileoverview `ConfigArray` class.
1255 * @author Toru Nagashima <https://github.com/mysticatea>
1256 */
1257
1258/**
1259 * @fileoverview Config file operations. This file must be usable in the browser,
1260 * so no Node-specific code can be here.
1261 * @author Nicholas C. Zakas
1262 */
1263
1264//------------------------------------------------------------------------------
1265// Private
1266//------------------------------------------------------------------------------
1267
1268const RULE_SEVERITY_STRINGS = ["off", "warn", "error"],
1269 RULE_SEVERITY = RULE_SEVERITY_STRINGS.reduce((map, value, index) => {
1270 map[value] = index;
1271 return map;
1272 }, {}),
1273 VALID_SEVERITIES = [0, 1, 2, "off", "warn", "error"];
1274
1275//------------------------------------------------------------------------------
1276// Public Interface
1277//------------------------------------------------------------------------------
1278
1279/**
1280 * Normalizes the severity value of a rule's configuration to a number
1281 * @param {(number|string|[number, ...*]|[string, ...*])} ruleConfig A rule's configuration value, generally
1282 * received from the user. A valid config value is either 0, 1, 2, the string "off" (treated the same as 0),
1283 * the string "warn" (treated the same as 1), the string "error" (treated the same as 2), or an array
1284 * whose first element is one of the above values. Strings are matched case-insensitively.
1285 * @returns {(0|1|2)} The numeric severity value if the config value was valid, otherwise 0.
1286 */
1287function getRuleSeverity(ruleConfig) {
1288 const severityValue = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
1289
1290 if (severityValue === 0 || severityValue === 1 || severityValue === 2) {
1291 return severityValue;
1292 }
1293
1294 if (typeof severityValue === "string") {
1295 return RULE_SEVERITY[severityValue.toLowerCase()] || 0;
1296 }
1297
1298 return 0;
1299}
1300
1301/**
1302 * Converts old-style severity settings (0, 1, 2) into new-style
1303 * severity settings (off, warn, error) for all rules. Assumption is that severity
1304 * values have already been validated as correct.
1305 * @param {Object} config The config object to normalize.
1306 * @returns {void}
1307 */
1308function normalizeToStrings(config) {
1309
1310 if (config.rules) {
1311 Object.keys(config.rules).forEach(ruleId => {
1312 const ruleConfig = config.rules[ruleId];
1313
1314 if (typeof ruleConfig === "number") {
1315 config.rules[ruleId] = RULE_SEVERITY_STRINGS[ruleConfig] || RULE_SEVERITY_STRINGS[0];
1316 } else if (Array.isArray(ruleConfig) && typeof ruleConfig[0] === "number") {
1317 ruleConfig[0] = RULE_SEVERITY_STRINGS[ruleConfig[0]] || RULE_SEVERITY_STRINGS[0];
1318 }
1319 });
1320 }
1321}
1322
1323/**
1324 * Determines if the severity for the given rule configuration represents an error.
1325 * @param {int|string|Array} ruleConfig The configuration for an individual rule.
1326 * @returns {boolean} True if the rule represents an error, false if not.
1327 */
1328function isErrorSeverity(ruleConfig) {
1329 return getRuleSeverity(ruleConfig) === 2;
1330}
1331
1332/**
1333 * Checks whether a given config has valid severity or not.
1334 * @param {number|string|Array} ruleConfig The configuration for an individual rule.
1335 * @returns {boolean} `true` if the configuration has valid severity.
1336 */
1337function isValidSeverity(ruleConfig) {
1338 let severity = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
1339
1340 if (typeof severity === "string") {
1341 severity = severity.toLowerCase();
1342 }
1343 return VALID_SEVERITIES.indexOf(severity) !== -1;
1344}
1345
1346/**
1347 * Checks whether every rule of a given config has valid severity or not.
1348 * @param {Object} config The configuration for rules.
1349 * @returns {boolean} `true` if the configuration has valid severity.
1350 */
1351function isEverySeverityValid(config) {
1352 return Object.keys(config).every(ruleId => isValidSeverity(config[ruleId]));
1353}
1354
1355/**
1356 * Normalizes a value for a global in a config
1357 * @param {(boolean|string|null)} configuredValue The value given for a global in configuration or in
1358 * a global directive comment
1359 * @returns {("readable"|"writeable"|"off")} The value normalized as a string
1360 * @throws Error if global value is invalid
1361 */
1362function normalizeConfigGlobal(configuredValue) {
1363 switch (configuredValue) {
1364 case "off":
1365 return "off";
1366
1367 case true:
1368 case "true":
1369 case "writeable":
1370 case "writable":
1371 return "writable";
1372
1373 case null:
1374 case false:
1375 case "false":
1376 case "readable":
1377 case "readonly":
1378 return "readonly";
1379
1380 default:
1381 throw new Error(`'${configuredValue}' is not a valid configuration for a global (use 'readonly', 'writable', or 'off')`);
1382 }
1383}
1384
1385var ConfigOps = {
1386 __proto__: null,
1387 getRuleSeverity: getRuleSeverity,
1388 normalizeToStrings: normalizeToStrings,
1389 isErrorSeverity: isErrorSeverity,
1390 isValidSeverity: isValidSeverity,
1391 isEverySeverityValid: isEverySeverityValid,
1392 normalizeConfigGlobal: normalizeConfigGlobal
1393};
1394
1395/**
1396 * @fileoverview Provide the function that emits deprecation warnings.
1397 * @author Toru Nagashima <http://github.com/mysticatea>
1398 */
1399
1400//------------------------------------------------------------------------------
1401// Private
1402//------------------------------------------------------------------------------
1403
1404// Defitions for deprecation warnings.
1405const deprecationWarningMessages = {
1406 ESLINT_LEGACY_ECMAFEATURES:
1407 "The 'ecmaFeatures' config file property is deprecated and has no effect.",
1408 ESLINT_PERSONAL_CONFIG_LOAD:
1409 "'~/.eslintrc.*' config files have been deprecated. " +
1410 "Please use a config file per project or the '--config' option.",
1411 ESLINT_PERSONAL_CONFIG_SUPPRESS:
1412 "'~/.eslintrc.*' config files have been deprecated. " +
1413 "Please remove it or add 'root:true' to the config files in your " +
1414 "projects in order to avoid loading '~/.eslintrc.*' accidentally."
1415};
1416
1417const sourceFileErrorCache = new Set();
1418
1419/**
1420 * Emits a deprecation warning containing a given filepath. A new deprecation warning is emitted
1421 * for each unique file path, but repeated invocations with the same file path have no effect.
1422 * No warnings are emitted if the `--no-deprecation` or `--no-warnings` Node runtime flags are active.
1423 * @param {string} source The name of the configuration source to report the warning for.
1424 * @param {string} errorCode The warning message to show.
1425 * @returns {void}
1426 */
1427function emitDeprecationWarning(source, errorCode) {
1428 const cacheKey = JSON.stringify({ source, errorCode });
1429
1430 if (sourceFileErrorCache.has(cacheKey)) {
1431 return;
1432 }
1433 sourceFileErrorCache.add(cacheKey);
1434
1435 const rel = path__default["default"].relative(process.cwd(), source);
1436 const message = deprecationWarningMessages[errorCode];
1437
1438 process.emitWarning(
1439 `${message} (found in "${rel}")`,
1440 "DeprecationWarning",
1441 errorCode
1442 );
1443}
1444
1445/**
1446 * @fileoverview The instance of Ajv validator.
1447 * @author Evgeny Poberezkin
1448 */
1449
1450//-----------------------------------------------------------------------------
1451// Helpers
1452//-----------------------------------------------------------------------------
1453
1454/*
1455 * Copied from ajv/lib/refs/json-schema-draft-04.json
1456 * The MIT License (MIT)
1457 * Copyright (c) 2015-2017 Evgeny Poberezkin
1458 */
1459const metaSchema = {
1460 id: "http://json-schema.org/draft-04/schema#",
1461 $schema: "http://json-schema.org/draft-04/schema#",
1462 description: "Core schema meta-schema",
1463 definitions: {
1464 schemaArray: {
1465 type: "array",
1466 minItems: 1,
1467 items: { $ref: "#" }
1468 },
1469 positiveInteger: {
1470 type: "integer",
1471 minimum: 0
1472 },
1473 positiveIntegerDefault0: {
1474 allOf: [{ $ref: "#/definitions/positiveInteger" }, { default: 0 }]
1475 },
1476 simpleTypes: {
1477 enum: ["array", "boolean", "integer", "null", "number", "object", "string"]
1478 },
1479 stringArray: {
1480 type: "array",
1481 items: { type: "string" },
1482 minItems: 1,
1483 uniqueItems: true
1484 }
1485 },
1486 type: "object",
1487 properties: {
1488 id: {
1489 type: "string"
1490 },
1491 $schema: {
1492 type: "string"
1493 },
1494 title: {
1495 type: "string"
1496 },
1497 description: {
1498 type: "string"
1499 },
1500 default: { },
1501 multipleOf: {
1502 type: "number",
1503 minimum: 0,
1504 exclusiveMinimum: true
1505 },
1506 maximum: {
1507 type: "number"
1508 },
1509 exclusiveMaximum: {
1510 type: "boolean",
1511 default: false
1512 },
1513 minimum: {
1514 type: "number"
1515 },
1516 exclusiveMinimum: {
1517 type: "boolean",
1518 default: false
1519 },
1520 maxLength: { $ref: "#/definitions/positiveInteger" },
1521 minLength: { $ref: "#/definitions/positiveIntegerDefault0" },
1522 pattern: {
1523 type: "string",
1524 format: "regex"
1525 },
1526 additionalItems: {
1527 anyOf: [
1528 { type: "boolean" },
1529 { $ref: "#" }
1530 ],
1531 default: { }
1532 },
1533 items: {
1534 anyOf: [
1535 { $ref: "#" },
1536 { $ref: "#/definitions/schemaArray" }
1537 ],
1538 default: { }
1539 },
1540 maxItems: { $ref: "#/definitions/positiveInteger" },
1541 minItems: { $ref: "#/definitions/positiveIntegerDefault0" },
1542 uniqueItems: {
1543 type: "boolean",
1544 default: false
1545 },
1546 maxProperties: { $ref: "#/definitions/positiveInteger" },
1547 minProperties: { $ref: "#/definitions/positiveIntegerDefault0" },
1548 required: { $ref: "#/definitions/stringArray" },
1549 additionalProperties: {
1550 anyOf: [
1551 { type: "boolean" },
1552 { $ref: "#" }
1553 ],
1554 default: { }
1555 },
1556 definitions: {
1557 type: "object",
1558 additionalProperties: { $ref: "#" },
1559 default: { }
1560 },
1561 properties: {
1562 type: "object",
1563 additionalProperties: { $ref: "#" },
1564 default: { }
1565 },
1566 patternProperties: {
1567 type: "object",
1568 additionalProperties: { $ref: "#" },
1569 default: { }
1570 },
1571 dependencies: {
1572 type: "object",
1573 additionalProperties: {
1574 anyOf: [
1575 { $ref: "#" },
1576 { $ref: "#/definitions/stringArray" }
1577 ]
1578 }
1579 },
1580 enum: {
1581 type: "array",
1582 minItems: 1,
1583 uniqueItems: true
1584 },
1585 type: {
1586 anyOf: [
1587 { $ref: "#/definitions/simpleTypes" },
1588 {
1589 type: "array",
1590 items: { $ref: "#/definitions/simpleTypes" },
1591 minItems: 1,
1592 uniqueItems: true
1593 }
1594 ]
1595 },
1596 format: { type: "string" },
1597 allOf: { $ref: "#/definitions/schemaArray" },
1598 anyOf: { $ref: "#/definitions/schemaArray" },
1599 oneOf: { $ref: "#/definitions/schemaArray" },
1600 not: { $ref: "#" }
1601 },
1602 dependencies: {
1603 exclusiveMaximum: ["maximum"],
1604 exclusiveMinimum: ["minimum"]
1605 },
1606 default: { }
1607};
1608
1609//------------------------------------------------------------------------------
1610// Public Interface
1611//------------------------------------------------------------------------------
1612
1613var ajvOrig = (additionalOptions = {}) => {
1614 const ajv = new Ajv__default["default"]({
1615 meta: false,
1616 useDefaults: true,
1617 validateSchema: false,
1618 missingRefs: "ignore",
1619 verbose: true,
1620 schemaId: "auto",
1621 ...additionalOptions
1622 });
1623
1624 ajv.addMetaSchema(metaSchema);
1625 // eslint-disable-next-line no-underscore-dangle
1626 ajv._opts.defaultMeta = metaSchema.id;
1627
1628 return ajv;
1629};
1630
1631/**
1632 * @fileoverview Defines a schema for configs.
1633 * @author Sylvan Mably
1634 */
1635
1636const baseConfigProperties = {
1637 $schema: { type: "string" },
1638 env: { type: "object" },
1639 extends: { $ref: "#/definitions/stringOrStrings" },
1640 globals: { type: "object" },
1641 overrides: {
1642 type: "array",
1643 items: { $ref: "#/definitions/overrideConfig" },
1644 additionalItems: false
1645 },
1646 parser: { type: ["string", "null"] },
1647 parserOptions: { type: "object" },
1648 plugins: { type: "array" },
1649 processor: { type: "string" },
1650 rules: { type: "object" },
1651 settings: { type: "object" },
1652 noInlineConfig: { type: "boolean" },
1653 reportUnusedDisableDirectives: { type: "boolean" },
1654
1655 ecmaFeatures: { type: "object" } // deprecated; logs a warning when used
1656};
1657
1658const configSchema = {
1659 definitions: {
1660 stringOrStrings: {
1661 oneOf: [
1662 { type: "string" },
1663 {
1664 type: "array",
1665 items: { type: "string" },
1666 additionalItems: false
1667 }
1668 ]
1669 },
1670 stringOrStringsRequired: {
1671 oneOf: [
1672 { type: "string" },
1673 {
1674 type: "array",
1675 items: { type: "string" },
1676 additionalItems: false,
1677 minItems: 1
1678 }
1679 ]
1680 },
1681
1682 // Config at top-level.
1683 objectConfig: {
1684 type: "object",
1685 properties: {
1686 root: { type: "boolean" },
1687 ignorePatterns: { $ref: "#/definitions/stringOrStrings" },
1688 ...baseConfigProperties
1689 },
1690 additionalProperties: false
1691 },
1692
1693 // Config in `overrides`.
1694 overrideConfig: {
1695 type: "object",
1696 properties: {
1697 excludedFiles: { $ref: "#/definitions/stringOrStrings" },
1698 files: { $ref: "#/definitions/stringOrStringsRequired" },
1699 ...baseConfigProperties
1700 },
1701 required: ["files"],
1702 additionalProperties: false
1703 }
1704 },
1705
1706 $ref: "#/definitions/objectConfig"
1707};
1708
1709/**
1710 * @fileoverview Defines environment settings and globals.
1711 * @author Elan Shanker
1712 */
1713
1714//------------------------------------------------------------------------------
1715// Helpers
1716//------------------------------------------------------------------------------
1717
1718/**
1719 * Get the object that has difference.
1720 * @param {Record<string,boolean>} current The newer object.
1721 * @param {Record<string,boolean>} prev The older object.
1722 * @returns {Record<string,boolean>} The difference object.
1723 */
1724function getDiff(current, prev) {
1725 const retv = {};
1726
1727 for (const [key, value] of Object.entries(current)) {
1728 if (!Object.hasOwnProperty.call(prev, key)) {
1729 retv[key] = value;
1730 }
1731 }
1732
1733 return retv;
1734}
1735
1736const newGlobals2015 = getDiff(globals__default["default"].es2015, globals__default["default"].es5); // 19 variables such as Promise, Map, ...
1737const newGlobals2017 = {
1738 Atomics: false,
1739 SharedArrayBuffer: false
1740};
1741const newGlobals2020 = {
1742 BigInt: false,
1743 BigInt64Array: false,
1744 BigUint64Array: false,
1745 globalThis: false
1746};
1747
1748const newGlobals2021 = {
1749 AggregateError: false,
1750 FinalizationRegistry: false,
1751 WeakRef: false
1752};
1753
1754//------------------------------------------------------------------------------
1755// Public Interface
1756//------------------------------------------------------------------------------
1757
1758/** @type {Map<string, import("../lib/shared/types").Environment>} */
1759var environments = new Map(Object.entries({
1760
1761 // Language
1762 builtin: {
1763 globals: globals__default["default"].es5
1764 },
1765 es6: {
1766 globals: newGlobals2015,
1767 parserOptions: {
1768 ecmaVersion: 6
1769 }
1770 },
1771 es2015: {
1772 globals: newGlobals2015,
1773 parserOptions: {
1774 ecmaVersion: 6
1775 }
1776 },
1777 es2016: {
1778 globals: newGlobals2015,
1779 parserOptions: {
1780 ecmaVersion: 7
1781 }
1782 },
1783 es2017: {
1784 globals: { ...newGlobals2015, ...newGlobals2017 },
1785 parserOptions: {
1786 ecmaVersion: 8
1787 }
1788 },
1789 es2018: {
1790 globals: { ...newGlobals2015, ...newGlobals2017 },
1791 parserOptions: {
1792 ecmaVersion: 9
1793 }
1794 },
1795 es2019: {
1796 globals: { ...newGlobals2015, ...newGlobals2017 },
1797 parserOptions: {
1798 ecmaVersion: 10
1799 }
1800 },
1801 es2020: {
1802 globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020 },
1803 parserOptions: {
1804 ecmaVersion: 11
1805 }
1806 },
1807 es2021: {
1808 globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
1809 parserOptions: {
1810 ecmaVersion: 12
1811 }
1812 },
1813 es2022: {
1814 globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
1815 parserOptions: {
1816 ecmaVersion: 13
1817 }
1818 },
1819 es2023: {
1820 globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
1821 parserOptions: {
1822 ecmaVersion: 14
1823 }
1824 },
1825 es2024: {
1826 globals: { ...newGlobals2015, ...newGlobals2017, ...newGlobals2020, ...newGlobals2021 },
1827 parserOptions: {
1828 ecmaVersion: 15
1829 }
1830 },
1831
1832 // Platforms
1833 browser: {
1834 globals: globals__default["default"].browser
1835 },
1836 node: {
1837 globals: globals__default["default"].node,
1838 parserOptions: {
1839 ecmaFeatures: {
1840 globalReturn: true
1841 }
1842 }
1843 },
1844 "shared-node-browser": {
1845 globals: globals__default["default"]["shared-node-browser"]
1846 },
1847 worker: {
1848 globals: globals__default["default"].worker
1849 },
1850 serviceworker: {
1851 globals: globals__default["default"].serviceworker
1852 },
1853
1854 // Frameworks
1855 commonjs: {
1856 globals: globals__default["default"].commonjs,
1857 parserOptions: {
1858 ecmaFeatures: {
1859 globalReturn: true
1860 }
1861 }
1862 },
1863 amd: {
1864 globals: globals__default["default"].amd
1865 },
1866 mocha: {
1867 globals: globals__default["default"].mocha
1868 },
1869 jasmine: {
1870 globals: globals__default["default"].jasmine
1871 },
1872 jest: {
1873 globals: globals__default["default"].jest
1874 },
1875 phantomjs: {
1876 globals: globals__default["default"].phantomjs
1877 },
1878 jquery: {
1879 globals: globals__default["default"].jquery
1880 },
1881 qunit: {
1882 globals: globals__default["default"].qunit
1883 },
1884 prototypejs: {
1885 globals: globals__default["default"].prototypejs
1886 },
1887 shelljs: {
1888 globals: globals__default["default"].shelljs
1889 },
1890 meteor: {
1891 globals: globals__default["default"].meteor
1892 },
1893 mongo: {
1894 globals: globals__default["default"].mongo
1895 },
1896 protractor: {
1897 globals: globals__default["default"].protractor
1898 },
1899 applescript: {
1900 globals: globals__default["default"].applescript
1901 },
1902 nashorn: {
1903 globals: globals__default["default"].nashorn
1904 },
1905 atomtest: {
1906 globals: globals__default["default"].atomtest
1907 },
1908 embertest: {
1909 globals: globals__default["default"].embertest
1910 },
1911 webextensions: {
1912 globals: globals__default["default"].webextensions
1913 },
1914 greasemonkey: {
1915 globals: globals__default["default"].greasemonkey
1916 }
1917}));
1918
1919/**
1920 * @fileoverview Validates configs.
1921 * @author Brandon Mills
1922 */
1923
1924const ajv = ajvOrig();
1925
1926const ruleValidators = new WeakMap();
1927const noop = Function.prototype;
1928
1929//------------------------------------------------------------------------------
1930// Private
1931//------------------------------------------------------------------------------
1932let validateSchema;
1933const severityMap = {
1934 error: 2,
1935 warn: 1,
1936 off: 0
1937};
1938
1939const validated = new WeakSet();
1940
1941//-----------------------------------------------------------------------------
1942// Exports
1943//-----------------------------------------------------------------------------
1944
1945class ConfigValidator {
1946 constructor({ builtInRules = new Map() } = {}) {
1947 this.builtInRules = builtInRules;
1948 }
1949
1950 /**
1951 * Gets a complete options schema for a rule.
1952 * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object
1953 * @returns {Object} JSON Schema for the rule's options.
1954 */
1955 getRuleOptionsSchema(rule) {
1956 if (!rule) {
1957 return null;
1958 }
1959
1960 const schema = rule.schema || rule.meta && rule.meta.schema;
1961
1962 // Given a tuple of schemas, insert warning level at the beginning
1963 if (Array.isArray(schema)) {
1964 if (schema.length) {
1965 return {
1966 type: "array",
1967 items: schema,
1968 minItems: 0,
1969 maxItems: schema.length
1970 };
1971 }
1972 return {
1973 type: "array",
1974 minItems: 0,
1975 maxItems: 0
1976 };
1977
1978 }
1979
1980 // Given a full schema, leave it alone
1981 return schema || null;
1982 }
1983
1984 /**
1985 * Validates a rule's severity and returns the severity value. Throws an error if the severity is invalid.
1986 * @param {options} options The given options for the rule.
1987 * @returns {number|string} The rule's severity value
1988 */
1989 validateRuleSeverity(options) {
1990 const severity = Array.isArray(options) ? options[0] : options;
1991 const normSeverity = typeof severity === "string" ? severityMap[severity.toLowerCase()] : severity;
1992
1993 if (normSeverity === 0 || normSeverity === 1 || normSeverity === 2) {
1994 return normSeverity;
1995 }
1996
1997 throw new Error(`\tSeverity should be one of the following: 0 = off, 1 = warn, 2 = error (you passed '${util__default["default"].inspect(severity).replace(/'/gu, "\"").replace(/\n/gu, "")}').\n`);
1998
1999 }
2000
2001 /**
2002 * Validates the non-severity options passed to a rule, based on its schema.
2003 * @param {{create: Function}} rule The rule to validate
2004 * @param {Array} localOptions The options for the rule, excluding severity
2005 * @returns {void}
2006 */
2007 validateRuleSchema(rule, localOptions) {
2008 if (!ruleValidators.has(rule)) {
2009 const schema = this.getRuleOptionsSchema(rule);
2010
2011 if (schema) {
2012 ruleValidators.set(rule, ajv.compile(schema));
2013 }
2014 }
2015
2016 const validateRule = ruleValidators.get(rule);
2017
2018 if (validateRule) {
2019 validateRule(localOptions);
2020 if (validateRule.errors) {
2021 throw new Error(validateRule.errors.map(
2022 error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n`
2023 ).join(""));
2024 }
2025 }
2026 }
2027
2028 /**
2029 * Validates a rule's options against its schema.
2030 * @param {{create: Function}|null} rule The rule that the config is being validated for
2031 * @param {string} ruleId The rule's unique name.
2032 * @param {Array|number} options The given options for the rule.
2033 * @param {string|null} source The name of the configuration source to report in any errors. If null or undefined,
2034 * no source is prepended to the message.
2035 * @returns {void}
2036 */
2037 validateRuleOptions(rule, ruleId, options, source = null) {
2038 try {
2039 const severity = this.validateRuleSeverity(options);
2040
2041 if (severity !== 0) {
2042 this.validateRuleSchema(rule, Array.isArray(options) ? options.slice(1) : []);
2043 }
2044 } catch (err) {
2045 const enhancedMessage = `Configuration for rule "${ruleId}" is invalid:\n${err.message}`;
2046
2047 if (typeof source === "string") {
2048 throw new Error(`${source}:\n\t${enhancedMessage}`);
2049 } else {
2050 throw new Error(enhancedMessage);
2051 }
2052 }
2053 }
2054
2055 /**
2056 * Validates an environment object
2057 * @param {Object} environment The environment config object to validate.
2058 * @param {string} source The name of the configuration source to report in any errors.
2059 * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded environments.
2060 * @returns {void}
2061 */
2062 validateEnvironment(
2063 environment,
2064 source,
2065 getAdditionalEnv = noop
2066 ) {
2067
2068 // not having an environment is ok
2069 if (!environment) {
2070 return;
2071 }
2072
2073 Object.keys(environment).forEach(id => {
2074 const env = getAdditionalEnv(id) || environments.get(id) || null;
2075
2076 if (!env) {
2077 const message = `${source}:\n\tEnvironment key "${id}" is unknown\n`;
2078
2079 throw new Error(message);
2080 }
2081 });
2082 }
2083
2084 /**
2085 * Validates a rules config object
2086 * @param {Object} rulesConfig The rules config object to validate.
2087 * @param {string} source The name of the configuration source to report in any errors.
2088 * @param {function(ruleId:string): Object} getAdditionalRule A map from strings to loaded rules
2089 * @returns {void}
2090 */
2091 validateRules(
2092 rulesConfig,
2093 source,
2094 getAdditionalRule = noop
2095 ) {
2096 if (!rulesConfig) {
2097 return;
2098 }
2099
2100 Object.keys(rulesConfig).forEach(id => {
2101 const rule = getAdditionalRule(id) || this.builtInRules.get(id) || null;
2102
2103 this.validateRuleOptions(rule, id, rulesConfig[id], source);
2104 });
2105 }
2106
2107 /**
2108 * Validates a `globals` section of a config file
2109 * @param {Object} globalsConfig The `globals` section
2110 * @param {string|null} source The name of the configuration source to report in the event of an error.
2111 * @returns {void}
2112 */
2113 validateGlobals(globalsConfig, source = null) {
2114 if (!globalsConfig) {
2115 return;
2116 }
2117
2118 Object.entries(globalsConfig)
2119 .forEach(([configuredGlobal, configuredValue]) => {
2120 try {
2121 normalizeConfigGlobal(configuredValue);
2122 } catch (err) {
2123 throw new Error(`ESLint configuration of global '${configuredGlobal}' in ${source} is invalid:\n${err.message}`);
2124 }
2125 });
2126 }
2127
2128 /**
2129 * Validate `processor` configuration.
2130 * @param {string|undefined} processorName The processor name.
2131 * @param {string} source The name of config file.
2132 * @param {function(id:string): Processor} getProcessor The getter of defined processors.
2133 * @returns {void}
2134 */
2135 validateProcessor(processorName, source, getProcessor) {
2136 if (processorName && !getProcessor(processorName)) {
2137 throw new Error(`ESLint configuration of processor in '${source}' is invalid: '${processorName}' was not found.`);
2138 }
2139 }
2140
2141 /**
2142 * Formats an array of schema validation errors.
2143 * @param {Array} errors An array of error messages to format.
2144 * @returns {string} Formatted error message
2145 */
2146 formatErrors(errors) {
2147 return errors.map(error => {
2148 if (error.keyword === "additionalProperties") {
2149 const formattedPropertyPath = error.dataPath.length ? `${error.dataPath.slice(1)}.${error.params.additionalProperty}` : error.params.additionalProperty;
2150
2151 return `Unexpected top-level property "${formattedPropertyPath}"`;
2152 }
2153 if (error.keyword === "type") {
2154 const formattedField = error.dataPath.slice(1);
2155 const formattedExpectedType = Array.isArray(error.schema) ? error.schema.join("/") : error.schema;
2156 const formattedValue = JSON.stringify(error.data);
2157
2158 return `Property "${formattedField}" is the wrong type (expected ${formattedExpectedType} but got \`${formattedValue}\`)`;
2159 }
2160
2161 const field = error.dataPath[0] === "." ? error.dataPath.slice(1) : error.dataPath;
2162
2163 return `"${field}" ${error.message}. Value: ${JSON.stringify(error.data)}`;
2164 }).map(message => `\t- ${message}.\n`).join("");
2165 }
2166
2167 /**
2168 * Validates the top level properties of the config object.
2169 * @param {Object} config The config object to validate.
2170 * @param {string} source The name of the configuration source to report in any errors.
2171 * @returns {void}
2172 */
2173 validateConfigSchema(config, source = null) {
2174 validateSchema = validateSchema || ajv.compile(configSchema);
2175
2176 if (!validateSchema(config)) {
2177 throw new Error(`ESLint configuration in ${source} is invalid:\n${this.formatErrors(validateSchema.errors)}`);
2178 }
2179
2180 if (Object.hasOwnProperty.call(config, "ecmaFeatures")) {
2181 emitDeprecationWarning(source, "ESLINT_LEGACY_ECMAFEATURES");
2182 }
2183 }
2184
2185 /**
2186 * Validates an entire config object.
2187 * @param {Object} config The config object to validate.
2188 * @param {string} source The name of the configuration source to report in any errors.
2189 * @param {function(ruleId:string): Object} [getAdditionalRule] A map from strings to loaded rules.
2190 * @param {function(envId:string): Object} [getAdditionalEnv] A map from strings to loaded envs.
2191 * @returns {void}
2192 */
2193 validate(config, source, getAdditionalRule, getAdditionalEnv) {
2194 this.validateConfigSchema(config, source);
2195 this.validateRules(config.rules, source, getAdditionalRule);
2196 this.validateEnvironment(config.env, source, getAdditionalEnv);
2197 this.validateGlobals(config.globals, source);
2198
2199 for (const override of config.overrides || []) {
2200 this.validateRules(override.rules, source, getAdditionalRule);
2201 this.validateEnvironment(override.env, source, getAdditionalEnv);
2202 this.validateGlobals(config.globals, source);
2203 }
2204 }
2205
2206 /**
2207 * Validate config array object.
2208 * @param {ConfigArray} configArray The config array to validate.
2209 * @returns {void}
2210 */
2211 validateConfigArray(configArray) {
2212 const getPluginEnv = Map.prototype.get.bind(configArray.pluginEnvironments);
2213 const getPluginProcessor = Map.prototype.get.bind(configArray.pluginProcessors);
2214 const getPluginRule = Map.prototype.get.bind(configArray.pluginRules);
2215
2216 // Validate.
2217 for (const element of configArray) {
2218 if (validated.has(element)) {
2219 continue;
2220 }
2221 validated.add(element);
2222
2223 this.validateEnvironment(element.env, element.name, getPluginEnv);
2224 this.validateGlobals(element.globals, element.name);
2225 this.validateProcessor(element.processor, element.name, getPluginProcessor);
2226 this.validateRules(element.rules, element.name, getPluginRule);
2227 }
2228 }
2229
2230}
2231
2232/**
2233 * @fileoverview Common helpers for naming of plugins, formatters and configs
2234 */
2235
2236const NAMESPACE_REGEX = /^@.*\//iu;
2237
2238/**
2239 * Brings package name to correct format based on prefix
2240 * @param {string} name The name of the package.
2241 * @param {string} prefix Can be either "eslint-plugin", "eslint-config" or "eslint-formatter"
2242 * @returns {string} Normalized name of the package
2243 * @private
2244 */
2245function normalizePackageName(name, prefix) {
2246 let normalizedName = name;
2247
2248 /**
2249 * On Windows, name can come in with Windows slashes instead of Unix slashes.
2250 * Normalize to Unix first to avoid errors later on.
2251 * https://github.com/eslint/eslint/issues/5644
2252 */
2253 if (normalizedName.includes("\\")) {
2254 normalizedName = normalizedName.replace(/\\/gu, "/");
2255 }
2256
2257 if (normalizedName.charAt(0) === "@") {
2258
2259 /**
2260 * it's a scoped package
2261 * package name is the prefix, or just a username
2262 */
2263 const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`, "u"),
2264 scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`, "u");
2265
2266 if (scopedPackageShortcutRegex.test(normalizedName)) {
2267 normalizedName = normalizedName.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
2268 } else if (!scopedPackageNameRegex.test(normalizedName.split("/")[1])) {
2269
2270 /**
2271 * for scoped packages, insert the prefix after the first / unless
2272 * the path is already @scope/eslint or @scope/eslint-xxx-yyy
2273 */
2274 normalizedName = normalizedName.replace(/^@([^/]+)\/(.*)$/u, `@$1/${prefix}-$2`);
2275 }
2276 } else if (!normalizedName.startsWith(`${prefix}-`)) {
2277 normalizedName = `${prefix}-${normalizedName}`;
2278 }
2279
2280 return normalizedName;
2281}
2282
2283/**
2284 * Removes the prefix from a fullname.
2285 * @param {string} fullname The term which may have the prefix.
2286 * @param {string} prefix The prefix to remove.
2287 * @returns {string} The term without prefix.
2288 */
2289function getShorthandName(fullname, prefix) {
2290 if (fullname[0] === "@") {
2291 let matchResult = new RegExp(`^(@[^/]+)/${prefix}$`, "u").exec(fullname);
2292
2293 if (matchResult) {
2294 return matchResult[1];
2295 }
2296
2297 matchResult = new RegExp(`^(@[^/]+)/${prefix}-(.+)$`, "u").exec(fullname);
2298 if (matchResult) {
2299 return `${matchResult[1]}/${matchResult[2]}`;
2300 }
2301 } else if (fullname.startsWith(`${prefix}-`)) {
2302 return fullname.slice(prefix.length + 1);
2303 }
2304
2305 return fullname;
2306}
2307
2308/**
2309 * Gets the scope (namespace) of a term.
2310 * @param {string} term The term which may have the namespace.
2311 * @returns {string} The namespace of the term if it has one.
2312 */
2313function getNamespaceFromTerm(term) {
2314 const match = term.match(NAMESPACE_REGEX);
2315
2316 return match ? match[0] : "";
2317}
2318
2319var naming = {
2320 __proto__: null,
2321 normalizePackageName: normalizePackageName,
2322 getShorthandName: getShorthandName,
2323 getNamespaceFromTerm: getNamespaceFromTerm
2324};
2325
2326/**
2327 * Utility for resolving a module relative to another module
2328 * @author Teddy Katz
2329 */
2330
2331/*
2332 * `Module.createRequire` is added in v12.2.0. It supports URL as well.
2333 * We only support the case where the argument is a filepath, not a URL.
2334 */
2335const createRequire = Module__default["default"].createRequire;
2336
2337/**
2338 * Resolves a Node module relative to another module
2339 * @param {string} moduleName The name of a Node module, or a path to a Node module.
2340 * @param {string} relativeToPath An absolute path indicating the module that `moduleName` should be resolved relative to. This must be
2341 * a file rather than a directory, but the file need not actually exist.
2342 * @returns {string} The absolute path that would result from calling `require.resolve(moduleName)` in a file located at `relativeToPath`
2343 */
2344function resolve(moduleName, relativeToPath) {
2345 try {
2346 return createRequire(relativeToPath).resolve(moduleName);
2347 } catch (error) {
2348
2349 // This `if` block is for older Node.js than 12.0.0. We can remove this block in the future.
2350 if (
2351 typeof error === "object" &&
2352 error !== null &&
2353 error.code === "MODULE_NOT_FOUND" &&
2354 !error.requireStack &&
2355 error.message.includes(moduleName)
2356 ) {
2357 error.message += `\nRequire stack:\n- ${relativeToPath}`;
2358 }
2359 throw error;
2360 }
2361}
2362
2363var ModuleResolver = {
2364 __proto__: null,
2365 resolve: resolve
2366};
2367
2368/**
2369 * @fileoverview The factory of `ConfigArray` objects.
2370 *
2371 * This class provides methods to create `ConfigArray` instance.
2372 *
2373 * - `create(configData, options)`
2374 * Create a `ConfigArray` instance from a config data. This is to handle CLI
2375 * options except `--config`.
2376 * - `loadFile(filePath, options)`
2377 * Create a `ConfigArray` instance from a config file. This is to handle
2378 * `--config` option. If the file was not found, throws the following error:
2379 * - If the filename was `*.js`, a `MODULE_NOT_FOUND` error.
2380 * - If the filename was `package.json`, an IO error or an
2381 * `ESLINT_CONFIG_FIELD_NOT_FOUND` error.
2382 * - Otherwise, an IO error such as `ENOENT`.
2383 * - `loadInDirectory(directoryPath, options)`
2384 * Create a `ConfigArray` instance from a config file which is on a given
2385 * directory. This tries to load `.eslintrc.*` or `package.json`. If not
2386 * found, returns an empty `ConfigArray`.
2387 * - `loadESLintIgnore(filePath)`
2388 * Create a `ConfigArray` instance from a config file that is `.eslintignore`
2389 * format. This is to handle `--ignore-path` option.
2390 * - `loadDefaultESLintIgnore()`
2391 * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in
2392 * the current working directory.
2393 *
2394 * `ConfigArrayFactory` class has the responsibility that loads configuration
2395 * files, including loading `extends`, `parser`, and `plugins`. The created
2396 * `ConfigArray` instance has the loaded `extends`, `parser`, and `plugins`.
2397 *
2398 * But this class doesn't handle cascading. `CascadingConfigArrayFactory` class
2399 * handles cascading and hierarchy.
2400 *
2401 * @author Toru Nagashima <https://github.com/mysticatea>
2402 */
2403
2404const require$1 = Module.createRequire(require('url').pathToFileURL(__filename).toString());
2405
2406const debug$2 = debugOrig__default["default"]("eslintrc:config-array-factory");
2407
2408//------------------------------------------------------------------------------
2409// Helpers
2410//------------------------------------------------------------------------------
2411
2412const configFilenames = [
2413 ".eslintrc.js",
2414 ".eslintrc.cjs",
2415 ".eslintrc.yaml",
2416 ".eslintrc.yml",
2417 ".eslintrc.json",
2418 ".eslintrc",
2419 "package.json"
2420];
2421
2422// Define types for VSCode IntelliSense.
2423/** @typedef {import("./shared/types").ConfigData} ConfigData */
2424/** @typedef {import("./shared/types").OverrideConfigData} OverrideConfigData */
2425/** @typedef {import("./shared/types").Parser} Parser */
2426/** @typedef {import("./shared/types").Plugin} Plugin */
2427/** @typedef {import("./shared/types").Rule} Rule */
2428/** @typedef {import("./config-array/config-dependency").DependentParser} DependentParser */
2429/** @typedef {import("./config-array/config-dependency").DependentPlugin} DependentPlugin */
2430/** @typedef {ConfigArray[0]} ConfigArrayElement */
2431
2432/**
2433 * @typedef {Object} ConfigArrayFactoryOptions
2434 * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
2435 * @property {string} [cwd] The path to the current working directory.
2436 * @property {string} [resolvePluginsRelativeTo] A path to the directory that plugins should be resolved from. Defaults to `cwd`.
2437 * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
2438 * @property {Object} [resolver=ModuleResolver] The module resolver object.
2439 * @property {string} eslintAllPath The path to the definitions for eslint:all.
2440 * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
2441 * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
2442 * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
2443 */
2444
2445/**
2446 * @typedef {Object} ConfigArrayFactoryInternalSlots
2447 * @property {Map<string,Plugin>} additionalPluginPool The map for additional plugins.
2448 * @property {string} cwd The path to the current working directory.
2449 * @property {string | undefined} resolvePluginsRelativeTo An absolute path the the directory that plugins should be resolved from.
2450 * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
2451 * @property {Object} [resolver=ModuleResolver] The module resolver object.
2452 * @property {string} eslintAllPath The path to the definitions for eslint:all.
2453 * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
2454 * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
2455 * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
2456 */
2457
2458/**
2459 * @typedef {Object} ConfigArrayFactoryLoadingContext
2460 * @property {string} filePath The path to the current configuration.
2461 * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
2462 * @property {string} name The name of the current configuration.
2463 * @property {string} pluginBasePath The base path to resolve plugins.
2464 * @property {"config" | "ignore" | "implicit-processor"} type The type of the current configuration. This is `"config"` in normal. This is `"ignore"` if it came from `.eslintignore`. This is `"implicit-processor"` if it came from legacy file-extension processors.
2465 */
2466
2467/**
2468 * @typedef {Object} ConfigArrayFactoryLoadingContext
2469 * @property {string} filePath The path to the current configuration.
2470 * @property {string} matchBasePath The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
2471 * @property {string} name The name of the current configuration.
2472 * @property {"config" | "ignore" | "implicit-processor"} type The type of the current configuration. This is `"config"` in normal. This is `"ignore"` if it came from `.eslintignore`. This is `"implicit-processor"` if it came from legacy file-extension processors.
2473 */
2474
2475/** @type {WeakMap<ConfigArrayFactory, ConfigArrayFactoryInternalSlots>} */
2476const internalSlotsMap$1 = new WeakMap();
2477
2478/** @type {WeakMap<object, Plugin>} */
2479const normalizedPlugins = new WeakMap();
2480
2481/**
2482 * Check if a given string is a file path.
2483 * @param {string} nameOrPath A module name or file path.
2484 * @returns {boolean} `true` if the `nameOrPath` is a file path.
2485 */
2486function isFilePath(nameOrPath) {
2487 return (
2488 /^\.{1,2}[/\\]/u.test(nameOrPath) ||
2489 path__default["default"].isAbsolute(nameOrPath)
2490 );
2491}
2492
2493/**
2494 * Convenience wrapper for synchronously reading file contents.
2495 * @param {string} filePath The filename to read.
2496 * @returns {string} The file contents, with the BOM removed.
2497 * @private
2498 */
2499function readFile(filePath) {
2500 return fs__default["default"].readFileSync(filePath, "utf8").replace(/^\ufeff/u, "");
2501}
2502
2503/**
2504 * Loads a YAML configuration from a file.
2505 * @param {string} filePath The filename to load.
2506 * @returns {ConfigData} The configuration object from the file.
2507 * @throws {Error} If the file cannot be read.
2508 * @private
2509 */
2510function loadYAMLConfigFile(filePath) {
2511 debug$2(`Loading YAML config file: ${filePath}`);
2512
2513 // lazy load YAML to improve performance when not used
2514 const yaml = require$1("js-yaml");
2515
2516 try {
2517
2518 // empty YAML file can be null, so always use
2519 return yaml.load(readFile(filePath)) || {};
2520 } catch (e) {
2521 debug$2(`Error reading YAML file: ${filePath}`);
2522 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
2523 throw e;
2524 }
2525}
2526
2527/**
2528 * Loads a JSON configuration from a file.
2529 * @param {string} filePath The filename to load.
2530 * @returns {ConfigData} The configuration object from the file.
2531 * @throws {Error} If the file cannot be read.
2532 * @private
2533 */
2534function loadJSONConfigFile(filePath) {
2535 debug$2(`Loading JSON config file: ${filePath}`);
2536
2537 try {
2538 return JSON.parse(stripComments__default["default"](readFile(filePath)));
2539 } catch (e) {
2540 debug$2(`Error reading JSON file: ${filePath}`);
2541 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
2542 e.messageTemplate = "failed-to-read-json";
2543 e.messageData = {
2544 path: filePath,
2545 message: e.message
2546 };
2547 throw e;
2548 }
2549}
2550
2551/**
2552 * Loads a legacy (.eslintrc) configuration from a file.
2553 * @param {string} filePath The filename to load.
2554 * @returns {ConfigData} The configuration object from the file.
2555 * @throws {Error} If the file cannot be read.
2556 * @private
2557 */
2558function loadLegacyConfigFile(filePath) {
2559 debug$2(`Loading legacy config file: ${filePath}`);
2560
2561 // lazy load YAML to improve performance when not used
2562 const yaml = require$1("js-yaml");
2563
2564 try {
2565 return yaml.load(stripComments__default["default"](readFile(filePath))) || /* istanbul ignore next */ {};
2566 } catch (e) {
2567 debug$2("Error reading YAML file: %s\n%o", filePath, e);
2568 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
2569 throw e;
2570 }
2571}
2572
2573/**
2574 * Loads a JavaScript configuration from a file.
2575 * @param {string} filePath The filename to load.
2576 * @returns {ConfigData} The configuration object from the file.
2577 * @throws {Error} If the file cannot be read.
2578 * @private
2579 */
2580function loadJSConfigFile(filePath) {
2581 debug$2(`Loading JS config file: ${filePath}`);
2582 try {
2583 return importFresh__default["default"](filePath);
2584 } catch (e) {
2585 debug$2(`Error reading JavaScript file: ${filePath}`);
2586 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
2587 throw e;
2588 }
2589}
2590
2591/**
2592 * Loads a configuration from a package.json file.
2593 * @param {string} filePath The filename to load.
2594 * @returns {ConfigData} The configuration object from the file.
2595 * @throws {Error} If the file cannot be read.
2596 * @private
2597 */
2598function loadPackageJSONConfigFile(filePath) {
2599 debug$2(`Loading package.json config file: ${filePath}`);
2600 try {
2601 const packageData = loadJSONConfigFile(filePath);
2602
2603 if (!Object.hasOwnProperty.call(packageData, "eslintConfig")) {
2604 throw Object.assign(
2605 new Error("package.json file doesn't have 'eslintConfig' field."),
2606 { code: "ESLINT_CONFIG_FIELD_NOT_FOUND" }
2607 );
2608 }
2609
2610 return packageData.eslintConfig;
2611 } catch (e) {
2612 debug$2(`Error reading package.json file: ${filePath}`);
2613 e.message = `Cannot read config file: ${filePath}\nError: ${e.message}`;
2614 throw e;
2615 }
2616}
2617
2618/**
2619 * Loads a `.eslintignore` from a file.
2620 * @param {string} filePath The filename to load.
2621 * @returns {string[]} The ignore patterns from the file.
2622 * @private
2623 */
2624function loadESLintIgnoreFile(filePath) {
2625 debug$2(`Loading .eslintignore file: ${filePath}`);
2626
2627 try {
2628 return readFile(filePath)
2629 .split(/\r?\n/gu)
2630 .filter(line => line.trim() !== "" && !line.startsWith("#"));
2631 } catch (e) {
2632 debug$2(`Error reading .eslintignore file: ${filePath}`);
2633 e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
2634 throw e;
2635 }
2636}
2637
2638/**
2639 * Creates an error to notify about a missing config to extend from.
2640 * @param {string} configName The name of the missing config.
2641 * @param {string} importerName The name of the config that imported the missing config
2642 * @param {string} messageTemplate The text template to source error strings from.
2643 * @returns {Error} The error object to throw
2644 * @private
2645 */
2646function configInvalidError(configName, importerName, messageTemplate) {
2647 return Object.assign(
2648 new Error(`Failed to load config "${configName}" to extend from.`),
2649 {
2650 messageTemplate,
2651 messageData: { configName, importerName }
2652 }
2653 );
2654}
2655
2656/**
2657 * Loads a configuration file regardless of the source. Inspects the file path
2658 * to determine the correctly way to load the config file.
2659 * @param {string} filePath The path to the configuration.
2660 * @returns {ConfigData|null} The configuration information.
2661 * @private
2662 */
2663function loadConfigFile(filePath) {
2664 switch (path__default["default"].extname(filePath)) {
2665 case ".js":
2666 case ".cjs":
2667 return loadJSConfigFile(filePath);
2668
2669 case ".json":
2670 if (path__default["default"].basename(filePath) === "package.json") {
2671 return loadPackageJSONConfigFile(filePath);
2672 }
2673 return loadJSONConfigFile(filePath);
2674
2675 case ".yaml":
2676 case ".yml":
2677 return loadYAMLConfigFile(filePath);
2678
2679 default:
2680 return loadLegacyConfigFile(filePath);
2681 }
2682}
2683
2684/**
2685 * Write debug log.
2686 * @param {string} request The requested module name.
2687 * @param {string} relativeTo The file path to resolve the request relative to.
2688 * @param {string} filePath The resolved file path.
2689 * @returns {void}
2690 */
2691function writeDebugLogForLoading(request, relativeTo, filePath) {
2692 /* istanbul ignore next */
2693 if (debug$2.enabled) {
2694 let nameAndVersion = null;
2695
2696 try {
2697 const packageJsonPath = resolve(
2698 `${request}/package.json`,
2699 relativeTo
2700 );
2701 const { version = "unknown" } = require$1(packageJsonPath);
2702
2703 nameAndVersion = `${request}@${version}`;
2704 } catch (error) {
2705 debug$2("package.json was not found:", error.message);
2706 nameAndVersion = request;
2707 }
2708
2709 debug$2("Loaded: %s (%s)", nameAndVersion, filePath);
2710 }
2711}
2712
2713/**
2714 * Create a new context with default values.
2715 * @param {ConfigArrayFactoryInternalSlots} slots The internal slots.
2716 * @param {"config" | "ignore" | "implicit-processor" | undefined} providedType The type of the current configuration. Default is `"config"`.
2717 * @param {string | undefined} providedName The name of the current configuration. Default is the relative path from `cwd` to `filePath`.
2718 * @param {string | undefined} providedFilePath The path to the current configuration. Default is empty string.
2719 * @param {string | undefined} providedMatchBasePath The type of the current configuration. Default is the directory of `filePath` or `cwd`.
2720 * @returns {ConfigArrayFactoryLoadingContext} The created context.
2721 */
2722function createContext(
2723 { cwd, resolvePluginsRelativeTo },
2724 providedType,
2725 providedName,
2726 providedFilePath,
2727 providedMatchBasePath
2728) {
2729 const filePath = providedFilePath
2730 ? path__default["default"].resolve(cwd, providedFilePath)
2731 : "";
2732 const matchBasePath =
2733 (providedMatchBasePath && path__default["default"].resolve(cwd, providedMatchBasePath)) ||
2734 (filePath && path__default["default"].dirname(filePath)) ||
2735 cwd;
2736 const name =
2737 providedName ||
2738 (filePath && path__default["default"].relative(cwd, filePath)) ||
2739 "";
2740 const pluginBasePath =
2741 resolvePluginsRelativeTo ||
2742 (filePath && path__default["default"].dirname(filePath)) ||
2743 cwd;
2744 const type = providedType || "config";
2745
2746 return { filePath, matchBasePath, name, pluginBasePath, type };
2747}
2748
2749/**
2750 * Normalize a given plugin.
2751 * - Ensure the object to have four properties: configs, environments, processors, and rules.
2752 * - Ensure the object to not have other properties.
2753 * @param {Plugin} plugin The plugin to normalize.
2754 * @returns {Plugin} The normalized plugin.
2755 */
2756function normalizePlugin(plugin) {
2757
2758 // first check the cache
2759 let normalizedPlugin = normalizedPlugins.get(plugin);
2760
2761 if (normalizedPlugin) {
2762 return normalizedPlugin;
2763 }
2764
2765 normalizedPlugin = {
2766 configs: plugin.configs || {},
2767 environments: plugin.environments || {},
2768 processors: plugin.processors || {},
2769 rules: plugin.rules || {}
2770 };
2771
2772 // save the reference for later
2773 normalizedPlugins.set(plugin, normalizedPlugin);
2774
2775 return normalizedPlugin;
2776}
2777
2778//------------------------------------------------------------------------------
2779// Public Interface
2780//------------------------------------------------------------------------------
2781
2782/**
2783 * The factory of `ConfigArray` objects.
2784 */
2785class ConfigArrayFactory {
2786
2787 /**
2788 * Initialize this instance.
2789 * @param {ConfigArrayFactoryOptions} [options] The map for additional plugins.
2790 */
2791 constructor({
2792 additionalPluginPool = new Map(),
2793 cwd = process.cwd(),
2794 resolvePluginsRelativeTo,
2795 builtInRules,
2796 resolver = ModuleResolver,
2797 eslintAllPath,
2798 getEslintAllConfig,
2799 eslintRecommendedPath,
2800 getEslintRecommendedConfig
2801 } = {}) {
2802 internalSlotsMap$1.set(this, {
2803 additionalPluginPool,
2804 cwd,
2805 resolvePluginsRelativeTo:
2806 resolvePluginsRelativeTo &&
2807 path__default["default"].resolve(cwd, resolvePluginsRelativeTo),
2808 builtInRules,
2809 resolver,
2810 eslintAllPath,
2811 getEslintAllConfig,
2812 eslintRecommendedPath,
2813 getEslintRecommendedConfig
2814 });
2815 }
2816
2817 /**
2818 * Create `ConfigArray` instance from a config data.
2819 * @param {ConfigData|null} configData The config data to create.
2820 * @param {Object} [options] The options.
2821 * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
2822 * @param {string} [options.filePath] The path to this config data.
2823 * @param {string} [options.name] The config name.
2824 * @returns {ConfigArray} Loaded config.
2825 */
2826 create(configData, { basePath, filePath, name } = {}) {
2827 if (!configData) {
2828 return new ConfigArray();
2829 }
2830
2831 const slots = internalSlotsMap$1.get(this);
2832 const ctx = createContext(slots, "config", name, filePath, basePath);
2833 const elements = this._normalizeConfigData(configData, ctx);
2834
2835 return new ConfigArray(...elements);
2836 }
2837
2838 /**
2839 * Load a config file.
2840 * @param {string} filePath The path to a config file.
2841 * @param {Object} [options] The options.
2842 * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
2843 * @param {string} [options.name] The config name.
2844 * @returns {ConfigArray} Loaded config.
2845 */
2846 loadFile(filePath, { basePath, name } = {}) {
2847 const slots = internalSlotsMap$1.get(this);
2848 const ctx = createContext(slots, "config", name, filePath, basePath);
2849
2850 return new ConfigArray(...this._loadConfigData(ctx));
2851 }
2852
2853 /**
2854 * Load the config file on a given directory if exists.
2855 * @param {string} directoryPath The path to a directory.
2856 * @param {Object} [options] The options.
2857 * @param {string} [options.basePath] The base path to resolve relative paths in `overrides[].files`, `overrides[].excludedFiles`, and `ignorePatterns`.
2858 * @param {string} [options.name] The config name.
2859 * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
2860 */
2861 loadInDirectory(directoryPath, { basePath, name } = {}) {
2862 const slots = internalSlotsMap$1.get(this);
2863
2864 for (const filename of configFilenames) {
2865 const ctx = createContext(
2866 slots,
2867 "config",
2868 name,
2869 path__default["default"].join(directoryPath, filename),
2870 basePath
2871 );
2872
2873 if (fs__default["default"].existsSync(ctx.filePath) && fs__default["default"].statSync(ctx.filePath).isFile()) {
2874 let configData;
2875
2876 try {
2877 configData = loadConfigFile(ctx.filePath);
2878 } catch (error) {
2879 if (!error || error.code !== "ESLINT_CONFIG_FIELD_NOT_FOUND") {
2880 throw error;
2881 }
2882 }
2883
2884 if (configData) {
2885 debug$2(`Config file found: ${ctx.filePath}`);
2886 return new ConfigArray(
2887 ...this._normalizeConfigData(configData, ctx)
2888 );
2889 }
2890 }
2891 }
2892
2893 debug$2(`Config file not found on ${directoryPath}`);
2894 return new ConfigArray();
2895 }
2896
2897 /**
2898 * Check if a config file on a given directory exists or not.
2899 * @param {string} directoryPath The path to a directory.
2900 * @returns {string | null} The path to the found config file. If not found then null.
2901 */
2902 static getPathToConfigFileInDirectory(directoryPath) {
2903 for (const filename of configFilenames) {
2904 const filePath = path__default["default"].join(directoryPath, filename);
2905
2906 if (fs__default["default"].existsSync(filePath)) {
2907 if (filename === "package.json") {
2908 try {
2909 loadPackageJSONConfigFile(filePath);
2910 return filePath;
2911 } catch { /* ignore */ }
2912 } else {
2913 return filePath;
2914 }
2915 }
2916 }
2917 return null;
2918 }
2919
2920 /**
2921 * Load `.eslintignore` file.
2922 * @param {string} filePath The path to a `.eslintignore` file to load.
2923 * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
2924 */
2925 loadESLintIgnore(filePath) {
2926 const slots = internalSlotsMap$1.get(this);
2927 const ctx = createContext(
2928 slots,
2929 "ignore",
2930 void 0,
2931 filePath,
2932 slots.cwd
2933 );
2934 const ignorePatterns = loadESLintIgnoreFile(ctx.filePath);
2935
2936 return new ConfigArray(
2937 ...this._normalizeESLintIgnoreData(ignorePatterns, ctx)
2938 );
2939 }
2940
2941 /**
2942 * Load `.eslintignore` file in the current working directory.
2943 * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
2944 */
2945 loadDefaultESLintIgnore() {
2946 const slots = internalSlotsMap$1.get(this);
2947 const eslintIgnorePath = path__default["default"].resolve(slots.cwd, ".eslintignore");
2948 const packageJsonPath = path__default["default"].resolve(slots.cwd, "package.json");
2949
2950 if (fs__default["default"].existsSync(eslintIgnorePath)) {
2951 return this.loadESLintIgnore(eslintIgnorePath);
2952 }
2953 if (fs__default["default"].existsSync(packageJsonPath)) {
2954 const data = loadJSONConfigFile(packageJsonPath);
2955
2956 if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
2957 if (!Array.isArray(data.eslintIgnore)) {
2958 throw new Error("Package.json eslintIgnore property requires an array of paths");
2959 }
2960 const ctx = createContext(
2961 slots,
2962 "ignore",
2963 "eslintIgnore in package.json",
2964 packageJsonPath,
2965 slots.cwd
2966 );
2967
2968 return new ConfigArray(
2969 ...this._normalizeESLintIgnoreData(data.eslintIgnore, ctx)
2970 );
2971 }
2972 }
2973
2974 return new ConfigArray();
2975 }
2976
2977 /**
2978 * Load a given config file.
2979 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
2980 * @returns {IterableIterator<ConfigArrayElement>} Loaded config.
2981 * @private
2982 */
2983 _loadConfigData(ctx) {
2984 return this._normalizeConfigData(loadConfigFile(ctx.filePath), ctx);
2985 }
2986
2987 /**
2988 * Normalize a given `.eslintignore` data to config array elements.
2989 * @param {string[]} ignorePatterns The patterns to ignore files.
2990 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
2991 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
2992 * @private
2993 */
2994 *_normalizeESLintIgnoreData(ignorePatterns, ctx) {
2995 const elements = this._normalizeObjectConfigData(
2996 { ignorePatterns },
2997 ctx
2998 );
2999
3000 // Set `ignorePattern.loose` flag for backward compatibility.
3001 for (const element of elements) {
3002 if (element.ignorePattern) {
3003 element.ignorePattern.loose = true;
3004 }
3005 yield element;
3006 }
3007 }
3008
3009 /**
3010 * Normalize a given config to an array.
3011 * @param {ConfigData} configData The config data to normalize.
3012 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3013 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3014 * @private
3015 */
3016 _normalizeConfigData(configData, ctx) {
3017 const validator = new ConfigValidator();
3018
3019 validator.validateConfigSchema(configData, ctx.name || ctx.filePath);
3020 return this._normalizeObjectConfigData(configData, ctx);
3021 }
3022
3023 /**
3024 * Normalize a given config to an array.
3025 * @param {ConfigData|OverrideConfigData} configData The config data to normalize.
3026 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3027 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3028 * @private
3029 */
3030 *_normalizeObjectConfigData(configData, ctx) {
3031 const { files, excludedFiles, ...configBody } = configData;
3032 const criteria = OverrideTester.create(
3033 files,
3034 excludedFiles,
3035 ctx.matchBasePath
3036 );
3037 const elements = this._normalizeObjectConfigDataBody(configBody, ctx);
3038
3039 // Apply the criteria to every element.
3040 for (const element of elements) {
3041
3042 /*
3043 * Merge the criteria.
3044 * This is for the `overrides` entries that came from the
3045 * configurations of `overrides[].extends`.
3046 */
3047 element.criteria = OverrideTester.and(criteria, element.criteria);
3048
3049 /*
3050 * Remove `root` property to ignore `root` settings which came from
3051 * `extends` in `overrides`.
3052 */
3053 if (element.criteria) {
3054 element.root = void 0;
3055 }
3056
3057 yield element;
3058 }
3059 }
3060
3061 /**
3062 * Normalize a given config to an array.
3063 * @param {ConfigData} configData The config data to normalize.
3064 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3065 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3066 * @private
3067 */
3068 *_normalizeObjectConfigDataBody(
3069 {
3070 env,
3071 extends: extend,
3072 globals,
3073 ignorePatterns,
3074 noInlineConfig,
3075 parser: parserName,
3076 parserOptions,
3077 plugins: pluginList,
3078 processor,
3079 reportUnusedDisableDirectives,
3080 root,
3081 rules,
3082 settings,
3083 overrides: overrideList = []
3084 },
3085 ctx
3086 ) {
3087 const extendList = Array.isArray(extend) ? extend : [extend];
3088 const ignorePattern = ignorePatterns && new IgnorePattern(
3089 Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
3090 ctx.matchBasePath
3091 );
3092
3093 // Flatten `extends`.
3094 for (const extendName of extendList.filter(Boolean)) {
3095 yield* this._loadExtends(extendName, ctx);
3096 }
3097
3098 // Load parser & plugins.
3099 const parser = parserName && this._loadParser(parserName, ctx);
3100 const plugins = pluginList && this._loadPlugins(pluginList, ctx);
3101
3102 // Yield pseudo config data for file extension processors.
3103 if (plugins) {
3104 yield* this._takeFileExtensionProcessors(plugins, ctx);
3105 }
3106
3107 // Yield the config data except `extends` and `overrides`.
3108 yield {
3109
3110 // Debug information.
3111 type: ctx.type,
3112 name: ctx.name,
3113 filePath: ctx.filePath,
3114
3115 // Config data.
3116 criteria: null,
3117 env,
3118 globals,
3119 ignorePattern,
3120 noInlineConfig,
3121 parser,
3122 parserOptions,
3123 plugins,
3124 processor,
3125 reportUnusedDisableDirectives,
3126 root,
3127 rules,
3128 settings
3129 };
3130
3131 // Flatten `overries`.
3132 for (let i = 0; i < overrideList.length; ++i) {
3133 yield* this._normalizeObjectConfigData(
3134 overrideList[i],
3135 { ...ctx, name: `${ctx.name}#overrides[${i}]` }
3136 );
3137 }
3138 }
3139
3140 /**
3141 * Load configs of an element in `extends`.
3142 * @param {string} extendName The name of a base config.
3143 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3144 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3145 * @private
3146 */
3147 _loadExtends(extendName, ctx) {
3148 debug$2("Loading {extends:%j} relative to %s", extendName, ctx.filePath);
3149 try {
3150 if (extendName.startsWith("eslint:")) {
3151 return this._loadExtendedBuiltInConfig(extendName, ctx);
3152 }
3153 if (extendName.startsWith("plugin:")) {
3154 return this._loadExtendedPluginConfig(extendName, ctx);
3155 }
3156 return this._loadExtendedShareableConfig(extendName, ctx);
3157 } catch (error) {
3158 error.message += `\nReferenced from: ${ctx.filePath || ctx.name}`;
3159 throw error;
3160 }
3161 }
3162
3163 /**
3164 * Load configs of an element in `extends`.
3165 * @param {string} extendName The name of a base config.
3166 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3167 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3168 * @private
3169 */
3170 _loadExtendedBuiltInConfig(extendName, ctx) {
3171 const {
3172 eslintAllPath,
3173 getEslintAllConfig,
3174 eslintRecommendedPath,
3175 getEslintRecommendedConfig
3176 } = internalSlotsMap$1.get(this);
3177
3178 if (extendName === "eslint:recommended") {
3179 const name = `${ctx.name} » ${extendName}`;
3180
3181 if (getEslintRecommendedConfig) {
3182 if (typeof getEslintRecommendedConfig !== "function") {
3183 throw new Error(`getEslintRecommendedConfig must be a function instead of '${getEslintRecommendedConfig}'`);
3184 }
3185 return this._normalizeConfigData(getEslintRecommendedConfig(), { ...ctx, name, filePath: "" });
3186 }
3187 return this._loadConfigData({
3188 ...ctx,
3189 name,
3190 filePath: eslintRecommendedPath
3191 });
3192 }
3193 if (extendName === "eslint:all") {
3194 const name = `${ctx.name} » ${extendName}`;
3195
3196 if (getEslintAllConfig) {
3197 if (typeof getEslintAllConfig !== "function") {
3198 throw new Error(`getEslintAllConfig must be a function instead of '${getEslintAllConfig}'`);
3199 }
3200 return this._normalizeConfigData(getEslintAllConfig(), { ...ctx, name, filePath: "" });
3201 }
3202 return this._loadConfigData({
3203 ...ctx,
3204 name,
3205 filePath: eslintAllPath
3206 });
3207 }
3208
3209 throw configInvalidError(extendName, ctx.name, "extend-config-missing");
3210 }
3211
3212 /**
3213 * Load configs of an element in `extends`.
3214 * @param {string} extendName The name of a base config.
3215 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3216 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3217 * @private
3218 */
3219 _loadExtendedPluginConfig(extendName, ctx) {
3220 const slashIndex = extendName.lastIndexOf("/");
3221
3222 if (slashIndex === -1) {
3223 throw configInvalidError(extendName, ctx.filePath, "plugin-invalid");
3224 }
3225
3226 const pluginName = extendName.slice("plugin:".length, slashIndex);
3227 const configName = extendName.slice(slashIndex + 1);
3228
3229 if (isFilePath(pluginName)) {
3230 throw new Error("'extends' cannot use a file path for plugins.");
3231 }
3232
3233 const plugin = this._loadPlugin(pluginName, ctx);
3234 const configData =
3235 plugin.definition &&
3236 plugin.definition.configs[configName];
3237
3238 if (configData) {
3239 return this._normalizeConfigData(configData, {
3240 ...ctx,
3241 filePath: plugin.filePath || ctx.filePath,
3242 name: `${ctx.name} » plugin:${plugin.id}/${configName}`
3243 });
3244 }
3245
3246 throw plugin.error || configInvalidError(extendName, ctx.filePath, "extend-config-missing");
3247 }
3248
3249 /**
3250 * Load configs of an element in `extends`.
3251 * @param {string} extendName The name of a base config.
3252 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3253 * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
3254 * @private
3255 */
3256 _loadExtendedShareableConfig(extendName, ctx) {
3257 const { cwd, resolver } = internalSlotsMap$1.get(this);
3258 const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
3259 let request;
3260
3261 if (isFilePath(extendName)) {
3262 request = extendName;
3263 } else if (extendName.startsWith(".")) {
3264 request = `./${extendName}`; // For backward compatibility. A ton of tests depended on this behavior.
3265 } else {
3266 request = normalizePackageName(
3267 extendName,
3268 "eslint-config"
3269 );
3270 }
3271
3272 let filePath;
3273
3274 try {
3275 filePath = resolver.resolve(request, relativeTo);
3276 } catch (error) {
3277 /* istanbul ignore else */
3278 if (error && error.code === "MODULE_NOT_FOUND") {
3279 throw configInvalidError(extendName, ctx.filePath, "extend-config-missing");
3280 }
3281 throw error;
3282 }
3283
3284 writeDebugLogForLoading(request, relativeTo, filePath);
3285 return this._loadConfigData({
3286 ...ctx,
3287 filePath,
3288 name: `${ctx.name} » ${request}`
3289 });
3290 }
3291
3292 /**
3293 * Load given plugins.
3294 * @param {string[]} names The plugin names to load.
3295 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3296 * @returns {Record<string,DependentPlugin>} The loaded parser.
3297 * @private
3298 */
3299 _loadPlugins(names, ctx) {
3300 return names.reduce((map, name) => {
3301 if (isFilePath(name)) {
3302 throw new Error("Plugins array cannot includes file paths.");
3303 }
3304 const plugin = this._loadPlugin(name, ctx);
3305
3306 map[plugin.id] = plugin;
3307
3308 return map;
3309 }, {});
3310 }
3311
3312 /**
3313 * Load a given parser.
3314 * @param {string} nameOrPath The package name or the path to a parser file.
3315 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3316 * @returns {DependentParser} The loaded parser.
3317 */
3318 _loadParser(nameOrPath, ctx) {
3319 debug$2("Loading parser %j from %s", nameOrPath, ctx.filePath);
3320
3321 const { cwd, resolver } = internalSlotsMap$1.get(this);
3322 const relativeTo = ctx.filePath || path__default["default"].join(cwd, "__placeholder__.js");
3323
3324 try {
3325 const filePath = resolver.resolve(nameOrPath, relativeTo);
3326
3327 writeDebugLogForLoading(nameOrPath, relativeTo, filePath);
3328
3329 return new ConfigDependency({
3330 definition: require$1(filePath),
3331 filePath,
3332 id: nameOrPath,
3333 importerName: ctx.name,
3334 importerPath: ctx.filePath
3335 });
3336 } catch (error) {
3337
3338 // If the parser name is "espree", load the espree of ESLint.
3339 if (nameOrPath === "espree") {
3340 debug$2("Fallback espree.");
3341 return new ConfigDependency({
3342 definition: require$1("espree"),
3343 filePath: require$1.resolve("espree"),
3344 id: nameOrPath,
3345 importerName: ctx.name,
3346 importerPath: ctx.filePath
3347 });
3348 }
3349
3350 debug$2("Failed to load parser '%s' declared in '%s'.", nameOrPath, ctx.name);
3351 error.message = `Failed to load parser '${nameOrPath}' declared in '${ctx.name}': ${error.message}`;
3352
3353 return new ConfigDependency({
3354 error,
3355 id: nameOrPath,
3356 importerName: ctx.name,
3357 importerPath: ctx.filePath
3358 });
3359 }
3360 }
3361
3362 /**
3363 * Load a given plugin.
3364 * @param {string} name The plugin name to load.
3365 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3366 * @returns {DependentPlugin} The loaded plugin.
3367 * @private
3368 */
3369 _loadPlugin(name, ctx) {
3370 debug$2("Loading plugin %j from %s", name, ctx.filePath);
3371
3372 const { additionalPluginPool, resolver } = internalSlotsMap$1.get(this);
3373 const request = normalizePackageName(name, "eslint-plugin");
3374 const id = getShorthandName(request, "eslint-plugin");
3375 const relativeTo = path__default["default"].join(ctx.pluginBasePath, "__placeholder__.js");
3376
3377 if (name.match(/\s+/u)) {
3378 const error = Object.assign(
3379 new Error(`Whitespace found in plugin name '${name}'`),
3380 {
3381 messageTemplate: "whitespace-found",
3382 messageData: { pluginName: request }
3383 }
3384 );
3385
3386 return new ConfigDependency({
3387 error,
3388 id,
3389 importerName: ctx.name,
3390 importerPath: ctx.filePath
3391 });
3392 }
3393
3394 // Check for additional pool.
3395 const plugin =
3396 additionalPluginPool.get(request) ||
3397 additionalPluginPool.get(id);
3398
3399 if (plugin) {
3400 return new ConfigDependency({
3401 definition: normalizePlugin(plugin),
3402 original: plugin,
3403 filePath: "", // It's unknown where the plugin came from.
3404 id,
3405 importerName: ctx.name,
3406 importerPath: ctx.filePath
3407 });
3408 }
3409
3410 let filePath;
3411 let error;
3412
3413 try {
3414 filePath = resolver.resolve(request, relativeTo);
3415 } catch (resolveError) {
3416 error = resolveError;
3417 /* istanbul ignore else */
3418 if (error && error.code === "MODULE_NOT_FOUND") {
3419 error.messageTemplate = "plugin-missing";
3420 error.messageData = {
3421 pluginName: request,
3422 resolvePluginsRelativeTo: ctx.pluginBasePath,
3423 importerName: ctx.name
3424 };
3425 }
3426 }
3427
3428 if (filePath) {
3429 try {
3430 writeDebugLogForLoading(request, relativeTo, filePath);
3431
3432 const startTime = Date.now();
3433 const pluginDefinition = require$1(filePath);
3434
3435 debug$2(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
3436
3437 return new ConfigDependency({
3438 definition: normalizePlugin(pluginDefinition),
3439 original: pluginDefinition,
3440 filePath,
3441 id,
3442 importerName: ctx.name,
3443 importerPath: ctx.filePath
3444 });
3445 } catch (loadError) {
3446 error = loadError;
3447 }
3448 }
3449
3450 debug$2("Failed to load plugin '%s' declared in '%s'.", name, ctx.name);
3451 error.message = `Failed to load plugin '${name}' declared in '${ctx.name}': ${error.message}`;
3452 return new ConfigDependency({
3453 error,
3454 id,
3455 importerName: ctx.name,
3456 importerPath: ctx.filePath
3457 });
3458 }
3459
3460 /**
3461 * Take file expression processors as config array elements.
3462 * @param {Record<string,DependentPlugin>} plugins The plugin definitions.
3463 * @param {ConfigArrayFactoryLoadingContext} ctx The loading context.
3464 * @returns {IterableIterator<ConfigArrayElement>} The config array elements of file expression processors.
3465 * @private
3466 */
3467 *_takeFileExtensionProcessors(plugins, ctx) {
3468 for (const pluginId of Object.keys(plugins)) {
3469 const processors =
3470 plugins[pluginId] &&
3471 plugins[pluginId].definition &&
3472 plugins[pluginId].definition.processors;
3473
3474 if (!processors) {
3475 continue;
3476 }
3477
3478 for (const processorId of Object.keys(processors)) {
3479 if (processorId.startsWith(".")) {
3480 yield* this._normalizeObjectConfigData(
3481 {
3482 files: [`*${processorId}`],
3483 processor: `${pluginId}/${processorId}`
3484 },
3485 {
3486 ...ctx,
3487 type: "implicit-processor",
3488 name: `${ctx.name}#processors["${pluginId}/${processorId}"]`
3489 }
3490 );
3491 }
3492 }
3493 }
3494 }
3495}
3496
3497/**
3498 * @fileoverview `CascadingConfigArrayFactory` class.
3499 *
3500 * `CascadingConfigArrayFactory` class has a responsibility:
3501 *
3502 * 1. Handles cascading of config files.
3503 *
3504 * It provides two methods:
3505 *
3506 * - `getConfigArrayForFile(filePath)`
3507 * Get the corresponded configuration of a given file. This method doesn't
3508 * throw even if the given file didn't exist.
3509 * - `clearCache()`
3510 * Clear the internal cache. You have to call this method when
3511 * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
3512 * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
3513 *
3514 * @author Toru Nagashima <https://github.com/mysticatea>
3515 */
3516
3517const debug$1 = debugOrig__default["default"]("eslintrc:cascading-config-array-factory");
3518
3519//------------------------------------------------------------------------------
3520// Helpers
3521//------------------------------------------------------------------------------
3522
3523// Define types for VSCode IntelliSense.
3524/** @typedef {import("./shared/types").ConfigData} ConfigData */
3525/** @typedef {import("./shared/types").Parser} Parser */
3526/** @typedef {import("./shared/types").Plugin} Plugin */
3527/** @typedef {import("./shared/types").Rule} Rule */
3528/** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
3529
3530/**
3531 * @typedef {Object} CascadingConfigArrayFactoryOptions
3532 * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
3533 * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
3534 * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
3535 * @property {string} [cwd] The base directory to start lookup.
3536 * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
3537 * @property {string[]} [rulePaths] The value of `--rulesdir` option.
3538 * @property {string} [specificConfigPath] The value of `--config` option.
3539 * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
3540 * @property {Function} loadRules The function to use to load rules.
3541 * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
3542 * @property {Object} [resolver=ModuleResolver] The module resolver object.
3543 * @property {string} eslintAllPath The path to the definitions for eslint:all.
3544 * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
3545 * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
3546 * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
3547 */
3548
3549/**
3550 * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
3551 * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
3552 * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
3553 * @property {ConfigArray} cliConfigArray The config array of CLI options.
3554 * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
3555 * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
3556 * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
3557 * @property {string} cwd The base directory to start lookup.
3558 * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
3559 * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
3560 * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
3561 * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
3562 * @property {boolean} useEslintrc if `false` then it doesn't load config files.
3563 * @property {Function} loadRules The function to use to load rules.
3564 * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
3565 * @property {Object} [resolver=ModuleResolver] The module resolver object.
3566 * @property {string} eslintAllPath The path to the definitions for eslint:all.
3567 * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
3568 * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
3569 * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
3570 */
3571
3572/** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
3573const internalSlotsMap = new WeakMap();
3574
3575/**
3576 * Create the config array from `baseConfig` and `rulePaths`.
3577 * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
3578 * @returns {ConfigArray} The config array of the base configs.
3579 */
3580function createBaseConfigArray({
3581 configArrayFactory,
3582 baseConfigData,
3583 rulePaths,
3584 cwd,
3585 loadRules
3586}) {
3587 const baseConfigArray = configArrayFactory.create(
3588 baseConfigData,
3589 { name: "BaseConfig" }
3590 );
3591
3592 /*
3593 * Create the config array element for the default ignore patterns.
3594 * This element has `ignorePattern` property that ignores the default
3595 * patterns in the current working directory.
3596 */
3597 baseConfigArray.unshift(configArrayFactory.create(
3598 { ignorePatterns: IgnorePattern.DefaultPatterns },
3599 { name: "DefaultIgnorePattern" }
3600 )[0]);
3601
3602 /*
3603 * Load rules `--rulesdir` option as a pseudo plugin.
3604 * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
3605 * the rule's options with only information in the config array.
3606 */
3607 if (rulePaths && rulePaths.length > 0) {
3608 baseConfigArray.push({
3609 type: "config",
3610 name: "--rulesdir",
3611 filePath: "",
3612 plugins: {
3613 "": new ConfigDependency({
3614 definition: {
3615 rules: rulePaths.reduce(
3616 (map, rulesPath) => Object.assign(
3617 map,
3618 loadRules(rulesPath, cwd)
3619 ),
3620 {}
3621 )
3622 },
3623 filePath: "",
3624 id: "",
3625 importerName: "--rulesdir",
3626 importerPath: ""
3627 })
3628 }
3629 });
3630 }
3631
3632 return baseConfigArray;
3633}
3634
3635/**
3636 * Create the config array from CLI options.
3637 * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
3638 * @returns {ConfigArray} The config array of the base configs.
3639 */
3640function createCLIConfigArray({
3641 cliConfigData,
3642 configArrayFactory,
3643 cwd,
3644 ignorePath,
3645 specificConfigPath
3646}) {
3647 const cliConfigArray = configArrayFactory.create(
3648 cliConfigData,
3649 { name: "CLIOptions" }
3650 );
3651
3652 cliConfigArray.unshift(
3653 ...(ignorePath
3654 ? configArrayFactory.loadESLintIgnore(ignorePath)
3655 : configArrayFactory.loadDefaultESLintIgnore())
3656 );
3657
3658 if (specificConfigPath) {
3659 cliConfigArray.unshift(
3660 ...configArrayFactory.loadFile(
3661 specificConfigPath,
3662 { name: "--config", basePath: cwd }
3663 )
3664 );
3665 }
3666
3667 return cliConfigArray;
3668}
3669
3670/**
3671 * The error type when there are files matched by a glob, but all of them have been ignored.
3672 */
3673class ConfigurationNotFoundError extends Error {
3674
3675 // eslint-disable-next-line jsdoc/require-description
3676 /**
3677 * @param {string} directoryPath The directory path.
3678 */
3679 constructor(directoryPath) {
3680 super(`No ESLint configuration found in ${directoryPath}.`);
3681 this.messageTemplate = "no-config-found";
3682 this.messageData = { directoryPath };
3683 }
3684}
3685
3686/**
3687 * This class provides the functionality that enumerates every file which is
3688 * matched by given glob patterns and that configuration.
3689 */
3690class CascadingConfigArrayFactory {
3691
3692 /**
3693 * Initialize this enumerator.
3694 * @param {CascadingConfigArrayFactoryOptions} options The options.
3695 */
3696 constructor({
3697 additionalPluginPool = new Map(),
3698 baseConfig: baseConfigData = null,
3699 cliConfig: cliConfigData = null,
3700 cwd = process.cwd(),
3701 ignorePath,
3702 resolvePluginsRelativeTo,
3703 rulePaths = [],
3704 specificConfigPath = null,
3705 useEslintrc = true,
3706 builtInRules = new Map(),
3707 loadRules,
3708 resolver,
3709 eslintRecommendedPath,
3710 getEslintRecommendedConfig,
3711 eslintAllPath,
3712 getEslintAllConfig
3713 } = {}) {
3714 const configArrayFactory = new ConfigArrayFactory({
3715 additionalPluginPool,
3716 cwd,
3717 resolvePluginsRelativeTo,
3718 builtInRules,
3719 resolver,
3720 eslintRecommendedPath,
3721 getEslintRecommendedConfig,
3722 eslintAllPath,
3723 getEslintAllConfig
3724 });
3725
3726 internalSlotsMap.set(this, {
3727 baseConfigArray: createBaseConfigArray({
3728 baseConfigData,
3729 configArrayFactory,
3730 cwd,
3731 rulePaths,
3732 loadRules
3733 }),
3734 baseConfigData,
3735 cliConfigArray: createCLIConfigArray({
3736 cliConfigData,
3737 configArrayFactory,
3738 cwd,
3739 ignorePath,
3740 specificConfigPath
3741 }),
3742 cliConfigData,
3743 configArrayFactory,
3744 configCache: new Map(),
3745 cwd,
3746 finalizeCache: new WeakMap(),
3747 ignorePath,
3748 rulePaths,
3749 specificConfigPath,
3750 useEslintrc,
3751 builtInRules,
3752 loadRules
3753 });
3754 }
3755
3756 /**
3757 * The path to the current working directory.
3758 * This is used by tests.
3759 * @type {string}
3760 */
3761 get cwd() {
3762 const { cwd } = internalSlotsMap.get(this);
3763
3764 return cwd;
3765 }
3766
3767 /**
3768 * Get the config array of a given file.
3769 * If `filePath` was not given, it returns the config which contains only
3770 * `baseConfigData` and `cliConfigData`.
3771 * @param {string} [filePath] The file path to a file.
3772 * @param {Object} [options] The options.
3773 * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
3774 * @returns {ConfigArray} The config array of the file.
3775 */
3776 getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
3777 const {
3778 baseConfigArray,
3779 cliConfigArray,
3780 cwd
3781 } = internalSlotsMap.get(this);
3782
3783 if (!filePath) {
3784 return new ConfigArray(...baseConfigArray, ...cliConfigArray);
3785 }
3786
3787 const directoryPath = path__default["default"].dirname(path__default["default"].resolve(cwd, filePath));
3788
3789 debug$1(`Load config files for ${directoryPath}.`);
3790
3791 return this._finalizeConfigArray(
3792 this._loadConfigInAncestors(directoryPath),
3793 directoryPath,
3794 ignoreNotFoundError
3795 );
3796 }
3797
3798 /**
3799 * Set the config data to override all configs.
3800 * Require to call `clearCache()` method after this method is called.
3801 * @param {ConfigData} configData The config data to override all configs.
3802 * @returns {void}
3803 */
3804 setOverrideConfig(configData) {
3805 const slots = internalSlotsMap.get(this);
3806
3807 slots.cliConfigData = configData;
3808 }
3809
3810 /**
3811 * Clear config cache.
3812 * @returns {void}
3813 */
3814 clearCache() {
3815 const slots = internalSlotsMap.get(this);
3816
3817 slots.baseConfigArray = createBaseConfigArray(slots);
3818 slots.cliConfigArray = createCLIConfigArray(slots);
3819 slots.configCache.clear();
3820 }
3821
3822 /**
3823 * Load and normalize config files from the ancestor directories.
3824 * @param {string} directoryPath The path to a leaf directory.
3825 * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
3826 * @returns {ConfigArray} The loaded config.
3827 * @private
3828 */
3829 _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
3830 const {
3831 baseConfigArray,
3832 configArrayFactory,
3833 configCache,
3834 cwd,
3835 useEslintrc
3836 } = internalSlotsMap.get(this);
3837
3838 if (!useEslintrc) {
3839 return baseConfigArray;
3840 }
3841
3842 let configArray = configCache.get(directoryPath);
3843
3844 // Hit cache.
3845 if (configArray) {
3846 debug$1(`Cache hit: ${directoryPath}.`);
3847 return configArray;
3848 }
3849 debug$1(`No cache found: ${directoryPath}.`);
3850
3851 const homePath = os__default["default"].homedir();
3852
3853 // Consider this is root.
3854 if (directoryPath === homePath && cwd !== homePath) {
3855 debug$1("Stop traversing because of considered root.");
3856 if (configsExistInSubdirs) {
3857 const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
3858
3859 if (filePath) {
3860 emitDeprecationWarning(
3861 filePath,
3862 "ESLINT_PERSONAL_CONFIG_SUPPRESS"
3863 );
3864 }
3865 }
3866 return this._cacheConfig(directoryPath, baseConfigArray);
3867 }
3868
3869 // Load the config on this directory.
3870 try {
3871 configArray = configArrayFactory.loadInDirectory(directoryPath);
3872 } catch (error) {
3873 /* istanbul ignore next */
3874 if (error.code === "EACCES") {
3875 debug$1("Stop traversing because of 'EACCES' error.");
3876 return this._cacheConfig(directoryPath, baseConfigArray);
3877 }
3878 throw error;
3879 }
3880
3881 if (configArray.length > 0 && configArray.isRoot()) {
3882 debug$1("Stop traversing because of 'root:true'.");
3883 configArray.unshift(...baseConfigArray);
3884 return this._cacheConfig(directoryPath, configArray);
3885 }
3886
3887 // Load from the ancestors and merge it.
3888 const parentPath = path__default["default"].dirname(directoryPath);
3889 const parentConfigArray = parentPath && parentPath !== directoryPath
3890 ? this._loadConfigInAncestors(
3891 parentPath,
3892 configsExistInSubdirs || configArray.length > 0
3893 )
3894 : baseConfigArray;
3895
3896 if (configArray.length > 0) {
3897 configArray.unshift(...parentConfigArray);
3898 } else {
3899 configArray = parentConfigArray;
3900 }
3901
3902 // Cache and return.
3903 return this._cacheConfig(directoryPath, configArray);
3904 }
3905
3906 /**
3907 * Freeze and cache a given config.
3908 * @param {string} directoryPath The path to a directory as a cache key.
3909 * @param {ConfigArray} configArray The config array as a cache value.
3910 * @returns {ConfigArray} The `configArray` (frozen).
3911 */
3912 _cacheConfig(directoryPath, configArray) {
3913 const { configCache } = internalSlotsMap.get(this);
3914
3915 Object.freeze(configArray);
3916 configCache.set(directoryPath, configArray);
3917
3918 return configArray;
3919 }
3920
3921 /**
3922 * Finalize a given config array.
3923 * Concatenate `--config` and other CLI options.
3924 * @param {ConfigArray} configArray The parent config array.
3925 * @param {string} directoryPath The path to the leaf directory to find config files.
3926 * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
3927 * @returns {ConfigArray} The loaded config.
3928 * @private
3929 */
3930 _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
3931 const {
3932 cliConfigArray,
3933 configArrayFactory,
3934 finalizeCache,
3935 useEslintrc,
3936 builtInRules
3937 } = internalSlotsMap.get(this);
3938
3939 let finalConfigArray = finalizeCache.get(configArray);
3940
3941 if (!finalConfigArray) {
3942 finalConfigArray = configArray;
3943
3944 // Load the personal config if there are no regular config files.
3945 if (
3946 useEslintrc &&
3947 configArray.every(c => !c.filePath) &&
3948 cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
3949 ) {
3950 const homePath = os__default["default"].homedir();
3951
3952 debug$1("Loading the config file of the home directory:", homePath);
3953
3954 const personalConfigArray = configArrayFactory.loadInDirectory(
3955 homePath,
3956 { name: "PersonalConfig" }
3957 );
3958
3959 if (
3960 personalConfigArray.length > 0 &&
3961 !directoryPath.startsWith(homePath)
3962 ) {
3963 const lastElement =
3964 personalConfigArray[personalConfigArray.length - 1];
3965
3966 emitDeprecationWarning(
3967 lastElement.filePath,
3968 "ESLINT_PERSONAL_CONFIG_LOAD"
3969 );
3970 }
3971
3972 finalConfigArray = finalConfigArray.concat(personalConfigArray);
3973 }
3974
3975 // Apply CLI options.
3976 if (cliConfigArray.length > 0) {
3977 finalConfigArray = finalConfigArray.concat(cliConfigArray);
3978 }
3979
3980 // Validate rule settings and environments.
3981 const validator = new ConfigValidator({
3982 builtInRules
3983 });
3984
3985 validator.validateConfigArray(finalConfigArray);
3986
3987 // Cache it.
3988 Object.freeze(finalConfigArray);
3989 finalizeCache.set(configArray, finalConfigArray);
3990
3991 debug$1(
3992 "Configuration was determined: %o on %s",
3993 finalConfigArray,
3994 directoryPath
3995 );
3996 }
3997
3998 // At least one element (the default ignore patterns) exists.
3999 if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
4000 throw new ConfigurationNotFoundError(directoryPath);
4001 }
4002
4003 return finalConfigArray;
4004 }
4005}
4006
4007/**
4008 * @fileoverview Compatibility class for flat config.
4009 * @author Nicholas C. Zakas
4010 */
4011
4012//-----------------------------------------------------------------------------
4013// Helpers
4014//-----------------------------------------------------------------------------
4015
4016/** @typedef {import("../../shared/types").Environment} Environment */
4017/** @typedef {import("../../shared/types").Processor} Processor */
4018
4019const debug = debugOrig__default["default"]("eslintrc:flat-compat");
4020const cafactory = Symbol("cafactory");
4021
4022/**
4023 * Translates an ESLintRC-style config object into a flag-config-style config
4024 * object.
4025 * @param {Object} eslintrcConfig An ESLintRC-style config object.
4026 * @param {Object} options Options to help translate the config.
4027 * @param {string} options.resolveConfigRelativeTo To the directory to resolve
4028 * configs from.
4029 * @param {string} options.resolvePluginsRelativeTo The directory to resolve
4030 * plugins from.
4031 * @param {ReadOnlyMap<string,Environment>} options.pluginEnvironments A map of plugin environment
4032 * names to objects.
4033 * @param {ReadOnlyMap<string,Processor>} options.pluginProcessors A map of plugin processor
4034 * names to objects.
4035 * @returns {Object} A flag-config-style config object.
4036 */
4037function translateESLintRC(eslintrcConfig, {
4038 resolveConfigRelativeTo,
4039 resolvePluginsRelativeTo,
4040 pluginEnvironments,
4041 pluginProcessors
4042}) {
4043
4044 const flatConfig = {};
4045 const configs = [];
4046 const languageOptions = {};
4047 const linterOptions = {};
4048 const keysToCopy = ["settings", "rules", "processor"];
4049 const languageOptionsKeysToCopy = ["globals", "parser", "parserOptions"];
4050 const linterOptionsKeysToCopy = ["noInlineConfig", "reportUnusedDisableDirectives"];
4051
4052 // copy over simple translations
4053 for (const key of keysToCopy) {
4054 if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
4055 flatConfig[key] = eslintrcConfig[key];
4056 }
4057 }
4058
4059 // copy over languageOptions
4060 for (const key of languageOptionsKeysToCopy) {
4061 if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
4062
4063 // create the languageOptions key in the flat config
4064 flatConfig.languageOptions = languageOptions;
4065
4066 if (key === "parser") {
4067 debug(`Resolving parser '${languageOptions[key]}' relative to ${resolveConfigRelativeTo}`);
4068
4069 if (eslintrcConfig[key].error) {
4070 throw eslintrcConfig[key].error;
4071 }
4072
4073 languageOptions[key] = eslintrcConfig[key].definition;
4074 continue;
4075 }
4076
4077 // clone any object values that are in the eslintrc config
4078 if (eslintrcConfig[key] && typeof eslintrcConfig[key] === "object") {
4079 languageOptions[key] = {
4080 ...eslintrcConfig[key]
4081 };
4082 } else {
4083 languageOptions[key] = eslintrcConfig[key];
4084 }
4085 }
4086 }
4087
4088 // copy over linterOptions
4089 for (const key of linterOptionsKeysToCopy) {
4090 if (key in eslintrcConfig && typeof eslintrcConfig[key] !== "undefined") {
4091 flatConfig.linterOptions = linterOptions;
4092 linterOptions[key] = eslintrcConfig[key];
4093 }
4094 }
4095
4096 // move ecmaVersion a level up
4097 if (languageOptions.parserOptions) {
4098
4099 if ("ecmaVersion" in languageOptions.parserOptions) {
4100 languageOptions.ecmaVersion = languageOptions.parserOptions.ecmaVersion;
4101 delete languageOptions.parserOptions.ecmaVersion;
4102 }
4103
4104 if ("sourceType" in languageOptions.parserOptions) {
4105 languageOptions.sourceType = languageOptions.parserOptions.sourceType;
4106 delete languageOptions.parserOptions.sourceType;
4107 }
4108
4109 // check to see if we even need parserOptions anymore and remove it if not
4110 if (Object.keys(languageOptions.parserOptions).length === 0) {
4111 delete languageOptions.parserOptions;
4112 }
4113 }
4114
4115 // overrides
4116 if (eslintrcConfig.criteria) {
4117 flatConfig.files = [absoluteFilePath => eslintrcConfig.criteria.test(absoluteFilePath)];
4118 }
4119
4120 // translate plugins
4121 if (eslintrcConfig.plugins && typeof eslintrcConfig.plugins === "object") {
4122 debug(`Translating plugins: ${eslintrcConfig.plugins}`);
4123
4124 flatConfig.plugins = {};
4125
4126 for (const pluginName of Object.keys(eslintrcConfig.plugins)) {
4127
4128 debug(`Translating plugin: ${pluginName}`);
4129 debug(`Resolving plugin '${pluginName} relative to ${resolvePluginsRelativeTo}`);
4130
4131 const { original: plugin, error } = eslintrcConfig.plugins[pluginName];
4132
4133 if (error) {
4134 throw error;
4135 }
4136
4137 flatConfig.plugins[pluginName] = plugin;
4138
4139 // create a config for any processors
4140 if (plugin.processors) {
4141 for (const processorName of Object.keys(plugin.processors)) {
4142 if (processorName.startsWith(".")) {
4143 debug(`Assigning processor: ${pluginName}/${processorName}`);
4144
4145 configs.unshift({
4146 files: [`**/*${processorName}`],
4147 processor: pluginProcessors.get(`${pluginName}/${processorName}`)
4148 });
4149 }
4150
4151 }
4152 }
4153 }
4154 }
4155
4156 // translate env - must come after plugins
4157 if (eslintrcConfig.env && typeof eslintrcConfig.env === "object") {
4158 for (const envName of Object.keys(eslintrcConfig.env)) {
4159
4160 // only add environments that are true
4161 if (eslintrcConfig.env[envName]) {
4162 debug(`Translating environment: ${envName}`);
4163
4164 if (environments.has(envName)) {
4165
4166 // built-in environments should be defined first
4167 configs.unshift(...translateESLintRC({
4168 criteria: eslintrcConfig.criteria,
4169 ...environments.get(envName)
4170 }, {
4171 resolveConfigRelativeTo,
4172 resolvePluginsRelativeTo
4173 }));
4174 } else if (pluginEnvironments.has(envName)) {
4175
4176 // if the environment comes from a plugin, it should come after the plugin config
4177 configs.push(...translateESLintRC({
4178 criteria: eslintrcConfig.criteria,
4179 ...pluginEnvironments.get(envName)
4180 }, {
4181 resolveConfigRelativeTo,
4182 resolvePluginsRelativeTo
4183 }));
4184 }
4185 }
4186 }
4187 }
4188
4189 // only add if there are actually keys in the config
4190 if (Object.keys(flatConfig).length > 0) {
4191 configs.push(flatConfig);
4192 }
4193
4194 return configs;
4195}
4196
4197
4198//-----------------------------------------------------------------------------
4199// Exports
4200//-----------------------------------------------------------------------------
4201
4202/**
4203 * A compatibility class for working with configs.
4204 */
4205class FlatCompat {
4206
4207 constructor({
4208 baseDirectory = process.cwd(),
4209 resolvePluginsRelativeTo = baseDirectory,
4210 recommendedConfig,
4211 allConfig
4212 } = {}) {
4213 this.baseDirectory = baseDirectory;
4214 this.resolvePluginsRelativeTo = resolvePluginsRelativeTo;
4215 this[cafactory] = new ConfigArrayFactory({
4216 cwd: baseDirectory,
4217 resolvePluginsRelativeTo,
4218 getEslintAllConfig: () => {
4219
4220 if (!allConfig) {
4221 throw new TypeError("Missing parameter 'allConfig' in FlatCompat constructor.");
4222 }
4223
4224 return allConfig;
4225 },
4226 getEslintRecommendedConfig: () => {
4227
4228 if (!recommendedConfig) {
4229 throw new TypeError("Missing parameter 'recommendedConfig' in FlatCompat constructor.");
4230 }
4231
4232 return recommendedConfig;
4233 }
4234 });
4235 }
4236
4237 /**
4238 * Translates an ESLintRC-style config into a flag-config-style config.
4239 * @param {Object} eslintrcConfig The ESLintRC-style config object.
4240 * @returns {Object} A flag-config-style config object.
4241 */
4242 config(eslintrcConfig) {
4243 const eslintrcArray = this[cafactory].create(eslintrcConfig, {
4244 basePath: this.baseDirectory
4245 });
4246
4247 const flatArray = [];
4248 let hasIgnorePatterns = false;
4249
4250 eslintrcArray.forEach(configData => {
4251 if (configData.type === "config") {
4252 hasIgnorePatterns = hasIgnorePatterns || configData.ignorePattern;
4253 flatArray.push(...translateESLintRC(configData, {
4254 resolveConfigRelativeTo: path__default["default"].join(this.baseDirectory, "__placeholder.js"),
4255 resolvePluginsRelativeTo: path__default["default"].join(this.resolvePluginsRelativeTo, "__placeholder.js"),
4256 pluginEnvironments: eslintrcArray.pluginEnvironments,
4257 pluginProcessors: eslintrcArray.pluginProcessors
4258 }));
4259 }
4260 });
4261
4262 // combine ignorePatterns to emulate ESLintRC behavior better
4263 if (hasIgnorePatterns) {
4264 flatArray.unshift({
4265 ignores: [filePath => {
4266
4267 // Compute the final config for this file.
4268 // This filters config array elements by `files`/`excludedFiles` then merges the elements.
4269 const finalConfig = eslintrcArray.extractConfig(filePath);
4270
4271 // Test the `ignorePattern` properties of the final config.
4272 return Boolean(finalConfig.ignores) && finalConfig.ignores(filePath);
4273 }]
4274 });
4275 }
4276
4277 return flatArray;
4278 }
4279
4280 /**
4281 * Translates the `env` section of an ESLintRC-style config.
4282 * @param {Object} envConfig The `env` section of an ESLintRC config.
4283 * @returns {Object[]} An array of flag-config objects representing the environments.
4284 */
4285 env(envConfig) {
4286 return this.config({
4287 env: envConfig
4288 });
4289 }
4290
4291 /**
4292 * Translates the `extends` section of an ESLintRC-style config.
4293 * @param {...string} configsToExtend The names of the configs to load.
4294 * @returns {Object[]} An array of flag-config objects representing the config.
4295 */
4296 extends(...configsToExtend) {
4297 return this.config({
4298 extends: configsToExtend
4299 });
4300 }
4301
4302 /**
4303 * Translates the `plugins` section of an ESLintRC-style config.
4304 * @param {...string} plugins The names of the plugins to load.
4305 * @returns {Object[]} An array of flag-config objects representing the plugins.
4306 */
4307 plugins(...plugins) {
4308 return this.config({
4309 plugins
4310 });
4311 }
4312}
4313
4314/**
4315 * @fileoverview Package exports for @eslint/eslintrc
4316 * @author Nicholas C. Zakas
4317 */
4318
4319//-----------------------------------------------------------------------------
4320// Exports
4321//-----------------------------------------------------------------------------
4322
4323const Legacy = {
4324 ConfigArray,
4325 createConfigArrayFactoryContext: createContext,
4326 CascadingConfigArrayFactory,
4327 ConfigArrayFactory,
4328 ConfigDependency,
4329 ExtractedConfig,
4330 IgnorePattern,
4331 OverrideTester,
4332 getUsedExtractedConfigs,
4333 environments,
4334
4335 // shared
4336 ConfigOps,
4337 ConfigValidator,
4338 ModuleResolver,
4339 naming
4340};
4341
4342exports.FlatCompat = FlatCompat;
4343exports.Legacy = Legacy;
4344//# sourceMappingURL=eslintrc.cjs.map
Note: See TracBrowser for help on using the repository browser.